|
|
@@ -44,7 +44,7 @@ jobs:
|
|
|
cache: pip
|
|
|
|
|
|
- name: Install build tooling
|
|
|
- run: python -m pip install --upgrade build twine
|
|
|
+ run: python -m pip install --upgrade build twine packaging
|
|
|
|
|
|
- name: Install documentation toolchain
|
|
|
run: python -m pip install -r requirements.txt
|
|
|
@@ -60,6 +60,20 @@ jobs:
|
|
|
- name: Check package metadata
|
|
|
run: twine check dist/*
|
|
|
|
|
|
+ - name: Verify the release tag
|
|
|
+ # Both checks run here, in the unprivileged build job, against the wheel that becomes this
|
|
|
+ # run's artifact, so neither publish job has to check out the repository or execute its
|
|
|
+ # scripts while holding id-token: write. A failure here skips every downstream job.
|
|
|
+ if: startsWith(github.ref, 'refs/tags/v')
|
|
|
+ env:
|
|
|
+ TAG: ${{ github.ref_name }}
|
|
|
+ run: |
|
|
|
+ [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]] || {
|
|
|
+ echo "Ref '$TAG' is not a release tag of the form vX.Y.Z[-designation]"
|
|
|
+ exit 1
|
|
|
+ }
|
|
|
+ python scripts/verify_release_tag.py "$TAG" dist/*.whl
|
|
|
+
|
|
|
- name: Upload package artifacts
|
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
|
with:
|
|
|
@@ -276,15 +290,14 @@ jobs:
|
|
|
name: Publish package to Test PyPI
|
|
|
runs-on: ubuntu-latest
|
|
|
needs: [smoke-test, cli-smoke-test, verify-dependencies, verify-sdist]
|
|
|
- # Publishing always requires a v* tag ref: a tag push publishes to Test PyPI
|
|
|
- # automatically, and a manual dispatch does the same when the chosen ref is a v* tag.
|
|
|
- # Branch dispatches still run the build, verify, and smoke-test jobs (a useful dry run)
|
|
|
- # but the publish job is skipped. Production PyPI publishing is intentionally absent
|
|
|
- # during the v4.6.x preview; it arrives with the v4.7.0 feature branch.
|
|
|
- # startsWith() only routes to this job (workflow `if:` expressions cannot regex-match);
|
|
|
- # the exact tag format (v<release.yaml version>) is enforced below by the "Enforce
|
|
|
- # release tag format" step and scripts/verify_release_tag.py before any upload.
|
|
|
- if: startsWith(github.ref, 'refs/tags/v') && (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
|
|
|
+ # Test PyPI remains an opt-in rehearsal channel: only a manual dispatch from a v* tag publishes
|
|
|
+ # here, so the publish path can be exercised against a real index without touching production.
|
|
|
+ # A branch dispatch still runs the build, verify, and smoke-test jobs as a dry run, with both
|
|
|
+ # publish jobs skipped.
|
|
|
+ # startsWith() is only a coarse route to this job; workflow if: expressions cannot regex-match.
|
|
|
+ # The tag format and the tag-to-wheel version match are enforced in the build job, which fails
|
|
|
+ # the whole run before anything is uploaded.
|
|
|
+ if: github.event_name == 'workflow_dispatch' && startsWith(github.ref, 'refs/tags/v')
|
|
|
environment:
|
|
|
name: testpypi
|
|
|
url: https://test.pypi.org/p/netbox
|
|
|
@@ -293,36 +306,45 @@ jobs:
|
|
|
id-token: write
|
|
|
|
|
|
steps:
|
|
|
- - name: Enforce release tag format
|
|
|
- env:
|
|
|
- TAG: ${{ github.ref_name }}
|
|
|
- run: |
|
|
|
- [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]] || {
|
|
|
- echo "Ref '$TAG' is not a release tag of the form vX.Y.Z[-designation]"
|
|
|
- exit 1
|
|
|
- }
|
|
|
-
|
|
|
- - name: Check out repository
|
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
+ - name: Download package artifacts
|
|
|
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
|
with:
|
|
|
- persist-credentials: false
|
|
|
- - name: Set up Python
|
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
|
+ name: python-package-distributions
|
|
|
+ path: dist/
|
|
|
+
|
|
|
+ - name: Publish package distributions to Test PyPI
|
|
|
+ uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
|
with:
|
|
|
- python-version: '3.12'
|
|
|
- - name: Install tooling
|
|
|
- run: python -m pip install --upgrade pip packaging
|
|
|
+ repository-url: https://test.pypi.org/legacy/
|
|
|
+ print-hash: true
|
|
|
|
|
|
+ publish-pypi:
|
|
|
+ name: Publish package to PyPI
|
|
|
+ runs-on: ubuntu-latest
|
|
|
+ needs: [smoke-test, cli-smoke-test, verify-dependencies, verify-sdist]
|
|
|
+ # A v* tag push is the production path. Test PyPI is an opt-in rehearsal rather than a promotion
|
|
|
+ # stage, so it is deliberately absent from this job's needs: an outage, a duplicate filename, or
|
|
|
+ # a misconfiguration on a test service must not block a verified production release. The four
|
|
|
+ # verification jobs above already ran against these exact artifacts. The protected pypi
|
|
|
+ # environment supplies the deliberate approval step, and because accepted PyPI filenames cannot
|
|
|
+ # be replaced or reused, a filename the index already holds fails the job instead of being
|
|
|
+ # skipped.
|
|
|
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
|
+ environment:
|
|
|
+ name: pypi
|
|
|
+ url: https://pypi.org/p/netbox
|
|
|
+ permissions:
|
|
|
+ contents: read
|
|
|
+ id-token: write
|
|
|
+
|
|
|
+ steps:
|
|
|
- name: Download package artifacts
|
|
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
|
with:
|
|
|
name: python-package-distributions
|
|
|
path: dist/
|
|
|
|
|
|
- - name: Verify the git tag matches the built version
|
|
|
- run: python scripts/verify_release_tag.py "${{ github.ref_name }}" dist/*.whl
|
|
|
-
|
|
|
- - name: Publish package distributions to Test PyPI
|
|
|
+ - name: Publish package distributions to PyPI
|
|
|
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
|
with:
|
|
|
- repository-url: https://test.pypi.org/legacy/
|
|
|
+ print-hash: true
|