diff --git a/.github/workflows/benchmark.yml.in b/.github/workflows/benchmark.yml.in index 6800a60..e521610 100644 --- a/.github/workflows/benchmark.yml.in +++ b/.github/workflows/benchmark.yml.in @@ -1,7 +1,4 @@ -name: benchmark - -env: - POETRY_VERSION: "1.4" +name: Benchmark on: workflow_dispatch: # manual invocation @@ -17,62 +14,14 @@ on: default: '["ubuntu-latest", "macos-13", "windows-latest"]' jobs: - make-workflow-benchmark: - strategy: - fail-fast: false - matrix: - python-version: {% raw %}${{ fromJSON(github.event.inputs.python)}}{% endraw %} - os: {% raw %}${{ fromJSON(github.event.inputs.platform)}}{% endraw %} - num_elements: {% raw %}${{ fromJSON(github.event.inputs.num_elements)}}{% endraw %} - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}${{ runner.os }}-test-${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Run app make workflow command - run: | - poetry run {{ executable_name }} --timeit-file benchmark_make_workflow_{% raw %}${{ matrix.num_elements }}{% endraw %}_elements-{% raw %}${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} make {{ benchmark_make_workflow }} --var N {% raw %}${{ matrix.num_elements }}{% endraw %} - - - uses: actions/upload-artifact@v4 - with: - name: {% raw %}benchmark_make_workflow_${{ matrix.num_elements }}_elements-${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} - path: {% raw %}benchmark_make_workflow_${{ matrix.num_elements }}_elements-${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} - - make-workflow-benchmark-upload: - needs: make-workflow-benchmark - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - run: | - mkdir benchmarks - - uses: actions/download-artifact@v4 - with: - merge-multiple: true - path: benchmarks - - uses: actions/upload-artifact@v4 - with: - name: benchmarks - path: benchmarks + workflow-benchmark: + uses: hpcflow/github-support/.github/workflows/benchmark-impl.yml@main + with: + executable_name: {{ executable_name }} + benchmark_make_workflow: {{ benchmark_make_workflow }} +{% raw %} + python: ${{ github.event.inputs.python }} + num_elements: ${{ github.event.inputs.num_elements }} + platform: ${{ github.event.inputs.platform }} + ref: ${{ github.ref }} +{% endraw %} diff --git a/.github/workflows/build-exes.yml.in b/.github/workflows/build-exes.yml.in index c8ccb4f..ea8674c 100644 --- a/.github/workflows/build-exes.yml.in +++ b/.github/workflows/build-exes.yml.in @@ -1,8 +1,4 @@ -name: build-exes - -env: - PYTHON_VERSION_BUILD_EXES: "3.12" - POETRY_VERSION: "1.4" +name: Build executables on: workflow_dispatch: @@ -43,313 +39,17 @@ on: default: "" jobs: - build-windows-executables: - if: github.event.inputs.build_windows == 'true' - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # get all history and tags - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_BUILD_EXES }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-build-windows-latest-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install poetry - run: python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - - - name: Configure poetry - run: | - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Install dependencies - run: poetry install --without dev - - - name: Get executable version name and store git SHA - run: | - $CUR_TAG = $(git describe --tags $(git rev-list --tags --max-count=1)) - echo "CUR_TAG is: $CUR_TAG" - echo "cur_tag=$CUR_TAG" >> $env:GITHUB_ENV - $vers = git describe --tags - echo "vers is: $vers" - echo "vers=$vers" >> $env:GITHUB_ENV - $sha = git rev-parse HEAD - echo "sha is: $sha" - echo "sha=$sha" >> $env:GITHUB_ENV - - - name: Build with pyinstaller for Windows (file) - if: github.event.inputs.build_onefile == 'true' - working-directory: {{ pyinstaller_dir }} - run: ./make.ps1 -ExeName "{{ executable_name }}-{% raw %}${{ env.vers }}-win" -LogLevel ${{ github.event.inputs.logLevel }}{% endraw %} -BuildType 'onefile' - - - name: Build with pyinstaller for Windows (folder) - if: github.event.inputs.build_onedir == 'true' - working-directory: {{ pyinstaller_dir }} - run: ./make.ps1 -ExeName "{{ executable_name }}-{% raw %}${{ env.vers }}-win-dir" -LogLevel ${{ github.event.inputs.logLevel }}{% endraw %} -BuildType 'onedir' - - - name: Upload executable artifact (file) - if: github.event.inputs.build_onefile == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.exe - path: {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.exe - - - name: Upload executable artifact (folder) - if: github.event.inputs.build_onedir == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir - path: {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir - - - name: Upload spec file - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.spec - path: {{ pyinstaller_dir }}/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.spec - - - name: Upload build directory - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-build - path: {{ pyinstaller_dir }}/build/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win - - - name: Set demo data GitHub URL using current git SHA (file) # instead of default which is current version tag - if: github.event.inputs.build_onefile == 'true' - run: | - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.exe config set-github-demo-data-dir {% raw %}${{ env.sha }}{% endraw %} - - - name: Set demo data GitHub URL using current git SHA (folder) # instead of default which is current version tag - if: github.event.inputs.build_onedir == 'true' - run: | - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir.exe config set-github-demo-data-dir {% raw %}${{ env.sha }}{% endraw %} - - - name: Run test suite on the frozen app (file) - if: github.event.inputs.build_onefile == 'true' - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win.exe test {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - - name: Run test suite on the frozen app (folder) - if: github.event.inputs.build_onedir == 'true' - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-win-dir.exe test {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - - build-macos-executables: - if: github.event.inputs.build_macos == 'true' - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # get all history and tags - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_BUILD_EXES }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-build-macos-13-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install poetry - run: python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - - - name: Configure poetry - run: | - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Install dependencies - run: poetry install --without dev - - - name: Get executable version name and store git SHA - run: | - CUR_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "CUR_TAG is: $CUR_TAG" - echo "cur_tag=$CUR_TAG" >> $GITHUB_ENV - vers=$(git describe --tags) - echo "vers is: $vers" - echo "vers=$vers" >> $GITHUB_ENV - sha=$(git rev-parse HEAD) - echo "sha is: $sha" - echo "sha=$sha" >> $GITHUB_ENV - - - name: Build with pyinstaller for macOS (file) - if: github.event.inputs.build_onefile == 'true' - working-directory: {{ pyinstaller_dir }} - run: ./make.sh {{ executable_name }}-{% raw %}${{ env.vers }}-macOS ${{ github.event.inputs.logLevel }}{% endraw %} 'onefile' - - - name: Build with pyinstaller for macOS (folder) - if: github.event.inputs.build_onedir == 'true' - working-directory: {{ pyinstaller_dir }} - run: ./make.sh {{ executable_name }}-{% raw %}${{ env.vers }}-macOS-dir ${{ github.event.inputs.logLevel }}{% endraw %} 'onedir' - - - name: Upload executable artifact (file) - if: github.event.inputs.build_onefile == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS - path: {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS - - - name: Upload executable artifact (folder) - if: github.event.inputs.build_onedir == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir - path: {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir - - - name: Upload spec file - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS.spec - path: {{ pyinstaller_dir }}/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS.spec - - - name: Upload build directory - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-build - path: {{ pyinstaller_dir }}/build/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS - - - name: Set demo data GitHub URL using current git SHA (file) # instead of default which is current version tag - if: github.event.inputs.build_onefile == 'true' - run: | - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS config set-github-demo-data-dir {% raw %}${{ env.sha }}{% endraw %} - - - name: Set demo data GitHub URL using current git SHA (folder) # instead of default which is current version tag - if: github.event.inputs.build_onedir == 'true' - run: | - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir config set-github-demo-data-dir {% raw %}${{ env.sha }}{% endraw %} - - - name: Run test suite on the frozen app (file) - if: github.event.inputs.build_onefile == 'true' - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS test {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - - name: Run test suite on the frozen app (folder) - if: github.event.inputs.build_onedir == 'true' - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-macOS-dir test {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - build-executables-linux: - if: github.event.inputs.build_linux == 'true' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # get all history and tags - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-build-CentOS-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Get executable version name and store git SHA - run: | - CUR_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "CUR_TAG is: $CUR_TAG" - echo "cur_tag=$CUR_TAG" >> $GITHUB_ENV - vers=$(git describe --tags) - echo "vers is: $vers" - echo "vers=$vers" >> $GITHUB_ENV - sha=$(git rev-parse HEAD) - echo "sha is: $sha" - echo "sha=$sha" >> $GITHUB_ENV - - - name: Build executable (file) within Docker - if: github.event.inputs.build_onefile == 'true' - uses: addnab/docker-run-action@v3 - with: - image: ghcr.io/hpcflow/centos7-poetry:latest - options: -v {% raw %}${{ github.workspace }}:/home --env GH_TOKEN=${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - - # set up poetry - cd /home - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - poetry install --without dev - - # build with pyinstaller for CentOS (file) - cd {{ pyinstaller_dir }} - ./make.sh {{ executable_name }}-{% raw %}${{ env.vers }}-linux ${{ github.event.inputs.logLevel }}{% endraw %} onefile - cd .. - - # set demo data GitHub URL using current git SHA (file), instead of default which is current version tag - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}-linux config set-github-demo-data-dir ${{ env.sha }}{% endraw %} - - # run test suite on the frozen app (file) - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}-linux test ${{ github.event.inputs.unit_test_args }}{% endraw %} - - - name: Build executable (folder) within Docker - if: github.event.inputs.build_onedir == 'true' - uses: addnab/docker-run-action@v3 - with: - image: ghcr.io/hpcflow/centos7-poetry:latest - options: -v {% raw %}${{ github.workspace }}:/home --env GH_TOKEN=${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - - # set up poetry - cd /home - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - poetry install --without dev - - # build with pyinstaller for CentOS (folder) - cd {{ pyinstaller_dir }} - ./make.sh {{ executable_name }}-{% raw %}${{ env.vers }}-linux-dir ${{ github.event.inputs.logLevel }}{% endraw %} onedir - cd .. - - # set demo data GitHub URL using current git SHA (folder), instead of default which is current version tag - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir config set-github-demo-data-dir {% raw %}${{ env.sha }}{% endraw %} - - # run test suite on the frozen app (folder) - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir test {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - - name: Upload executable artifact (file) - if: github.event.inputs.build_onefile == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux - path: {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux - - - name: Upload executable artifact (folder) - if: github.event.inputs.build_onedir == 'true' - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir - path: {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-dir - - - name: Upload spec file - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux.spec - path: {{ pyinstaller_dir }}/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux.spec - - - name: Upload build directory - if: ((github.event.inputs.build_onefile == 'true') || (github.event.inputs.build_onedir == 'true')) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux-build - path: {{ pyinstaller_dir }}/build/{{ executable_name }}-{% raw %}${{ env.vers }}{% endraw %}-linux + build-exes: + uses: hpcflow/github-support/.github/workflows/build-exes-impl.yml@main + with: +{% raw %} + build_linux: ${{ github.event.inputs.build_linux }} + build_macos: ${{ github.event.inputs.build_macos }} + build_windows: ${{ github.event.inputs.build_windows }} + build_onedir: ${{ github.event.inputs.build_onedir }} + build_onefile: ${{ github.event.inputs.build_onefile }} + logLevel: ${{ github.event.inputs.logLevel }} + unit_test_args: ${{ github.event.inputs.unit_test_args }} +{% endraw %} + executable_name: {{ executable_name }} + pyinstaller_dir: {{ pyinstaller_dir }} diff --git a/.github/workflows/release.yml.in b/.github/workflows/release.yml.in index 6e2a4fb..30cf6ff 100644 --- a/.github/workflows/release.yml.in +++ b/.github/workflows/release.yml.in @@ -1,642 +1,41 @@ -name: release +name: Release concurrency: release -env: - PYTHON_VERSION_BUMP: "3.12" - PYTHON_VERSION_BUILD_EXES: "3.12" - PYTHON_VERSION_RELEASE: "3.12" - PYTHON_VERSION_BUILD_DOCS: "3.12" - PYTHON_VERSION_UPDATE_WEB: "3.12" - POETRY_VERSION: "1.4" - on: pull_request_target: branches: [{{ release_branch }}, {{ pre_release_branch }}] types: [closed] jobs: - bump-version: - if: - | # skip if: trying to re-run; PR is closed without merging; '[skip release]' is in the PR title; or if merging any branch other than pre_release_branch into release_branch - ( - github.run_attempt == '1' - && github.event.pull_request.merged - && ! contains(github.event.pull_request.title, '[skip release]') - && ( - github.event.pull_request.base.ref == '{{ pre_release_branch }}' || ( - github.event.pull_request.base.ref == '{{ release_branch }}' - && github.event.pull_request.head.ref == '{{ pre_release_branch }}' - ) - ) - ) - runs-on: ubuntu-latest - outputs: - new_tag_name: {% raw %}${{ steps.get_new_tag.outputs.new_tag_name }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # get all history and tags - ref: {% raw %}${{ github.event.pull_request.base.ref }}{% endraw %} - token: {{ '${{' }} secrets.{{ token_name }} {{ '}}' }} - - - run: | - git config user.name {{ bot_account_name }} - git config user.email {{ bot_account_email }} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_BUMP }}{% endraw %} - - - name: Get git-chglog executable - run: | - wget https://github.com/git-chglog/git-chglog/releases/download/v0.15.0/git-chglog_0.15.0_linux_amd64.tar.gz - tar --extract --file git-chglog_0.15.0_linux_amd64.tar.gz git-chglog - - - name: Install commitizen - run: pip install commitizen - - - name: Manipulate tags (stable release) - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: - | # delete all pre-release tags, set current version to the latest stable release, - CUR_PRE_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "CUR_PRE_TAG is: $CUR_PRE_TAG" - echo "cur_pre_tag=$CUR_PRE_TAG" >> $GITHUB_ENV - git tag -l | awk '/^(v[0-9]+\.[0-9]+\.[0-9]+(a|b|rc).*)$/ {print $1}' | xargs git tag -d - - - name: Get current tag - run: | - CUR_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "CUR_TAG is: $CUR_TAG" - echo "cur_tag=$CUR_TAG" >> $GITHUB_ENV - - - name: Commitizen bump (pre-release) # Bump version strings (pre-release) and add a new tag; commit - if: github.event.pull_request.base.ref == '{{ pre_release_branch }}' - run: cz bump --prerelease alpha - - - name: Commitizen bump # First update version number to latest stable release, then bump to new stable release, add a new tag and commit - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - python3 -c " - from commitizen.bump import update_version_in_files - update_version_in_files({% raw %} - current_version='${{ env.cur_pre_tag }}'.lstrip('v'), - new_version='${{ env.cur_tag }}'.lstrip('v'),{% endraw %} - files=['pyproject.toml', '{{ version_file }}'], - )" - cz bump - - - name: Get new tag - id: get_new_tag - run: | - NEW_TAG=$(git describe --tags $(git rev-list --tags --max-count=1)) - echo "NEW_TAG is: $NEW_TAG" - echo "new_tag=$NEW_TAG" >> $GITHUB_ENV - echo "new_tag_name=$NEW_TAG" >> $GITHUB_OUTPUT - - - name: Generate CHANGELOG (stable release) - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - ./git-chglog --output CHANGELOG.md - git add CHANGELOG.md - - - name: Generate CHANGELOG-dev (pre-release) - if: github.event.pull_request.base.ref == '{{ pre_release_branch }}' - run: | - ./git-chglog --output CHANGELOG-dev.md - git add CHANGELOG-dev.md + release: + uses: hpcflow/github-support/.github/workflows/release-impl.yml@main + with: {% raw %} - - name: Push new CHANGELOG - run: | - git tag -d ${{ env.new_tag }} - git commit --amend --no-edit - git tag ${{ env.new_tag }} - git push && git push origin ${{ env.new_tag }} + gh-run-attempt: ${{ github.run_attempt }} + pr-merged: ${{ github.event.pull_request.merged }} + pr-title: ${{ github.event.pull_request.title }} + pr-base-ref: ${{ github.event.pull_request.base.ref }} + pr-head-ref: ${{ github.event.pull_request.head.ref }} {% endraw %} - - name: Rebase into develop branch if exists (stable release) - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - exists_in_remote=$(git ls-remote --heads origin refs/heads/{{ pre_release_branch }}) - echo "exists_in_remote: $exists_in_remote" - if [[ -n $exists_in_remote ]]; then - export SKIP=end-of-file-fixer - git checkout {{ pre_release_branch }} - git pull - git rebase {{ release_branch }} - git push -u origin {{ pre_release_branch }} - else - echo "No {{ pre_release_branch }} branch to merge into." - fi - - - name: Generate incremental CHANGELOG for GitHub release body (stable release) - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - {% raw %}./git-chglog --template .chglog/RELEASE.tpl.md --output CHANGELOG_increment.md ${{ env.cur_tag }}..{% endraw %} - cat CHANGELOG_increment.md - - - name: Generate incremental CHANGELOG for GitHub release body (pre-release) - if: github.event.pull_request.base.ref == '{{ pre_release_branch }}' - run: | - {% raw %}./git-chglog --template .chglog/RELEASE.tpl.md --output CHANGELOG_increment.md ${{ env.new_tag }}{% endraw %} - cat CHANGELOG_increment.md - - - uses: actions/upload-artifact@v4 - with: - name: CHANGELOG_increment - path: CHANGELOG_increment.md - - build-executables: - needs: bump-version - strategy: - fail-fast: false - matrix: - os: [windows-2019, macos-13] - include: - - os: windows-2019 - executable_ext: .exe - executable_os: win - - os: macos-13 - executable_ext: "" - executable_os: macOS - - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.event.pull_request.base.ref }}{% endraw %} # otherwise we get the ref when the workflow started (missing above commit) - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_BUILD_EXES }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-build-${{ matrix.os }}-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install poetry - run: python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - - - name: Configure poetry - run: | - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Install dependencies - run: poetry install --without dev - - - name: Build with pyinstaller (non-Windows, file) - if: "!contains(matrix.os, 'windows')" - working-directory: {{ pyinstaller_dir }} - run: ./make.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }} INFO 'onefile'{% endraw %} - - - name: Build with pyinstaller (non-Windows, folder) - if: "!contains(matrix.os, 'windows')" - working-directory: {{ pyinstaller_dir }} - run: ./make.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name}}-${{ matrix.executable_os }}-dir INFO 'onedir'{% endraw %} - - - name: Build with pyinstaller (Windows, file) - if: contains(matrix.os, 'windows') - working-directory: {{ pyinstaller_dir }} - run: ./make.ps1 -ExeName '{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}' -LogLevel INFO -BuildType 'onefile'{% endraw %} - - - name: Build with pyinstaller (Windows, folder) - if: contains(matrix.os, 'windows') - working-directory: {{ pyinstaller_dir }} - run: ./make.ps1 -ExeName '{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir' -LogLevel INFO -BuildType 'onedir'{% endraw %} - - - name: Version check (windows, file) - if: contains(matrix.os, 'windows') - run: | - $tag = "{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}" - $tagNoV = $tag.trim('v') - ${{ executable_name }}_vers = {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}${{ matrix.executable_ext }}{% endraw %} --version - ${{ executable_name }}_vers_expected = "{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo "${{ executable_name }}_vers_expected" - if (${{ executable_name }}_vers -ne ${{ executable_name }}_vers_expected) { - exit 1 - } - - - name: Version check (windows, folder) - if: contains(matrix.os, 'windows') - run: | - $tag = "{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}" - $tagNoV = $tag.trim('v') - ${{ executable_name }}_vers = {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir/{% endraw %}{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir${{ matrix.executable_ext }} {% endraw %} --version - ${{ executable_name }}_vers_expected = "{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo "${{ executable_name }}_vers_expected" - if (${{ executable_name }}_vers -ne ${{ executable_name }}_vers_expected) { - exit 1 - } - - - name: Version check (non-windows, file) - if: "!contains(matrix.os, 'windows')" - run: | - tag={% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - tagNoV=${tag:1} - {{ executable_name }}_vers=$({{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}${{ matrix.executable_ext }}{% endraw %} --version) - {{ executable_name }}_vers_expected="{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo ${{ executable_name }}_vers_expected - [ "${{ executable_name }}_vers" = "${{ executable_name }}_vers_expected" ] - - - name: Version check (non-windows, folder) - if: "!contains(matrix.os, 'windows')" - run: | - tag={% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - tagNoV=${tag:1} - {{ executable_name }}_vers=$({{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir/{% endraw %}{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir${{ matrix.executable_ext }}{% endraw %} --version) - {{ executable_name }}_vers_expected="{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo ${{ executable_name }}_vers_expected - [ "${{ executable_name }}_vers" = "${{ executable_name }}_vers_expected" ] - - - name: Run test suite on the frozen app (folder) - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir/{% endraw %}{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir${{ matrix.executable_ext }}{% endraw %} test - - - name: Compress folder (windows, folder) - if: contains(matrix.os, 'windows') - working-directory: {{ pyinstaller_dir }} - run: ./compress.ps1 -ExeName '{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir' -BuildType 'onedir'{% endraw %} - - - name: Compress folder (non-windows, folder) - if: "!contains(matrix.os, 'windows')" - working-directory: {{ pyinstaller_dir }} - run: ./compress.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}-dir 'onedir'{% endraw %} - - - name: Upload executable artifact (file) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}${{ matrix.executable_ext }}{% endraw %} - path: {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}${{ matrix.executable_ext }}{% endraw %} - - - name: Upload executable artifact (compressed folder) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}{% endraw %}-dir.zip - path: {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-${{ matrix.executable_os }}{% endraw %}-dir.zip - - build-executables-linux: - runs-on: ubuntu-latest - needs: bump-version - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.event.pull_request.base.ref }}{% endraw %} # otherwise we get the ref when the workflow started (missing above commit) - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: venv-build-CentOS-{% raw %}${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Build executables within Docker - uses: addnab/docker-run-action@v3 - with: - image: ghcr.io/hpcflow/centos7-poetry:latest - options: -v {% raw %}${{ github.workspace }}:/home --env GH_TOKEN=${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - # set up poetry - cd /home - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - poetry install --without dev - - # build with pyinstaller for CentOS (file) - cd {{ pyinstaller_dir }} - ./make.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-linux INFO onefile{% endraw %} - cd .. - - # version check (file) - tag={% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - tagNoV=${tag:1} - {{ executable_name }}_vers=$({{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux --version) - {{ executable_name }}_vers_expected="{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo ${{ executable_name }}_vers_expected - [ "${{ executable_name }}_vers" = "${{ executable_name }}_vers_expected" ] - - # run test suite on the frozen app (file) - {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-linux test{% endraw %} - - # build with pyinstaller for CentOS (folder) - cd {{ pyinstaller_dir }} - ./make.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-linux-dir INFO onedir{% endraw %} - cd .. - - # version check (folder) - tag={% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - tagNoV=${tag:1} - {{ executable_name }}_vers=$({{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir --version) - {{ executable_name }}_vers_expected="{{ app_name }}, version $tagNoV" - echo ${{ executable_name }}_vers - echo ${{ executable_name }}_vers_expected - [ "${{ executable_name }}_vers" = "${{ executable_name }}_vers_expected" ] - - # run test suite on the frozen app (folder) - {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir test - - # Compress folder (folder) - cd pyinstaller - ./compress.sh {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}-linux-dir 'onedir'{% endraw %} - cd .. - - - name: Upload executable artifact (file) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux - path: {{ pyinstaller_dir }}/dist/onefile/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux - - - name: Upload executable artifact (compressed folder) - uses: actions/upload-artifact@v4 - with: - name: {{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir.zip - path: {{ pyinstaller_dir }}/dist/onedir/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir.zip - - make-workflow-benchmark: - needs: bump-version - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.12" - os: - - ubuntu-latest - - macos-13 - - windows-latest - num_elements: - - 1 - - 100 - - 10000 - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}${{ runner.os }}-test-${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Run app make workflow command - run: | - poetry run {{ executable_name }} --timeit-file benchmark_make_workflow_{% raw %}${{ matrix.num_elements }}{% endraw %}_elements-{% raw %}${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} make {{ benchmark_make_workflow }} --var N {% raw %}${{ matrix.num_elements }}{% endraw %} - - - uses: actions/upload-artifact@v4 - with: - name: {% raw %}benchmark_make_workflow_${{ matrix.num_elements }}_elements-${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} - path: {% raw %}benchmark_make_workflow_${{ matrix.num_elements }}_elements-${{ runner.os }}-py-${{ matrix.python-version }}.txt{% endraw %} - - make-workflow-benchmark-upload: - needs: make-workflow-benchmark - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - run: | - mkdir benchmarks - - uses: actions/download-artifact@v4 - with: - merge-multiple: true - path: benchmarks - - name: zip benchmark results - run: | - zip -r ./benchmarks.zip benchmarks - - uses: actions/upload-artifact@v4 - with: - name: benchmarks.zip - path: benchmarks.zip - - release-github-PyPI: - needs: - - bump-version - - build-executables - - build-executables-linux - - make-workflow-benchmark-upload - runs-on: ubuntu-latest - outputs: - binary_download_links: {% raw %}${{ steps.get_binary_download_links.outputs.binary_download_links }}{% endraw %} + pre_release_branch: {{ pre_release_branch }} + release_branch: {{ release_branch }} + app_name: {{ app_name }} + benchmark_make_workflow: {{ benchmark_make_workflow }} + docs_url_prefix: {{ docs_url_prefix }} + executable_name: {{ executable_name }} + pyinstaller_dir: {{ pyinstaller_dir }} + pypi-url: {{ PYPI_URL }} + repository: {{ org }}/{{ repo }} + version_file: {{ version_file }} + website_source_org: {{ website_source_org }} + website_source_repo: {{ website_source_repo }} + secrets: +{% raw %} + general-token: ${{ secrets.GITHUB_TOKEN }} +{% endraw %} + commit-token: {{ '${{' }} secrets.{{ token_name }} {{ '}}' }} + pypi-token: {{ '${{' }} secrets.{{ PYPI_token_name }} {{ '}}' }} + website-token: {{ '${{' }} secrets.{{ website_source_token_name }} {{ '}}' }} permissions: + id-token: write contents: write - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.event.pull_request.base.ref }}{% endraw %} # otherwise we get the ref when the workflow started (missing above commit) - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_RELEASE }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-release-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install poetry - run: python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - - - name: Configure poetry - run: | - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Install dependencies - run: poetry install --without dev,pyinstaller - - - name: Build (for PyPI) - run: | - poetry build - - - run: mkdir release-artifacts - - - uses: actions/download-artifact@v4 - with: - path: release-artifacts - - - uses: actions/download-artifact@v3 # for CentOS (docker) build-exes - with: - path: release-artifacts - - - name: Display structure of downloaded files - run: ls -R - - - name: Release - id: release - uses: softprops/action-gh-release@v2 - with: - body_path: release-artifacts/CHANGELOG_increment/CHANGELOG_increment.md - tag_name: {% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - files: | - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-win.exe - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-macOS - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-win-dir.zip - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-macOS-dir.zip - **/{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-linux-dir.zip - **/benchmarks.zip - prerelease: {{ '${{' }} github.event.pull_request.base.ref == '{{ pre_release_branch }}' {{ '}}' }} - - - name: Release info - id: get_binary_download_links - run: | - binaryYaml=$(python3 -c " - from pathlib import Path - out_yaml = '' - for i in ['win.exe', 'macOS', 'linux', 'win-dir.zip', 'macOS-dir.zip', 'linux-dir.zip']: - exe_name = '{{ executable_name }}-{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}-' + i - url = 'https://github.com/{{ org }}/{{ repo }}/releases/download/{% raw %}${{ needs.bump-version.outputs.new_tag_name }}{% endraw %}/' + exe_name - out_yaml += exe_name + ': ' + url + '\n' - print(out_yaml) - ") - # Save multiline output - EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) - echo "binary_download_links<<$EOF" >> $GITHUB_OUTPUT - echo "$binaryYaml" >> $GITHUB_OUTPUT - echo "$EOF" >> $GITHUB_OUTPUT - - - name: Publish (to {{ PYPI_URL }}) - run: | - poetry config repositories.pypi {{ PYPI_URL }} - poetry config pypi-token.pypi {{ '${{' }} secrets.{{ PYPI_token_name }} {{ '}}' }} - poetry publish --repository pypi - - build-documentation: - needs: release-github-PyPI - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 # get all history and tags - ref: {% raw %}${{ github.event.pull_request.base.ref }}{% endraw %} # otherwise we get the ref when the workflow started (missing above commit) - token: {{ '${{' }} secrets.{{ token_name }} {{ '}}' }} - - - run: | - git config user.name {{ bot_account_name }} - git config user.email {{ bot_account_email }} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_BUILD_DOCS }}{% endraw %} - - - name: Write binary links YAML file and push - run: | - {% raw %}echo -e "${{ needs.release-github-PyPI.outputs.binary_download_links }}" > docs/source/released_binaries.yml{% endraw %} - git add . - git commit -m "build: update binary download links file [skip ci]" - git push - - - name: Rebase into develop branch if exists (stable release) - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - exists_in_remote=$(git ls-remote --heads origin refs/heads/{{ pre_release_branch }}) - echo "exists_in_remote: $exists_in_remote" - if [[ -n $exists_in_remote ]]; then - export SKIP=end-of-file-fixer - git checkout {{ pre_release_branch }} - git pull - git rebase {{ release_branch }} - git push -u origin {{ pre_release_branch }} - else - echo "No {{ pre_release_branch }} branch to merge into." - fi - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-release-${{ matrix.os }}-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install poetry - run: python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - - - name: Configure poetry - run: | - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Install dependencies - run: poetry install --without test,pyinstaller - - - name: Build documentation with Sphinx - run: | - cd docs - poetry run make clean - poetry run make html - - - name: Upload documentation artifact - uses: actions/upload-artifact@v4 - with: - name: docs_html - path: docs/build/html - - update-website: - needs: [bump-version, release-github-PyPI, build-documentation] - runs-on: ubuntu-latest - steps: - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_UPDATE_WEB }}{% endraw %} - - - uses: actions/checkout@v4 - with: - repository: {{ website_source_org }}/{{ website_source_repo }} - token: {{ '${{' }} secrets.{{ website_source_token_name }} {{ '}}' }} - - - run: | - git config user.name {{ bot_account_name }} - git config user.email {{ bot_account_email }} - - - name: Download documentation artifact - uses: actions/download-artifact@v4 - with: - name: docs_html - path: {% raw %}docs/${{ needs.bump-version.outputs.new_tag_name }}{% endraw %} - - - name: Update stable docs symlink - if: github.event.pull_request.base.ref == '{{ release_branch }}' - run: | - {% raw %}ln -sfn ${{ needs.bump-version.outputs.new_tag_name }} docs/stable{% endraw %} - - - name: Update pre-release docs symlink - if: github.event.pull_request.base.ref == '{{ pre_release_branch }}' - run: | - {% raw %}ln -sfn ${{ needs.bump-version.outputs.new_tag_name }} docs/dev{% endraw %} - - - run: | - tree - - - name: Update doc version switcher - run: | - curl https://raw.githubusercontent.com/{{ org }}/{{ repo }}/{% raw %}${{ github.ref_name }}{% endraw %}/docs/make_vers_switcher.py --output docs/make_vers_switcher.py - python docs/make_vers_switcher.py {{ docs_url_prefix }} - - - name: Push changes - run: | - git add . - git commit -m "update content" - git push diff --git a/.github/workflows/test.yml.in b/.github/workflows/test.yml.in index 473fd18..0a4df69 100644 --- a/.github/workflows/test.yml.in +++ b/.github/workflows/test.yml.in @@ -1,11 +1,4 @@ -name: test -concurrency: - | # e.g. don't run simultaneously on the same branch (since we may commit to that branch) - {% raw %}ci-${{ format('{0}github.head_ref', 'refs/heads') || github.ref }}{% endraw %} - -env: - PYTHON_VERSION_PRE_COMMIT: "3.12" - POETRY_VERSION: "1.4" +name: Test on: workflow_dispatch: # manual invocation @@ -45,492 +38,28 @@ on: branches: [main, develop] # have to manually change these jobs: - pre-commit: - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.event.inputs.pre_commit == 'true' - steps: - - uses: actions/checkout@v4 - with: - # PAT of user who has permission to bypass branch - # protection || or standard GITHUB_TOKEN if running on an external fork (won't - # be able to commit fixes): - token: {{ '${{' }} secrets.{{ token_name }} {{ '|| secrets.GITHUB_TOKEN }}' }} - # checkout PR source branch (head_ref) if event is pull_request: - ref: {% raw %}${{ github.head_ref || github.ref }}{% endraw %} - repository: {% raw %}${{ github.event.pull_request.head.repo.full_name }}{% endraw %} - - - run: | - git config user.name {{ bot_account_name }} - git config user.email {{ bot_account_email }} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ env.PYTHON_VERSION_PRE_COMMIT }}{% endraw %} - - - name: pre-commit - # avoid exit code 1 (which halts GH actions) from pre-commit run command by - # running twice: - run: | - pip install pre-commit - pre-commit install - export SKIP=no-commit-to-branch - pre-commit run --all-files || pre-commit run --all-files - - - name: pre-commit push changes - run: | - if git diff --quiet; then - echo "No pre-commit changes" - else - git commit -am "pre-commit fixes [skip ci]" - git push - fi - - test-units: - needs: pre-commit - if: github.event_name == 'pull_request' || github.event.inputs.unit_tests == 'true' - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - os: - - ubuntu-latest - - macos-13 - - windows-latest - - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}${{ runner.os }}-test-${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Run tests - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - poetry run python -m pytest {{ pytest_args }} {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - test-units-CentOS: - needs: pre-commit - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.event.inputs.unit_tests == 'true' - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-CentOS-test-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Run unit tests within Docker - uses: addnab/docker-run-action@v3 - with: - image: ghcr.io/hpcflow/centos7-poetry:latest - options: -v {% raw %}${{ github.workspace }}:/home --env GH_TOKEN=${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - cd /home - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - poetry install --without dev,pyinstaller - poetry run python -m pytest {% raw %}${{ github.event.inputs.unit_test_args }}{% endraw %} - - test-integration: - needs: pre-commit - if: github.event_name == 'pull_request' || github.event.inputs.integration_tests == 'true' - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - os: - - ubuntu-latest - - macos-13 - - windows-latest - - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}${{ runner.os }}-test-${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Run tests - env: - GH_TOKEN: {% raw %}${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - poetry run {{ executable_name }} test {{ pytest_args }} --integration {% raw %}${{ github.event.inputs.integration_test_args }}{% endraw %} - - test-integration-CentOS: - needs: pre-commit - runs-on: ubuntu-latest - if: github.event_name == 'pull_request' || github.event.inputs.integration_tests == 'true' - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}venv-CentOS-test-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Run integration tests within Docker - uses: addnab/docker-run-action@v3 - with: - image: ghcr.io/hpcflow/centos7-poetry:latest - options: -v {% raw %}${{ github.workspace }}:/home --env GH_TOKEN=${{ secrets.GITHUB_TOKEN }}{% endraw %} - run: | - cd /home - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - poetry install --without dev,pyinstaller - poetry run hpcflow test --integration {% raw %}${{ github.event.inputs.integration_test_args }}{% endraw %} - - test-invocation-ubuntu: - if: github.event_name == 'pull_request' || github.event.inputs.invocation_tests == 'true' - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install poetry and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: venv-test-invocation-linux{% raw %}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - poetry run pip install ipython - - - name: Test invocation command with `python ./{{ CLI_path }}` - run: | - source $(poetry env info --path)/bin/activate - actual=`python ./{{ CLI_path }} internal get-invoc-cmd` - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with `python -m {{ CLI_module }}` - run: | - source $(poetry env info --path)/bin/activate - actual=`python -m {{ CLI_module }} internal get-invoc-cmd` - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with `{{ executable_name }}` entry point script - run: | - source $(poetry env info --path)/bin/activate - actual=`{{ executable_name }} internal get-invoc-cmd` - expected="('`command -v python`', '`command -v {{ executable_name }}`')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command within a python script - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd.py {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with interactive python - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd_interactive.py python {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with interactive ipython - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd_interactive.py ipython {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test direct workflow submission within a python script - run: | - source $(poetry env info --path)/bin/activate - python ./.github/workflows/test_direct_sub_python_script.py {{ app_package }} - - - name: Test direct workflow submission within a Jupyter notebook (via papermill) - run: | - source $(poetry env info --path)/bin/activate - python -m ipykernel install --user --name python3 - papermill ./.github/workflows/test_direct_sub_jupyter_notebook.ipynb ./.github/workflows/test_direct_sub_jupyter_notebook_{% raw %}${{ matrix.python-version }}_${{ runner.os }}{% endraw %}.ipynb -p app_import_str {{ app_package }} - - test-invocation-macos: - if: github.event_name == 'pull_request' || github.event.inputs.invocation_tests == 'true' - runs-on: macos-13 - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install poetry and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: venv-test-invocation-macos{% raw %}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - poetry run pip install ipython - - - name: Test invocation command with `python ./{{ CLI_path }}` - run: | - source $(poetry env info --path)/bin/activate - actual=`python ./{{ CLI_path }} internal get-invoc-cmd` - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with `python -m {{ CLI_module }}` - run: | - source $(poetry env info --path)/bin/activate - actual=`python -m {{ CLI_module }} internal get-invoc-cmd` - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with `{{ executable_name }}` entry point script - run: | - source $(poetry env info --path)/bin/activate - actual=`{{ executable_name }} internal get-invoc-cmd` - expected="('`command -v python`', '`command -v {{ executable_name }}`')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command within a python script - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd.py {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with interactive python - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd_interactive.py python {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test invocation command with interactive ipython - run: | - source $(poetry env info --path)/bin/activate - actual=$(python ./.github/workflows/get_invoc_cmd_interactive.py ipython {{ app_package }}) - expected="('`command -v python`', '$GITHUB_WORKSPACE/{{ CLI_path }}')" - echo actual: $actual - echo expected: $expected - [ "$actual" = "$expected" ] - - - name: Test direct workflow submission within a python script - run: | - source $(poetry env info --path)/bin/activate - python ./.github/workflows/test_direct_sub_python_script.py {{ app_package }} - - - name: Test direct workflow submission within a Jupyter notebook (via papermill) - run: | - source $(poetry env info --path)/bin/activate - python -m ipykernel install --user --name python3 - papermill ./.github/workflows/test_direct_sub_jupyter_notebook.ipynb ./.github/workflows/test_direct_sub_jupyter_notebook_{% raw %}${{ matrix.python-version }}_${{ runner.os }}{% endraw %}.ipynb -p app_import_str {{ app_package }} - - test-invocation-windows: - if: github.event_name == 'pull_request' || github.event.inputs.invocation_tests == 'true' - runs-on: windows-latest - strategy: - fail-fast: false - matrix: - python-version: - - "3.8" - - "3.9" - - "3.10" - - "3.11" - - "3.12" - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - - - name: Install poetry and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: venv-test-invocation-windows{% raw %}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Test invocation command with `python ./{{ CLI_path }}` - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - $actual = $(python ./{{ CLI_path }} internal get-invoc-cmd) - $expected = "('" + ((Get-Command python).source | Resolve-Path).Path.Replace('\', '\\') + "', '" + "$env:GITHUB_WORKSPACE\{{ CLI_path_win }}".Replace('\', '\\') + "')" - Write-Host actual: $actual - Write-Host expected: $expected - if ($actual -ne $expected) { - exit 1 - } - - - name: Test invocation command with `python -m {{ CLI_module }}` - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - $actual = $(python -m {{ CLI_module }} internal get-invoc-cmd) - $expected = "('" + ((Get-Command python).source | Resolve-Path).Path.Replace('\', '\\') + "', '" + "$env:GITHUB_WORKSPACE\{{ CLI_path_win }}".Replace('\', '\\') + "')" - Write-Host actual: $actual - Write-Host expected: $expected - if ($actual -ne $expected) { - exit 1 - } - - - name: Test invocation command with `{{ executable_name }}` entry point script - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - $actual = $({{ executable_name }} internal get-invoc-cmd) - $expected = "('" + ((Get-Command python).source | Resolve-Path).Path.Replace('\', '\\') + "', '" + ((Get-Command {{ executable_name }}).source | Resolve-Path).Path.Replace('\', '\\').Trim('.cmd') + "')" - Write-Host actual: $actual - Write-Host expected: $expected - if ($actual -ne $expected) { - exit 1 - } - - - name: Test invocation command within a python script - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - $actual = $(python .\.github\workflows\get_invoc_cmd.py {{ app_package }}) - $expected = "('" + ((Get-Command python).source | Resolve-Path).Path.Replace('\', '\\') + "', '" + "$env:GITHUB_WORKSPACE\{{ CLI_path_win }}".Replace('\', '\\') + "')" - Write-Host actual: $actual - Write-Host expected: $expected - if ($actual -ne $expected) { - exit 1 - } - - - name: Test direct workflow submission within a python script - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - python .\.github\workflows\test_direct_sub_python_script.py {{ app_package }} - - - name: Test direct workflow submission within a Jupyter notebook (via papermill) - run: | - ."$(poetry env info --path)\Scripts\activate.ps1" - python -m ipykernel install --user --name python3 - papermill .\.github\workflows\test_direct_sub_jupyter_notebook.ipynb .\.github\workflows\test_direct_sub_jupyter_notebook_{% raw %}${{ matrix.python-version }}_${{ runner.os }}{% endraw %}.ipynb -p app_import_str {{ app_package }} + test: + uses: hpcflow/github-support/.github/workflows/test-impl.yml@main + with: +{% raw %} + pre_commit: ${{ github.event_name == 'pull_request' || github.event.inputs.pre_commit }} + unit_tests: ${{ github.event_name == 'pull_request' || github.event.inputs.unit_tests }} + integration_tests: ${{ github.event_name == 'pull_request' || github.event.inputs.integration_tests }} + invocation_tests: ${{ github.event_name == 'pull_request' || github.event.inputs.invocation_tests }} + unit_test_args: ${{ github.event.inputs.unit_test_args }} + integration_test_args: ${{ github.event.inputs.integration_test_args }} + ref: ${{ github.ref }} + head-ref: ${{ github.head_ref }} + full-repo-name: ${{ github.event.pull_request.head.repo.full_name }} +{% endraw %} + app_package: {{ app_package }} + CLI_module: {{ CLI_module }} + CLI_path: {{ CLI_path }} + CLI_path_win: {{ CLI_path_win }} + executable_name: {{ executable_name }} + pytest_args: {{ pytest_args }} + secrets: + pre-commit-token: {{ '${{' }} secrets.{{ token_name }} {{ '|| secrets.GITHUB_TOKEN }}' }} + permissions: + id-token: write + contents: write diff --git a/.github/workflows/test_pre_python.yml.in b/.github/workflows/test_pre_python.yml.in index 7fbc90d..a5d8445 100644 --- a/.github/workflows/test_pre_python.yml.in +++ b/.github/workflows/test_pre_python.yml.in @@ -1,53 +1,12 @@ -name: test-pre-python -concurrency: - | # e.g. don't run simultaneously on the same branch (since we may commit to that branch) - {% raw %}ci-${{ format('{0}github.head_ref', 'refs/heads') || github.ref }}{% endraw %} - -env: - POETRY_VERSION: "1.4" - +name: Test pre-python on: workflow_dispatch: # manual invocation - jobs: test: - strategy: - fail-fast: false - matrix: - python-version: - - "3.13-dev" - os: - - ubuntu-latest - - macos-13 - - windows-latest - - runs-on: {% raw %}${{ matrix.os }}{% endraw %} - steps: - - uses: actions/checkout@v4 - with: - ref: {% raw %}${{ github.ref }}{% endraw %} - - - uses: actions/setup-python@v5 - with: - python-version: {% raw %}${{ matrix.python-version }}{% endraw %} - allow-prereleases: true - - - name: Install and configure poetry - run: | - python -m pip install poetry=={% raw %}${{ env.POETRY_VERSION }}{% endraw %} - poetry config virtualenvs.in-project true - poetry config installer.modern-installation false - - - name: Cache the virtualenv - uses: actions/cache@v4 - with: - path: ./.venv - key: {% raw %}${{ runner.os }}-test-${{ matrix.python-version }}-venv-${{ hashFiles('**/poetry.lock') }}{% endraw %} - - - name: Install dependencies - run: | - poetry install --without dev,pyinstaller - - - name: Run tests - run: | - poetry run python -m pytest {{ pytest_args }} + uses: hpcflow/github-support/.github/workflows/test-pre-python-impl.yml@main + with: +{% raw %} + ref: ${{ github.ref }} + head-ref: ${{ github.head_ref }} +{% endraw %} + pytest-args: {{ pytest_args }}