mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-12 18:15:33 +00:00
Merge pull request #2765 from arc53/fix/release-recovery-and-attestations
ci: fix PyPI publishing from the release chain, make image builds recoverable
This commit is contained in:
4 files changed
+125
-22
No files matched your search
@@ -14,11 +14,25 @@ on:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -51,6 +65,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
# Build the source the tag names, not whatever the run was started
|
||||
# from: a manual run dispatched off main would otherwise publish the
|
||||
# current branch under an older version's tags. Resolved under
|
||||
# refs/tags/ so a version that is also a branch name cannot win, and a
|
||||
# version with no tag fails here instead of mislabelling an image.
|
||||
# Falls back to the run's own ref for the push that tags `develop`.
|
||||
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || github.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
@@ -142,15 +163,24 @@ jobs:
|
||||
- name: Create and push multi-arch manifests
|
||||
env:
|
||||
TAG: ${{ env.RELEASE_TAG }}${{ matrix.variant }}
|
||||
# A stable release moves `latest`; a prerelease published by hand
|
||||
# moves only its own tag (the release trigger fires for those too).
|
||||
LATEST: ${{ (inputs.version || !github.event.release.prerelease) && format('latest{0}', matrix.variant) || '' }}
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
# Raw facts; the shell below decides from them what `latest` does.
|
||||
IS_PRERELEASE: ${{ github.event.release.prerelease || false }}
|
||||
MOVE_LATEST: ${{ inputs.move_latest }}
|
||||
run: |
|
||||
set -e
|
||||
# $LATEST is deliberately unquoted: it is empty for a prerelease, and
|
||||
# an empty word would create a manifest named "$repo:".
|
||||
# `latest` follows this build, except for a release marked prerelease
|
||||
# (the release trigger fires for those too) or a manual run that asked
|
||||
# it not to. MOVE_LATEST is empty for a release event, where only the
|
||||
# prerelease flag decides.
|
||||
moving="latest${VARIANT}"
|
||||
if [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then
|
||||
moving=""
|
||||
fi
|
||||
# $moving is deliberately unquoted: an empty word would create a
|
||||
# manifest named "$repo:".
|
||||
for repo in "$DOCKERHUB_NAMESPACE/docsgpt" "ghcr.io/${{ github.repository_owner }}/docsgpt"; do
|
||||
for name in "$TAG" $LATEST; do
|
||||
for name in "$TAG" $moving; do
|
||||
docker manifest create "$repo:$name" \
|
||||
--amend "$repo:$TAG-amd64" \
|
||||
--amend "$repo:$TAG-arm64"
|
||||
@@ -167,6 +197,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
# Build the source the tag names, not whatever the run was started
|
||||
# from: a manual run dispatched off main would otherwise publish the
|
||||
# current branch under an older version's tags. Resolved under
|
||||
# refs/tags/ so a version that is also a branch name cannot win, and a
|
||||
# version with no tag fails here instead of mislabelling an image.
|
||||
# Falls back to the run's own ref for the push that tags `develop`.
|
||||
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || github.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Attach the standalone compose file to the release
|
||||
|
||||
@@ -14,11 +14,25 @@ on:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -26,10 +40,6 @@ permissions:
|
||||
env:
|
||||
# The tag being published: passed in by the caller, or the release's own.
|
||||
RELEASE_TAG: ${{ inputs.version || github.event.release.tag_name }}
|
||||
# A stable release also moves `latest`. A prerelease published by hand moves
|
||||
# only its own tag: the release trigger fires for those too, and they must not
|
||||
# become `latest`.
|
||||
MOVING_TAG: ${{ (inputs.version || !github.event.release.prerelease) && 'latest' || '' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -58,6 +68,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
# Build the source the tag names, not whatever the run was started
|
||||
# from: a manual run dispatched off main would otherwise publish the
|
||||
# current branch under an older version's tags. Resolved under
|
||||
# refs/tags/ so a version that is also a branch name cannot win, and a
|
||||
# version with no tag fails here instead of mislabelling an image.
|
||||
# Falls back to the run's own ref for the push that tags `develop`.
|
||||
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || github.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
@@ -143,13 +160,23 @@ jobs:
|
||||
- name: Create and push multi-arch manifests
|
||||
env:
|
||||
TAG: ${{ env.RELEASE_TAG }}
|
||||
MOVING: ${{ env.MOVING_TAG }}
|
||||
# Raw facts; the shell below decides from them what `latest` does.
|
||||
IS_PRERELEASE: ${{ github.event.release.prerelease || false }}
|
||||
MOVE_LATEST: ${{ inputs.move_latest }}
|
||||
run: |
|
||||
set -e
|
||||
# $MOVING is deliberately unquoted: it is empty for a prerelease, and
|
||||
# an empty word would create a manifest named "$repo:".
|
||||
# `latest` follows this build, except for a release marked prerelease
|
||||
# (the release trigger fires for those too) or a manual run that asked
|
||||
# it not to. MOVE_LATEST is empty for a release event, where only the
|
||||
# prerelease flag decides.
|
||||
moving=latest
|
||||
if [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then
|
||||
moving=""
|
||||
fi
|
||||
# $moving is deliberately unquoted: an empty word would create a
|
||||
# manifest named "$repo:".
|
||||
for repo in "$DOCKERHUB_NAMESPACE/docsgpt-fe" "ghcr.io/${{ github.repository_owner }}/docsgpt-fe"; do
|
||||
for name in "$TAG" $MOVING; do
|
||||
for name in "$TAG" $moving; do
|
||||
docker manifest create "$repo:$name" \
|
||||
--amend "$repo:$TAG-amd64" \
|
||||
--amend "$repo:$TAG-arm64"
|
||||
|
||||
@@ -6,6 +6,13 @@ name: Publish to PyPI
|
||||
# creates with GITHUB_TOKEN never fires the release trigger); a release created
|
||||
# by hand publishes through that trigger; a manual run publishes to TestPyPI
|
||||
# by default.
|
||||
#
|
||||
# Attestations are on only when this file is the workflow that STARTED the run.
|
||||
# A PEP 740 attestation records the entry workflow in its certificate, while
|
||||
# trusted publishing matches the called workflow, so when backend-release calls
|
||||
# this one the two disagree and PyPI rejects the upload with "Certificate's
|
||||
# Build Config URI ... does not match expected Trusted Publisher". No publisher
|
||||
# configuration satisfies both, so the release chain publishes unattested.
|
||||
|
||||
on:
|
||||
release:
|
||||
@@ -116,6 +123,9 @@ jobs:
|
||||
path: dist/
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
||||
with:
|
||||
# Only when this workflow is the entry point: see the note at the top.
|
||||
attestations: ${{ contains(github.workflow_ref, '/pypi-publish.yml@') }}
|
||||
|
||||
publish-testpypi:
|
||||
if: inputs.target == 'testpypi'
|
||||
@@ -134,6 +144,8 @@ jobs:
|
||||
|
||||
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
||||
with:
|
||||
# Only when this workflow is the entry point: see the note at the top.
|
||||
attestations: ${{ contains(github.workflow_ref, '/pypi-publish.yml@') }}
|
||||
repository-url: https://test.pypi.org/legacy/
|
||||
# TestPyPI is a rehearsal target: a version that is already there
|
||||
# must not fail the run.
|
||||
|
||||
@@ -21,11 +21,25 @@ on:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Release tag to build and push (the images are tagged with it)
|
||||
type: string
|
||||
required: true
|
||||
move_latest:
|
||||
description: Also move the `latest` tag onto this build
|
||||
type: boolean
|
||||
default: true
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
@@ -38,10 +52,6 @@ permissions:
|
||||
env:
|
||||
# The version being published, or `develop` for a push to main.
|
||||
RELEASE_TAG: ${{ inputs.version || github.event.release.tag_name || 'develop' }}
|
||||
# A stable release also moves `latest`. A push to main moves nothing but
|
||||
# `develop`, and a prerelease published by hand moves only its own tag: the
|
||||
# release trigger fires for those too, and they must not become `latest`.
|
||||
MOVING_TAG: ${{ (inputs.version || (github.event.release.tag_name && !github.event.release.prerelease)) && 'latest' || '' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -70,6 +80,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
|
||||
with:
|
||||
# Build the source the tag names, not whatever the run was started
|
||||
# from: a manual run dispatched off main would otherwise publish the
|
||||
# current branch under an older version's tags. Resolved under
|
||||
# refs/tags/ so a version that is also a branch name cannot win, and a
|
||||
# version with no tag fails here instead of mislabelling an image.
|
||||
# Falls back to the run's own ref for the push that tags `develop`.
|
||||
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || github.ref }}
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
@@ -155,13 +172,23 @@ jobs:
|
||||
- name: Create and push multi-arch manifests
|
||||
env:
|
||||
TAG: ${{ env.RELEASE_TAG }}
|
||||
MOVING: ${{ env.MOVING_TAG }}
|
||||
# Raw facts; the shell below decides from them what `latest` does.
|
||||
IS_PRERELEASE: ${{ github.event.release.prerelease || false }}
|
||||
MOVE_LATEST: ${{ inputs.move_latest }}
|
||||
run: |
|
||||
set -e
|
||||
# $MOVING is deliberately unquoted: it is empty for a push to main,
|
||||
# and an empty word would create a manifest named "$repo:".
|
||||
# `latest` follows this build, except for the rolling `develop` build,
|
||||
# a release marked prerelease (the release trigger fires for those
|
||||
# too), or a manual run that asked it not to. MOVE_LATEST is empty for
|
||||
# a release event and for a push, where the other two rules decide.
|
||||
moving=latest
|
||||
if [ "$TAG" = develop ] || [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then
|
||||
moving=""
|
||||
fi
|
||||
# $moving is deliberately unquoted: an empty word would create a
|
||||
# manifest named "$repo:".
|
||||
for repo in "$DOCKERHUB_NAMESPACE/docsgpt-sandbox" "ghcr.io/${{ github.repository_owner }}/docsgpt-sandbox"; do
|
||||
for name in "$TAG" $MOVING; do
|
||||
for name in "$TAG" $moving; do
|
||||
docker manifest create "$repo:$name" \
|
||||
--amend "$repo:$TAG-amd64" \
|
||||
--amend "$repo:$TAG-arm64"
|
||||
|
||||
Reference in new issue
Block a user