diff --git a/.github/workflows/build-and-release-single-package.yml b/.github/workflows/build-and-release-single-package.yml new file mode 100644 index 0000000000..cdde1e8acf --- /dev/null +++ b/.github/workflows/build-and-release-single-package.yml @@ -0,0 +1,162 @@ +name: Build and release one taipy sub-package + +on: + workflow_dispatch: + inputs: + internal_dep_on_pypi: + description: "Point taipy internal dependencies to Pypi? If false it will point to the github .tar.gz release file" + default: "false" + required: true + release_type: + description: "The type of release to be made (dev or production)" + default: "dev" + required: true + target_version: + description: "The version of the package to be released" + required: true + target_package: + description: "The package to be released (gui, config, core, rest, templates, taipy)" + required: true + +jobs: + fetch-versions: + runs-on: ubuntu-latest + outputs: + config_VERSION: ${{ steps.version-setup.outputs.config_VERSION }} + core_VERSION: ${{ steps.version-setup.outputs.core_VERSION }} + gui_VERSION: ${{ steps.version-setup.outputs.gui_VERSION }} + rest_VERSION: ${{ steps.version-setup.outputs.rest_VERSION }} + templates_VERSION: ${{ steps.version-setup.outputs.templates_VERSION }} + VERSION: ${{ steps.version-setup.outputs.VERSION }} + NEW_VERSION: ${{ steps.version-setup.outputs.NEW_VERSION }} + steps: + - uses: actions/checkout@v4 + - name: Extract branch name + shell: bash + run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extract_branch + + - name: Setup Version + id: version-setup + run: | + python tools/release/fetch_latest_versions.py ${{ github.event.inputs.release_type }} ${{ github.event.inputs.internal_dep_on_pypi }} ${{ github.event.inputs.target_version }} >> $GITHUB_OUTPUT + + build-and-release-package: + needs: [fetch-versions] + timeout-minutes: 20 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ssh-key: ${{secrets.DEPLOY_KEY}} + - uses: actions/setup-python@v4 + with: + python-version: 3.9 + - uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Extract commit hash + shell: bash + run: echo "HASH=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + id: extract_hash + + - name: Set Build Variables + id: set-variables + run: | + if [ " ${{ github.event.inputs.target_package }}" == "config" ]; then + echo "package_version=${{needs.fetch-versions.outputs.config_VERSION}}" >> $GITHUB_OUTPUT + echo "package_dir=./taipy/config" >> $GITHUB_OUTPUT + echo "release_name=${{needs.fetch-versions.outputs.config_VERSION}}-config" >> $GITHUB_OUTPUT + echo "tar_path=./dist/${{ github.event.repository.name }}-config-${{needs.fetch-versions.outputs.config_VERSION}}.tar.gz" >> $GITHUB_OUTPUT + elif [ " ${{ github.event.inputs.target_package }}" == "core" ]; then + echo "package_version=${{needs.fetch-versions.outputs.core_VERSION}}" >> $GITHUB_OUTPUT + echo "package_dir=./taipy/core" >> $GITHUB_OUTPUT + echo "release_name=${{needs.fetch-versions.outputs.core_VERSION}}-core" >> $GITHUB_OUTPUT + echo "tar_path=./dist/${{ github.event.repository.name }}-core-${{needs.fetch-versions.outputs.core_VERSION}}.tar.gz" >> $GITHUB_OUTPUT + elif [ " ${{ github.event.inputs.target_package }}" == "gui" ]; then + echo "package_version=${{needs.fetch-versions.outputs.gui_VERSION}}" >> $GITHUB_OUTPUT + echo "package_dir=./taipy/gui" >> $GITHUB_OUTPUT + echo "release_name=${{needs.fetch-versions.outputs.gui_VERSION}}-gui" >> $GITHUB_OUTPUT + echo "tar_path=./dist/${{ github.event.repository.name }}-gui-${{needs.fetch-versions.outputs.gui_VERSION}}.tar.gz" >> $GITHUB_OUTPUT + elif [ " ${{ github.event.inputs.target_package }}" == "rest" ]; then + echo "package_version=${{needs.fetch-versions.outputs.rest_VERSION}}" >> $GITHUB_OUTPUT + echo "package_dir=./taipy/rest" >> $GITHUB_OUTPUT + echo "release_name=${{needs.fetch-versions.outputs.rest_VERSION}}-rest" >> $GITHUB_OUTPUT + echo "tar_path=./dist/${{ github.event.repository.name }}-rest-${{needs.fetch-versions.outputs.rest_VERSION}}.tar.gz" >> $GITHUB_OUTPUT + elif [ " ${{ github.event.inputs.target_package }}" == "templates" ]; then + echo "package_version=${{needs.fetch-versions.outputs.templates_VERSION}}" >> $GITHUB_OUTPUT + echo "package_dir=./taipy/templates" >> $GITHUB_OUTPUT + echo "release_name=${{needs.fetch-versions.outputs.templates_VERSION}}-templates" >> $GITHUB_OUTPUT + echo "tar_path=./dist/${{ github.event.repository.name }}-templates-${{needs.fetch-versions.outputs.templates_VERSION}}.tar.gz" >> $GITHUB_OUTPUT + fi + shell: bash + + - name: Update setup.requirements.txt + run: | + python tools/release/update_setup_requirements.py taipy- ${{ github.event.inputs.target_package }} \ + ${{needs.fetch-versions.outputs.config_VERSION}} \ + ${{needs.fetch-versions.outputs.core_VERSION}} \ + ${{needs.fetch-versions.outputs.gui_VERSION}} \ + ${{needs.fetch-versions.outputs.rest_VERSION}} \ + ${{needs.fetch-versions.outputs.templates_VERSION}} \ + ${{ github.event.inputs.internal_dep_on_pypi }} + + - name: Copy tools + run: | + cp -r tools ${{ steps.set-variables.outputs.package_dir }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build wheel pipenv mypy black isort + + - name: Install GUI dependencies + if: matrix.package == 'gui' + run: | + pipenv install --dev + + - name: Generate GUI pyi file + if: matrix.package == 'gui' + run: | + cp tools/gui/generate_pyi.py pyi_temp.py && pipenv run python pyi_temp.py && rm pyi_temp.py + + - name: Build frontends + if: matrix.package == 'gui' + run: | + python tools/frontend/bundle_build.py + + - name: Copy files from tools + run: | + cp -r tools/packages/taipy-${{matrix.package}}/. ${{ steps.set-variables.outputs.package_dir }} + + - name: Build Package Structure + working-directory: ${{ steps.set-variables.outputs.package_dir }} + run: | + python tools/release/build_package_structure.py ${{ github.event.inputs.target_package }} + + - name: Copy Taipy Logger + if: matrix.package == 'config' + run: | + cp -r taipy/logger/. ${{ steps.set-variables.outputs.package_dir }}/taipy/logger + + - name: Copy _cli folder + run: | + cp -r taipy/_cli/. ${{ steps.set-variables.outputs.package_dir }}/taipy/_cli + + - name: Build package + working-directory: ${{ steps.set-variables.outputs.package_dir }} + run: | + python setup.py build_py && python -m build + + - name: Create tag and release + working-directory: ${{ steps.set-variables.outputs.package_dir }} + run: | + if [ "${{ github.event.inputs.release_type }}" == "dev" ]; then + gh release create ${{ steps.set-variables.outputs.release_name }} ${{ steps.set-variables.outputs.tar_path }} --target ${{ steps.extract_hash.outputs.HASH }} --prerelease --title ${{ steps.set-variables.outputs.release_name }} --notes "Release Draft ${{ steps.set-variables.outputs.release_name }}" + else + gh release create ${{ steps.set-variables.outputs.release_name }} ${{ steps.set-variables.outputs.tar_path }} --target ${{ steps.extract_hash.outputs.HASH }} --title ${{ steps.set-variables.outputs.release_name }} --notes "Release ${{ steps.set-variables.outputs.release_name }}" + fi + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish-single-package.yml b/.github/workflows/publish-single-package.yml new file mode 100644 index 0000000000..d46c50aab1 --- /dev/null +++ b/.github/workflows/publish-single-package.yml @@ -0,0 +1,45 @@ +name: Publish a taipy package on Pypi + +on: + workflow_dispatch: + inputs: + version: + description: "The tag of the package to publish on Pypi (ex: 1.0.0, 1.0.0.dev0)" + required: true + target_package: + description: "The package to be released (gui, config, core, rest, templates, taipy)" + required: true + +jobs: + + publish-package-to-pypi: + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + timeout-minutes: 20 + environment: publish + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + sparse-checkout: taipy/${{ matrix.package }} + sparse-checkout-cone-mode: false + + - name: Checks if package is already on Pypi + id: check-version + run: | + if curl https://pypi.org/simple/taipy-${{ github.event.inputs.target_package }}} | grep -o ">taipy-${{ github.event.inputs.target_package }}}-${{ github.event.inputs.version }}\.tar\.gz<"; then + echo "exists=true" >> $GITHUB_OUTPUT + else + echo "exists=false" >> $GITHUB_OUTPUT + fi + + - name: Download assets from tag + if: steps.check-version.outputs.exists == 'false' + run: | + gh release download ${{ github.event.inputs.version }}-${{ github.event.inputs.target_package }}} --dir dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Publish to PyPI + if: steps.check-version.outputs.exists == 'false' + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/tools/release/fetch_latest_versions.py b/tools/release/fetch_latest_versions.py new file mode 100644 index 0000000000..de1171b6f0 --- /dev/null +++ b/tools/release/fetch_latest_versions.py @@ -0,0 +1,77 @@ +# Copyright 2021-2024 Avaiga Private Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +# an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. + +import sys + +import requests + + +def fetch_latest_releases_from_github(dev=False): + releases = {} + url = "https://api.github.com/repos/Avaiga/taipy/releases" + response = requests.get(url) + resp_json = response.json() + + for rel in resp_json: + tag = rel["tag_name"] + + if not dev and ".dev" in tag: + continue + if "config" in tag: + releases["config"] = releases.get("config") or tag.split("-")[0] + elif "core" in tag: + releases["core"] = releases.get("core") or tag.split("-")[0] + elif "gui" in tag: + releases["gui"] = releases.get("gui") or tag.split("-")[0] + elif "rest" in tag: + releases["rest"] = releases.get("rest") or tag.split("-")[0] + elif "templates" in tag: + releases["templates"] = releases.get("templates") or tag.split("-")[0] + + return releases + + +def fetch_latest_releases_from_pypi(dev=False): + releases = {} + + for pkg in ["config", "core", "gui", "rest", "templates"]: + url = f"https://pypi.org/pypi/taipy-{pkg}/json" + response = requests.get(url) + resp_json = response.json() + versions = list(resp_json["releases"].keys()) + versions.reverse() + + for ver in versions: + if not dev and ".dev" in ver: + continue + releases[pkg] = ver + break + + return releases + + +if __name__ == "__main__": + is_dev_version = sys.argv[1] == "dev" + is_pypi = sys.argv[2] == "true" + target_version = sys.argv[3] + + if is_dev_version and ".dev" not in target_version: + raise Exception("Version does not contain suffix .dev") + + versions = {} + + if not is_pypi: + versions = fetch_latest_releases_from_github(is_dev_version) + else: + versions = fetch_latest_releases_from_pypi(is_dev_version) + + for name, version in versions.items(): + print(f"{name}_VERSION={version}") # noqa: T201