Automated release management for the HagiCode platform. This repository handles version monitoring, GitHub releases, and multi-architecture Docker image publishing to Edge ACR.
The HagiCode release repository manages:
- Version Monitoring: Detects new versions in Azure Blob Storage
- GitHub Releases: Creates GitHub releases with application packages
- Docker Multi-Arch Builds: Builds and publishes Docker images for linux/amd64 and linux/arm64
- Multi-Registry Publishing: Pushes Docker images to Azure ACR, Aliyun ACR, and DockerHub
- Publish Result Tracking: Automatically generates and uploads publish result JSON files to GitHub Releases
- Aliyun Image Sync: Syncs Azure ACR images to Aliyun ACR with automatic version discovery
- DockerHub Integration: Syncs images to DockerHub with username-based path format
- .NET 10 SDK
- Docker 20.10 or later with buildx support
- Azure Blob Storage access (SAS URL)
- GitHub personal access token (PAT)
- Edge ACR credentials (username, password, registry)
- jq (for JSON parsing in multi-arch verification)
# Clone repository
git clone https://github.com/your-org/hagicode-release.git
cd hagicode-release
# Run Nuke build (use version without v prefix)
./build.sh DockerRelease \
--ReleaseVersion "1.2.3" \
--AzureBlobSasUrl "https://..." \
--AzureAcrRegistry "hagicode.azurecr.io" \
--AzureAcrUsername "username" \
--AzureAcrPassword "password" \
--DockerPlatform "all"Important: Version numbers follow semantic versioning (semver) format.
- Recommended:
1.2.3,1.2.3-beta.1(without "v" prefix) - Accepted:
v1.2.3,v1.2.3-beta.1(with "v" prefix, for backward compatibility) - Incorrect:
1.2,1.2.3 beta,latest
Note: Version numbers with and without "v" prefix are functionally equivalent (e.g., 1.2.3 = v1.2.3). The system treats them as the same version for comparison and download purposes.
Version format is validated automatically in:
- Version Monitor (skips invalid versions with warning)
- Docker Build workflow (fails with error message)
| Target | Description | Dependencies |
|---|---|---|
Clean |
Clean output directories | - |
Restore |
Restore build dependencies | - |
Download |
Download packages from Azure Blob Storage | - |
VersionMonitor |
Monitor Azure Blob for new versions | - |
GitHubRelease |
Create GitHub release with packages | Download |
DockerBuild |
Build Docker images (local only) | Download |
DockerPush |
Push Docker images to configured registries | DockerBuild |
DockerRelease |
Build and push Docker images to configured registries | DockerPush |
./build.sh DockerBuild \
--ReleaseVersion "1.2.3" \
--DockerPlatform "linux-amd64"./build.sh DockerBuild \
--ReleaseVersion "1.2.3" \
--DockerPlatform "linux-arm64"./build.sh DockerRelease \
--ReleaseVersion "1.2.3" \
--DockerPlatform "all"hagicode/hagicode:1.2.3 - Application image with version tag
hagicode/hagicode:1.2 - Application image with minor version tag
hagicode/hagicode:1 - Application image with major version tag
hagicode/hagicode:latest - Application image with latest tag
Note: The Docker image uses a unified multi-stage build. Base tools (Node.js, .NET runtime, CLI tools) and application code are combined in a single image. No separate base image is pushed to registries.
# Login to Edge ACR
docker login hagicode.azurecr.io -u <username> -p <password>
# Pull image
docker pull hagicode.azurecr.io/hagicode:1.2.3
# Run container
docker run -d -p 5000:5000 hagicode.azurecr.io/hagicode:1.2.3docker run -d \
-p 5000:5000 \
-e ANTHROPIC_AUTH_TOKEN="sk-ant-..." \
-v ~/claude-config:/claude-mount \
hagicode.azurecr.io/hagicode:1.2.3# Login to DockerHub
docker login -u <username> -p <token>
# Pull image
docker pull newbe36524/hagicode:1.2.3
# Run container
docker run -d -p 5000:5000 newbe36524/hagicode:1.2.3# Login to Aliyun ACR
docker login registry.cn-hangzhou.aliyuncs.com -u <username> -p <password>
# Pull image
docker pull registry.cn-hangzhou.aliyuncs.com/hagicode/hagicode:1.2.3
# Run container
docker run -d -p 5000:5000 registry.cn-hangzhou.aliyuncs.com/hagicode/hagicode:1.2.3The repository includes GitHub Actions workflows that are triggered automatically:
| Workflow | Trigger | Description |
|---|---|---|
version-monitor.yml |
Push to main, Schedule (every 4 hours) | Monitors Azure Blob for new versions |
github-release-workflow.yml |
Repository dispatch (version-monitor-release) |
Creates GitHub releases |
docker-build.yml |
Tag push (v*..), Repository dispatch (version-monitor-docker) |
Builds and publishes Docker images to Azure ACR, Aliyun ACR, and DockerHub |
The docker-build.yml workflow automatically generates a publish result JSON file after successfully publishing images to both Azure ACR and Aliyun ACR. This file is uploaded to the GitHub Release and contains:
- Version: The semantic version of the release
- Published At: ISO 8601 timestamp of publish time
- Azure Registry: The Azure Container Registry URL
- Azure Images: Array of published image URLs (base, version, major/minor, major, latest tags)
- Aliyun Registry: The Aliyun Container Registry URL
- Aliyun Images: Array of published image URLs to Aliyun ACR
- GitHub Run Info: Workflow run ID and URL for traceability
The publish result file is named publish-results-{version}.json and can be found in the Release's download section.
The build system supports pushing images to multiple registries after successfully building and pushing to Azure ACR. The workflow automatically pushes to:
- Aliyun ACR: Pushes images from Azure ACR to Aliyun ACR using
docker buildx imagetools create - DockerHub: Pushes images from Azure ACR to DockerHub using username-based path format
- Logs in to Aliyun ACR using credentials from GitHub Secrets
- Retags and pushes images from Azure ACR to Aliyun ACR using
docker buildx imagetools create - Generates version tags (major.minor, major) for both registries
- Handles pre-release versions - skips
latesttag for pre-release versions (rc, beta, alpha, preview, dev)
- Logs in to DockerHub using credentials from GitHub Secrets
- Retags and pushes images from Azure ACR to DockerHub using
docker buildx imagetools create - Generates version tags (major.minor, major) for both registries
- Handles pre-release versions - skips
latesttag for pre-release versions
For stable releases (e.g., 1.2.3):
1.2.3- Full version1.2- Major.minor1- Majorlatest- Latest stable
For pre-release versions (e.g., 1.2.3-rc.1):
1.2.3-rc.1- Full version1.2- Major.minor1- Major- (no
latesttag)
For Aliyun ACR, configure the following GitHub Secrets:
ALIYUN_ACR_USERNAME- Aliyun ACR usernameALIYUN_ACR_PASSWORD- Aliyun ACR password
For DockerHub, configure the following GitHub Secrets:
DOCKERHUB_USERNAME- DockerHub usernameDOCKERHUB_TOKEN- DockerHub access token (created at https://hub.docker.com/settings/security)
{
"version": "1.2.3",
"publishedAt": "2024-01-01T00:00:00Z",
"github": {
"runId": "1234567890",
"runUrl": "https://github.com/.../actions/runs/...",
"repository": "owner/repo"
},
"azure": {
"registry": "hagicode.azurecr.io",
"images": [
{
"name": "hagicode",
"tag": "base",
"fullUrl": "hagicode.azurecr.io/hagicode:base"
},
{
"name": "hagicode",
"tag": "1.2.3",
"fullUrl": "hagicode.azurecr.io/hagicode:1.2.3"
},
{
"name": "hagicode",
"tag": "1.2",
"fullUrl": "hagicode.azurecr.io/hagicode:1.2"
},
{
"name": "hagicode",
"tag": "1",
"fullUrl": "hagicode.azurecr.io/hagicode:1"
},
{
"name": "hagicode",
"tag": "latest",
"fullUrl": "hagicode.azurecr.io/hagicode:latest"
}
]
},
"aliyun": {
"registry": "registry.cn-hangzhou.aliyuncs.com",
"images": [
{
"name": "hagicode",
"tag": "base",
"fullUrl": "registry.cn-hangzhou.aliyuncs.com/hagicode:base"
},
{
"name": "hagicode",
"tag": "1.2.3",
"fullUrl": "registry.cn-hangzhou.aliyuncs.com/hagicode:1.2.3"
},
{
"name": "hagicode",
"tag": "1.2",
"fullUrl": "registry.cn-hangzhou.aliyuncs.com/hagicode:1.2"
},
{
"name": "hagicode",
"tag": "1",
"fullUrl": "registry.cn-hangzhou.aliyuncs.com/hagicode:1"
},
{
"name": "hagicode",
"tag": "latest",
"fullUrl": "registry.cn-hangzhou.aliyuncs.com/hagicode:latest"
}
]
},
"dockerhub": {
"registry": "docker.io",
"images": [
{
"name": "hagicode",
"tag": "base",
"fullUrl": "newbe36524/hagicode:base"
},
{
"name": "hagicode",
"tag": "1.2.3",
"fullUrl": "newbe36524/hagicode:1.2.3"
},
{
"name": "hagicode",
"tag": "1.2",
"fullUrl": "newbe36524/hagicode:1.2"
},
{
"name": "hagicode",
"tag": "1",
"fullUrl": "newbe36524/hagicode:1"
},
{
"name": "hagicode",
"tag": "latest",
"fullUrl": "newbe36524/hagicode:latest"
}
]
}
}The workflows can be triggered programmatically via repository_dispatch events:
| Event Type | Triggered By | Payload Required |
|---|---|---|
version-monitor-release |
Version Monitor | {"version": "1.2.3"} |
version-monitor-docker |
Version Monitor | {"version": "1.2.3"} |
Example trigger via GitHub CLI:
# Trigger GitHub Release
gh api --method POST repos/{owner}/{repo}/dispatches \
-F event_type='version-monitor-release' \
-F client_payload='{"version": "1.2.3"}'
# Trigger Docker Build
gh api --method POST repos/{owner}/{repo}/dispatches \
-F event_type='version-monitor-docker' \
-F client_payload='{"version": "1.2.3"}'You can trigger workflows manually from the GitHub Actions UI:
- Go to Actions tab
- Select Docker Multi-Arch Build and Push to Edge ACR
- Click Run workflow
- Configure:
- Version:
1.2.3 - Platform:
all,linux-amd64, orlinux-arm64 - Dry Run: Enable to test without publishing
- Version:
- Go to Actions tab
- Select Azure to Aliyun Image Sync
- Click Run workflow
- Configure:
- VERSION: Optional version to sync (e.g.,
v1.2.3or1.2.3) - Leave empty to sync the latest release automatically
- VERSION: Optional version to sync (e.g.,
See ENVIRONMENT_VARIABLES.md for detailed configuration.
export AZURE_BLOB_SAS_URL="https://hagicode.blob.core.windows.net/packages?sp=..."
export GITHUB_TOKEN="ghp_xxxxxxxxxxxxxxxxxxxx"
export AZURE_ACR_USERNAME="hagicode"
export AZURE_ACR_PASSWORD="password"
export AZURE_ACR_REGISTRY="hagicode.azurecr.io"To push images to DockerHub, configure the following:
export DOCKERHUB_USERNAME="your-dockerhub-username"
export DOCKERHUB_TOKEN="your-dockerhub-access-token"Note: DockerHub access tokens can be created at https://hub.docker.com/settings/security
To push images to Aliyun ACR, configure the following:
export ALIYUN_ACR_USERNAME="your-aliyun-username"
export ALIYUN_ACR_PASSWORD="your-aliyun-password"
export ALIYUN_ACR_REGISTRY="registry.cn-hangzhou.aliyuncs.com"
export ALIYUN_ACR_NAMESPACE="hagicode"Pass parameters directly to Nuke:
./build.sh DockerRelease \
--ReleaseVersion "1.2.3" \
--DockerPlatform "all" \
--DockerImageName "hagicode/hagicode"The Docker images include pre-installed AI agents:
- Claude Code CLI: Version 2.1.34
- OpenSpec CLI: Version >=1.0.0 <2.0.0
- UIPro CLI: Version 2.1.3
- Codex CLI: Latest major stream via
@openai/codex
See AGENTS.md for detailed documentation.
Claude Code can be configured using environment variables:
docker run -e ANTHROPIC_AUTH_TOKEN="sk-ant-..." hagicode.azurecr.io/hagicode:1.2.3Alternatively, mount host configuration:
docker run -v ~/claude-config:/claude-mount hagicode.azurecr.io/hagicode:1.2.3Codex connectivity is configured through container environment variables. This change does not require additional app-side API key or UI configuration.
docker run -d \
-p 5000:5000 \
-e CODEX_BASE_URL="https://api.openai.com/v1" \
-e CODEX_API_KEY="sk-..." \
hagicode.azurecr.io/hagicode:1.2.3Compatibility aliases are also supported:
OPENAI_BASE_URL(fallback alias for base URL)OPENAI_API_KEY(fallback alias for API key)
Precedence:
- Base URL:
CODEX_BASE_URL>OPENAI_BASE_URL - API key:
CODEX_API_KEY>OPENAI_API_KEY
| File | Purpose | Platform |
|---|---|---|
docker_deployment/Dockerfile.template |
Unified multi-stage build template | multi-arch |
docker_deployment/docker-entrypoint.sh |
Container entrypoint | all |
docker_deployment/.dockerignore |
Build exclusions | all |
- QEMU Setup: Install binfmt for cross-architecture builds
- Buildx Builder: Create Docker buildx builder for multi-arch
- Unified Image Build: Build unified Docker image using multi-stage build (base stage + final stage in single Dockerfile)
- Dockerfile Generation: Generate Dockerfile from template with version injection
- Azure ACR Push: Push unified images to Azure ACR with version tags
- Multi-Architecture Verification: Verify images contain both amd64 and arm64 architectures
- Additional Registry Pushes: Replicate images to Aliyun ACR and DockerHub with verification
The build system uses an adapter pattern to support pushing images to multiple container registries:
| Registry | Path Format | Example |
|---|---|---|
| Azure ACR | {registry}/{image} |
hagicode.azurecr.io/hagicode |
| Aliyun ACR | {registry}/{namespace}/{image} |
registry.cn-hangzhou.aliyuncs.com/hagicode/hagicode |
| DockerHub | {username}/{image} |
newbe36524/hagicode |
Registry pushes are configured independently - only configured registries will be used.
All published Docker images are verified to contain both linux/amd64 and linux/arm64 architectures:
- Azure ACR: After push,
Verify Images in Registrystep checks manifest for both architectures - Aliyun ACR: After sync,
Verify Images in Aliyun ACRstep verifies all pushed tags
If either architecture is missing, the workflow fails with a clear error message:
Error: Tag 1.2.3 does not contain amd64 architecture
This ensures users on both AMD64 and ARM64 platforms can pull compatible images.
Images are tagged with multiple versions:
- Full Version:
1.2.3(exact version) - Minor Version:
1.2(major.minor) - Major Version:
1(major) - Latest:
latest(always points to newest)
Example tags for version 1.2.3:
hagicode.azurecr.io/hagicode:1.2.3
hagicode.azurecr.io/hagicode:1.2
hagicode.azurecr.io/hagicode:1
hagicode.azurecr.io/hagicode:latest
Issue: docker: Error response from daemon: unknown
Solution:
- Verify Docker is running:
docker ps - Check Docker version:
docker --version(requires >= 20.10) - Enable buildx:
docker buildx version
Issue: Failed to setup QEMU for cross-architecture builds
Solution:
# Manually install binfmt
docker run --privileged --rm tonistiigi/binfmt --install allIssue: unauthorized: authentication required
Solution:
- Verify credentials are correct
- Login manually:
docker login hagicode.azurecr.io - Check token has not expired
Issue: Registry verification fails after push
Solution:
- Wait for registry propagation (may take 1-2 minutes)
- Check image exists:
docker manifest inspect hagicode.azurecr.io/hagicode:1.2.3 - Verify image digest matches push output
This repository uses Nuke for build automation.
- Definition:
nukeBuild/Build.cs - Targets: Split across multiple files (Targets.*.cs)
- Partial Classes: State and helpers in
Build.Partial.cs
To add a new build target:
- Create
nukeBuild/Build.Targets.YourTarget.cs - Define target:
Target YourTarget => _ => _
.DependsOn(Download)
.Executes(() => {
// Your implementation
});- Run with:
./build.sh YourTarget
When contributing to this repository:
- Follow existing code style and patterns
- Update documentation for new features
- Test with both AMD64 and ARM64 platforms
- Ensure environment variables are documented
- Update AGENTS.md when changing AI agent versions
- MIGRATION.md - Release process migration guide
- AGENTS.md - AI agents and integration
- ENVIRONMENT_VARIABLES.md - Complete environment variable reference
See LICENSE file for details.
For issues or questions:
- Check GitHub Issues
- Review AGENTS.md for AI agent issues
- Consult ENVIRONMENT_VARIABLES.md for configuration help