agent-zero/.github/workflows/docker-publish.yml
Alessandro 6664fc7f38
Some checks failed
Build And Publish Docker Images / plan (push) Has been cancelled
Build And Publish Docker Images / build (push) Has been cancelled
Free runner disk before Docker publish
The multi-platform Docker publish job can exhaust the hosted runner disk before BuildKit finishes, causing ENOSPC failures during log writing and cleanup.

Remove unused hosted toolchains and stale local Docker data before QEMU and Buildx setup so release builds have more room without changing Docker image inputs or install scripts.
2026-05-15 19:27:49 +02:00

257 lines
8.9 KiB
YAML

name: Build And Publish Docker Images
on:
push:
branches:
- "testing"
- "ready"
- "main"
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "Optional release tag to rebuild, for example v1.21"
required: false
type: string
env:
# Non-main branches publish a Docker tag with the same name as the branch.
ALLOWED_BRANCHES: "testing ready main"
MAIN_BRANCH: "main"
RELEASE_TAG_REGEX: "^v([0-9]+)\\.([0-9]+)$"
MIN_RELEASE_MAJOR: "1"
MIN_RELEASE_MINOR: "0"
DOCKERFILE_DIR: "docker/run"
DOCKERFILE_PATH: "docker/run/Dockerfile"
DOCKER_IMAGE_NAME: "agent-zero"
DOCKER_PLATFORMS: "linux/amd64,linux/arm64"
permissions:
contents: read
jobs:
plan:
if: github.repository == 'agent0ai/agent-zero'
runs-on: ubuntu-latest
outputs:
has_work: ${{ steps.plan.outputs.has_work }}
matrix: ${{ steps.plan.outputs.matrix }}
steps:
- name: Validate Docker Hub secrets
env:
DOCKERHUB_ORG: ${{ secrets.DOCKERHUB_ORG }}
DOCKERHUB_OAT_TOKEN: ${{ secrets.DOCKERHUB_OAT_TOKEN }}
run: |
if [[ -z "$DOCKERHUB_ORG" || -z "$DOCKERHUB_OAT_TOKEN" ]]; then
echo "::error::Missing DOCKERHUB_ORG or DOCKERHUB_OAT_TOKEN secret."
exit 1
fi
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch remote branches and tags
run: git fetch --force --tags origin '+refs/heads/*:refs/remotes/origin/*'
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_ORG }}
password: ${{ secrets.DOCKERHUB_OAT_TOKEN }}
- name: Plan Docker publish targets
id: plan
env:
EVENT_NAME: ${{ github.event_name }}
SOURCE_REF_NAME: ${{ github.ref_name }}
SOURCE_REF_TYPE: ${{ github.ref_type }}
BEFORE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }}
AFTER_SHA: ${{ github.event_name == 'push' && github.sha || '' }}
MANUAL_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || '' }}
DOCKER_IMAGE_REPO: ${{ format('{0}/{1}', secrets.DOCKERHUB_ORG, env.DOCKER_IMAGE_NAME) }}
run: python3 .github/scripts/docker_release_plan.py plan
build:
if: needs.plan.outputs.has_work == 'true'
needs: plan
runs-on: ubuntu-latest
permissions:
contents: write
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.plan.outputs.matrix) }}
concurrency:
group: docker-publish-${{ github.repository }}-${{ matrix.branch }}
cancel-in-progress: false
steps:
- name: Check out repository
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch remote branches and tags
run: git fetch --force --tags origin '+refs/heads/*:refs/remotes/origin/*'
- name: Validate Docker Hub secrets
env:
DOCKERHUB_ORG: ${{ secrets.DOCKERHUB_ORG }}
DOCKERHUB_OAT_TOKEN: ${{ secrets.DOCKERHUB_OAT_TOKEN }}
run: |
if [[ -z "$DOCKERHUB_ORG" || -z "$DOCKERHUB_OAT_TOKEN" ]]; then
echo "::error::Missing DOCKERHUB_ORG or DOCKERHUB_OAT_TOKEN secret."
exit 1
fi
- name: Free runner disk space
run: |
echo "Disk before cleanup:"
df -h /
docker system df || true
sudo rm -rf \
/opt/az \
/opt/ghc \
/opt/hostedtoolcache/CodeQL \
/usr/local/.ghcup \
/usr/local/lib/android \
/usr/local/share/boost \
/usr/share/dotnet
sudo apt-get clean
docker system prune -af --volumes || true
echo "Disk after cleanup:"
df -h /
docker system df || true
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_ORG }}
password: ${{ secrets.DOCKERHUB_OAT_TOKEN }}
- name: Re-resolve Docker tags for this build
id: resolve
env:
EVENT_NAME: ${{ github.event_name }}
SOURCE_REF_NAME: ${{ github.ref_name }}
SOURCE_REF_TYPE: ${{ github.ref_type }}
BEFORE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }}
AFTER_SHA: ${{ github.event_name == 'push' && github.sha || '' }}
MANUAL_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || '' }}
DOCKER_IMAGE_REPO: ${{ format('{0}/{1}', secrets.DOCKERHUB_ORG, env.DOCKER_IMAGE_NAME) }}
TARGET_BRANCH: ${{ matrix.branch }}
TARGET_TAG: ${{ matrix.source_tag }}
TARGET_MODE: ${{ matrix.mode }}
TARGET_PUBLISH_VERSION: ${{ matrix.publish_version }}
TARGET_PUBLISH_BRANCH_TAG: ${{ matrix.publish_branch_tag }}
run: python3 .github/scripts/docker_release_plan.py resolve-build
- name: Skip when target is no longer eligible
if: steps.resolve.outputs.should_build != 'true'
run: echo "${{ steps.resolve.outputs.skip_reason }}"
- name: Set cache date
if: steps.resolve.outputs.should_build == 'true'
id: cache_date
run: echo "value=$(date -u +%Y-%m-%d:%H:%M:%S)" >> "$GITHUB_OUTPUT"
- name: Build and push Docker image
if: steps.resolve.outputs.should_build == 'true'
uses: docker/build-push-action@v6
with:
context: ${{ env.DOCKERFILE_DIR }}
file: ${{ env.DOCKERFILE_PATH }}
platforms: ${{ env.DOCKER_PLATFORMS }}
push: true
tags: ${{ steps.resolve.outputs.tags }}
build-args: |
BRANCH=${{ matrix.branch }}
CACHE_DATE=${{ steps.cache_date.outputs.value }}
- name: Resolve GitHub release target
if: steps.resolve.outputs.should_build == 'true'
id: release_plan
env:
EVENT_NAME: ${{ github.event_name }}
SOURCE_REF_NAME: ${{ github.ref_name }}
SOURCE_REF_TYPE: ${{ github.ref_type }}
BEFORE_SHA: ${{ github.event_name == 'push' && github.event.before || '' }}
AFTER_SHA: ${{ github.event_name == 'push' && github.sha || '' }}
MANUAL_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || '' }}
DOCKER_IMAGE_REPO: ${{ format('{0}/{1}', secrets.DOCKERHUB_ORG, env.DOCKER_IMAGE_NAME) }}
TARGET_BRANCH: ${{ matrix.branch }}
TARGET_TAG: ${{ matrix.source_tag }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
OPENROUTER_MODEL_NAME: ${{ vars.OPENROUTER_MODEL_NAME }}
run: python3 .github/scripts/docker_release_plan.py resolve-release
- name: Skip GitHub release
if: steps.resolve.outputs.should_build == 'true' && steps.release_plan.outputs.should_release != 'true'
run: echo "${{ steps.release_plan.outputs.skip_reason }}"
- name: Create or update GitHub release
if: steps.resolve.outputs.should_build == 'true' && steps.release_plan.outputs.should_release == 'true'
uses: actions/github-script@v7
env:
RELEASE_TAG: ${{ steps.release_plan.outputs.release_tag }}
RELEASE_NAME: ${{ steps.release_plan.outputs.release_name }}
RELEASE_BODY: ${{ steps.release_plan.outputs.release_body }}
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const tag = process.env.RELEASE_TAG;
const name = process.env.RELEASE_NAME;
const body = process.env.RELEASE_BODY;
try {
const existing = await github.rest.repos.getReleaseByTag({
owner,
repo,
tag,
});
await github.rest.repos.updateRelease({
owner,
repo,
release_id: existing.data.id,
tag_name: tag,
name,
body,
draft: false,
prerelease: false,
make_latest: "true",
});
core.info(`Updated release ${tag}`);
} catch (error) {
if (error.status !== 404) {
throw error;
}
await github.rest.repos.createRelease({
owner,
repo,
tag_name: tag,
name,
body,
draft: false,
prerelease: false,
make_latest: "true",
});
core.info(`Created release ${tag}`);
}