commit: 72df87d671d856d01b3f4e5924ca4e66a1b77446 Author: Brian Harring <ferringb <AT> gmail <DOT> com> AuthorDate: Sun Nov 9 15:38:56 2025 +0000 Commit: Brian Harring <ferringb <AT> gmail <DOT> com> CommitDate: Thu Nov 27 15:16:28 2025 +0000 URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcore.git/commit/?id=72df87d6
chore: rework release workflow to reuse the tests workflow. High level description of changes: * Add multiple release-test-* branch targets as a way to flex and test the release pathway. This includes wiring test pypi in. The test pypi pkgcore project is under my account which I'll transfer once the PR lands and I figure out the 'how'. * The release process now runs the full test suite. This is being done for obvious reasons, but particularly since the previous intermixing via `.[test,docs]` is what hid the issue at the GH level. I'll resolve the underlying python level tests OOB. * To support reusing the test workflow, the checkout processes now uses a custom action that can pivot between git cloning, or using a GH artifact (IE, the release tarball being tested). https://github.com/pkgcore/gh-actions/blob/179e77c1ab499e19171b3c0c28a64e3fc5dcad8a/get-source/action.yml shows why an action encapsulating this was necessary. lesser stuff: * disable format check for releases. If we've tagged, by the time the tag is in github we have to just accept any format violations. * The publish code is duplicated because pypi upload doesn't support being invoked from reusable workflows. And GH doesn't support the yaml spec fully (no <<:*), thus just violating DRY. Moving that to an in repo action is my intention down the line. * I turned off 'draft' for github publishing. If we publish to PyPI, the source has to be publically available. I also forced the github release to be first for this reason (if it fails, no pypi release). * Since I broke out actions, I also moved the VCS check into it. Things like this will get centralized since we have 4 projects and copypasta for GH is pain. Closes: pkgcore/pkgcore#455 Signed-off-by: Brian Harring <ferringb <AT> gmail.com> .github/workflows/release.yml | 132 +++++++++++++++++++++++++++++------------- .github/workflows/test.yml | 45 +++++++++----- Makefile | 7 +++ 3 files changed, 128 insertions(+), 56 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4a0b9da8..bd615ba4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,34 +2,26 @@ name: release on: push: - branches: [deploy] + branches: [release-test-pypi, release-test-github, release-test-full] tags: [v*] workflow_dispatch: + jobs: - build-and-deploy: + build: runs-on: ubuntu-latest - environment: release - - permissions: - id-token: write # Used to authenticate to PyPI via OIDC - - contents: write # Used to authenticate github release publish + outputs: + release-artifact-id: ${{ steps.upload-release.outputs.artifact-id }} + wheel-artifact-id: ${{ steps.upload-wheel.outputs.artifact-id }} + artifact-runner: ${{ github.job }} steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Reject any VCS dependencies - shell: python - run: | - import re, tomllib - manifest = tomllib.load(open('pyproject.toml', 'rb')) - deps = manifest['build-system']['requires'] - deps.extend(manifest['project']['dependencies']) - if rejects := list(filter(re.compile(r'@[^+]+').search, deps)): - rejects = " \n".join(sorted(rejects)) - raise Exception(f'VCS dependencies were detected in [build-system]:\n {rejects}') + continue-on-error: ${{ github.ref_type == 'branch' && github.ref_name != 'release-test-full' }} + uses: pkgcore/gh-actions/reject-python-vcs-deps@main - name: Set up Python 3.13 uses: actions/setup-python@v5 @@ -41,40 +33,98 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install build ".[test,doc]" - - - name: Test with pytest - env: - PY_COLORS: 1 # forcibly enable pytest colors - run: pytest + pip install build ".[doc]" - - name: Build sdist + - name: Build the release run: | - git clean -fxd - make man - make sdist - - - name: Build wheel - run: make wheel + make release - name: Output dist file info run: | sha512sum dist/* + echo ::group::Release contents tar -ztf dist/*.tar.gz | sort + echo ::endgroup:: + echo ::group::All generated content in dist + find . + echo ::endgroup:: + + - name: Upload wheel + id: upload-wheel + uses: actions/upload-artifact@v5 + with: + name: wheel-release + path: dist/*.whl + if-no-files-found: error - - uses: actions/upload-artifact@v4 + - name: Upload release source + id: upload-release + uses: actions/upload-artifact@v5 with: - name: results - path: dist/* + name: release-source + path: dist/*.tar.gz + if-no-files-found: error + + test: + needs: [build] + uses: ./.github/workflows/test.yml + with: + release-artifact-id: ${{ needs.build.outputs.release-artifact-id }} + format-check: false - - name: publish - uses: pypa/gh-action-pypi-publish@release/v1 - if: startsWith(github.ref, 'refs/tags/') + publish: + if: github.ref_type == 'tag' + needs: [build, test] + environment: release + permissions: + id-token: write # Used to authenticate to PyPI via OIDC + contents: write # release uploads + runs-on: ubuntu-latest - - name: Create GitHub release - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') + steps: + - &common_download_artifacts + name: Download artifacts + uses: actions/download-artifact@v5 + with: + merge-multiple: true # store both in the root, not in named directories + artifact-ids: ${{ needs.build.outputs.release-artifact-id }},${{ needs.build.outputs.wheel-artifact-id }} + + - name: Publish github source + uses: softprops/action-gh-release@v2 with: - files: dist/*.tar.gz + files: '*.tar.*' + fail_on_unmatched_files: true + + - name: Publish to PyPi server + uses: pypa/gh-action-pypi-publish@release/v1.13 + with: + packages-dir: . + + test-publish: + # use the full form to ensure insane tags and errors in 'on' filter still don't kick. + if: github.ref_type == 'branch' + needs: [build, test] + environment: test-release + permissions: + id-token: write # Used to authenticate to PyPI via OIDC + contents: write # release uploads- + runs-on: ubuntu-latest + + steps: + - *common_download_artifacts + - name: Publish github source + uses: softprops/action-gh-release@v2 + if: github.ref_name == 'release-test-github' || github.ref_name == 'release-test-full' + with: + files: '*.tar.*' fail_on_unmatched_files: true draft: true + + - name: Publish to Test PyPi server + if: github.ref_name == 'release-test-pypi' || github.ref_name == 'release-test-full' + uses: pypa/gh-action-pypi-publish@release/v1.13 + with: + packages-dir: . + repository-url: https://test.pypi.org/legacy/ + # attestations are bound in a way re-releasing isn't possible. Disable for tests. + attestations: false \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5037b7d7..5ee22670 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,10 +2,20 @@ name: test on: push: - branches-ignore: [deploy] + branches-ignore: [release-test-*] pull_request: branches: [master] - + workflow_call: + inputs: + release-artifact-id: + required: false + type: string + default: '' + description: The artifact-id to run the tests against. + format-check: + type: boolean + default: true + description: Run the ruff format check. This should only be disabled for releases. jobs: build: runs-on: ${{ matrix.os }} @@ -32,8 +42,10 @@ jobs: fail-fast: false steps: - - name: Checkout code - uses: actions/checkout@v4 + - name: Checkout pkgcore + uses: pkgcore/gh-actions/get-source@main + with: + artifact-id: ${{ inputs.release-artifact-id }} - name: Pin dependencies to minimal versions if: ${{ matrix.deps == 'minimal-deps' }} @@ -77,12 +89,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout pkgcore - uses: actions/checkout@v4 + uses: pkgcore/gh-actions/get-source@main with: + artifact-id: ${{ inputs.release-artifact-id }} path: pkgcore - name: Checkout pkgcheck - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: pkgcore/pkgcheck path: pkgcheck @@ -99,7 +112,7 @@ jobs: - name: Install pip dependencies run: | python -m pip install --upgrade pip - pip install -e "./pkgcore" + pip install "./pkgcore" pip install "./pkgcheck[test]" - name: Test with pytest @@ -112,12 +125,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout pkgcore - uses: actions/checkout@v4 + uses: pkgcore/gh-actions/get-source@main with: + artifact-id: ${{ inputs.release-artifact-id }} path: pkgcore - - name: Checkout pkgdev - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: pkgcore/pkgdev path: pkgdev @@ -134,7 +147,7 @@ jobs: - name: Install pip dependencies run: | python -m pip install --upgrade pip - pip install -e "./pkgcore" + pip install "./pkgcore" pip install "./pkgdev[test]" - name: Test with pytest @@ -145,9 +158,10 @@ jobs: format: runs-on: ubuntu-latest + if: inputs.format-check steps: - - name: Checkout code - uses: actions/checkout@v4 + - name: Checkout pkgcore + uses: actions/checkout@v5 - uses: astral-sh/ruff-action@v3 with: args: "format --check --diff" @@ -156,8 +170,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout pkgcore - uses: actions/checkout@v4 + uses: pkgcore/gh-actions/get-source@main with: + artifact-id: ${{ inputs.release-artifact-id }} path: pkgcore - name: Checkout gentoo @@ -174,7 +189,7 @@ jobs: - name: Install pip dependencies run: | python -m pip install --upgrade pip - pip install -e "./pkgcore" + pip install "./pkgcore" - name: Run pmaint regen working-directory: ./gentoo diff --git a/Makefile b/Makefile index 4673a9a1..f3fe42c1 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,17 @@ man html: html: man +.PHONY: docs +docs: man html + .PHONY: sdist wheel sdist wheel: $(PYTHON) -m build --$@ +sdist: man + +.PHONY: release +release: sdist wheel .PHONY: clean clean:
