mirror of
https://github.com/agent0ai/agent-zero.git
synced 2026-05-23 21:06:39 +00:00
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.
257 lines
8.9 KiB
YAML
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}`);
|
|
}
|