Files
DocsGPT/.github/workflows/backend-release.yml
T
Alex fc5992c5d4 ci: publish the docsgpt-sandbox image
deployment/k8s/deployments/sandbox-deploy.yaml pulls arc53/docsgpt-sandbox,
which has never been pushed anywhere: Compose builds the runner from the
checkout (`build: ./sandbox`), but Kubernetes cannot build, so enabling code
execution on a cluster failed on an image that does not exist.

Build and push it like the other two images: `develop` on a push to main that
touches deployment/sandbox, and `<version>` plus `latest` when the release
workflow calls it. Release and develop live in one file here rather than two,
because the runner changes rarely and the only difference is which tags move.
The tag comes from the inputs and the release payload, not from
`github.event_name`, which is `push` when backend-release calls this.
2026-09-12 22:06:27 +01:00

148 lines
5.0 KiB
YAML

name: Backend release
# A version bump on main tags the commit, creates the GitHub release, then
# publishes the backend, frontend and sandbox Docker images and the PyPI
# package by calling those workflows.
# The release is created with GITHUB_TOKEN, and GitHub never starts workflows
# from events that token produces, so the `release: published` triggers on the
# publish workflows would not fire (0.18.0 got no images that way). Releases
# created by hand still publish through those triggers.
on:
push:
branches: [main]
paths:
- 'docsgpt/version.py'
workflow_dispatch:
permissions: {}
concurrency:
group: backend-release
cancel-in-progress: false
jobs:
release:
if: github.repository == 'arc53/DocsGPT'
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
version: ${{ steps.ver.outputs.version }}
# The publish jobs run only for a release this run created. A release
# that already existed was either made by hand (its release event
# published it) or made by an earlier run: re-run that run's failed jobs.
created: ${{ steps.check.outputs.release == 'missing' }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false
- name: Read version from docsgpt/version.py
id: ver
run: |
VERSION=$(python3 -c "g={}; exec(open('docsgpt/version.py').read(), g); print(g['__version__'])")
if [ -z "$VERSION" ]; then
echo "::error::Could not read __version__ from docsgpt/version.py"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Resolved version: $VERSION"
- name: Check what already exists
id: check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.ver.outputs.version }}
run: |
# The tag and the release are checked separately: a run that pushed
# the tag and then failed to create the release must still create
# it (and publish) when re-run.
if git ls-remote --tags --exit-code origin "refs/tags/$VERSION" >/dev/null 2>&1; then
echo "tag=exists" >> "$GITHUB_OUTPUT"
echo "Tag $VERSION already exists on origin."
else
echo "tag=missing" >> "$GITHUB_OUTPUT"
fi
if gh release view "$VERSION" >/dev/null 2>&1; then
echo "release=exists" >> "$GITHUB_OUTPUT"
echo "Release $VERSION already exists — nothing to publish."
else
echo "release=missing" >> "$GITHUB_OUTPUT"
fi
- name: Create and push tag
if: steps.check.outputs.tag == 'missing'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.ver.outputs.version }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "$VERSION"
# Authenticate this single push via a one-shot tokenized remote URL
# instead of leaving GITHUB_TOKEN persisted in .git/config (see
# persist-credentials: false on the checkout step above).
git push \
"https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" \
"$VERSION"
- name: Create GitHub release
if: steps.check.outputs.release == 'missing'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.ver.outputs.version }}
run: |
gh release create "$VERSION" \
--title "v$VERSION" \
--generate-notes
docker:
needs: release
if: needs.release.outputs.created == 'true'
uses: $/.github/workflows/ci.yml
with:
version: ${{ needs.release.outputs.version }}
secrets:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
permissions:
contents: write # release-assets attaches the compose file to the release
packages: write
frontend:
needs: release
if: needs.release.outputs.created == 'true'
uses: $/.github/workflows/cife.yml
with:
version: ${{ needs.release.outputs.version }}
secrets:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
permissions:
contents: read
packages: write
sandbox:
needs: release
if: needs.release.outputs.created == 'true'
uses: $/.github/workflows/sandbox-image.yml
with:
version: ${{ needs.release.outputs.version }}
secrets:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
permissions:
contents: read
packages: write
pypi:
needs: release
if: needs.release.outputs.created == 'true'
uses: $/.github/workflows/pypi-publish.yml
with:
version: ${{ needs.release.outputs.version }}
permissions:
contents: read
id-token: write