Files
DocsGPT/.github/workflows/ci.yml
T
Alex 4f0bf2cca8 feat: one-command installers for macOS, Linux and Windows
deployment/install.sh (curl | bash) and install.ps1 (irm | iex) check for
Docker, install uv when it is missing or older than 0.8 (pinned 0.12.15 via
Astral's installer), install or upgrade the docsgpt package with
`uv tool install`, and hand the terminal to `docsgpt up` with any arguments.
On Linux without Docker the shell installer offers get.docker.com. Both run
entirely inside a function, so a download cut short runs nothing.

Releases attach both scripts next to the Compose file, which is where
docs.ac/install and docs.ac/install.ps1 will point. installer-lint.yml runs
shellcheck and the PowerShell parser; docker-image-verify.yml now installs
through install.sh. README, Quickstart, Docker-Deploying and the changelog
lead with the one-liner.
2026-09-16 01:10:11 +01:00

222 lines
8.8 KiB
YAML

name: Build and push DocsGPT Docker image
# Runs for a release created by hand (the release event), or called by the
# backend-release workflow with the version it just tagged: GitHub never starts
# workflows from events GITHUB_TOKEN produces, so a bot-created release does not
# fire the release trigger on its own.
on:
release:
types: [published]
workflow_call:
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
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
env:
# The tag being published: passed in by the caller, or the release's own.
RELEASE_TAG: ${{ inputs.version || github.event.release.tag_name }}
jobs:
build:
if: github.repository == 'arc53/DocsGPT'
# Publishing jobs run in a GitHub Actions environment so the registry
# credentials can be scoped to it and protection rules (required reviewers,
# branch restrictions) applied in the repository settings.
environment: docker-hub
env:
# Public namespace the compose files pull from; the login secret only
# authenticates the push.
DOCKERHUB_NAMESPACE: arc53
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
# "" is the slim default image; "-docling" bakes the docling parser
# engine, its models and tesseract in (OCR-ready).
variant: ["", "-docling"]
runs-on: ${{ matrix.platform == 'linux/arm64' && 'ubuntu-24.04-arm' || 'ubuntu-latest' }}
permissions:
contents: read
packages: write
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
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
with:
driver: docker-container
install: true
- name: Login to DockerHub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to ghcr.io
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Image metadata (OCI labels)
id: meta
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
with:
images: |
${{ env.DOCKERHUB_NAMESPACE }}/docsgpt
ghcr.io/${{ github.repository_owner }}/docsgpt
labels: |
org.opencontainers.image.title=DocsGPT${{ matrix.variant }}
org.opencontainers.image.version=${{ env.RELEASE_TAG }}
- name: Build and push platform-specific images
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
with:
file: './docsgpt/Dockerfile'
platforms: ${{ matrix.platform }}
context: .
push: true
build-args: |
EXTRAS=${{ matrix.variant == '-docling' && 'docling' || '' }}
INSTALL_TESSERACT=${{ matrix.variant == '-docling' && 'true' || 'false' }}
tags: |
${{ env.DOCKERHUB_NAMESPACE }}/docsgpt:${{ env.RELEASE_TAG }}${{ matrix.variant }}-${{ matrix.platform == 'linux/arm64' && 'arm64' || 'amd64' }}
ghcr.io/${{ github.repository_owner }}/docsgpt:${{ env.RELEASE_TAG }}${{ matrix.variant }}-${{ matrix.platform == 'linux/arm64' && 'arm64' || 'amd64' }}
labels: ${{ steps.meta.outputs.labels }}
provenance: false
sbom: false
cache-from: type=registry,ref=${{ env.DOCKERHUB_NAMESPACE }}/docsgpt:latest${{ matrix.variant }}
cache-to: type=inline
manifest:
if: github.repository == 'arc53/DocsGPT'
# Publishing jobs run in a GitHub Actions environment so the registry
# credentials can be scoped to it and protection rules (required reviewers,
# branch restrictions) applied in the repository settings.
environment: docker-hub
env:
# Public namespace the compose files pull from; the login secret only
# authenticates the push.
DOCKERHUB_NAMESPACE: arc53
needs: build
strategy:
matrix:
variant: ["", "-docling"]
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
with:
driver: docker-container
install: true
- name: Login to DockerHub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to ghcr.io
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push multi-arch manifests
env:
TAG: ${{ env.RELEASE_TAG }}${{ 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` 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" $moving; do
docker manifest create "$repo:$name" \
--amend "$repo:$TAG-amd64" \
--amend "$repo:$TAG-arm64"
docker manifest push "$repo:$name"
done
done
release-assets:
if: github.repository == 'arc53/DocsGPT'
needs: manifest
runs-on: ubuntu-latest
permissions:
contents: write
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
# The installers are served from these assets: docs.ac/install redirects to
# releases/latest/download/install.sh (and install.ps1), so the script a
# user runs always comes from the newest release.
- name: Attach the standalone compose file and the installers to the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: ${{ env.RELEASE_TAG }}
run: |
gh release upload "$TAG" \
deployment/docker-compose-standalone.yaml \
deployment/install.sh \
deployment/install.ps1 \
--clobber