Skip to content

v1.0.0

v1.0.0 #10

name: Build Release Docker Image
on:
release:
types: [created]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to build (e.g., v1.0.0)'
required: true
type: string
concurrency:
group: tag-release-image-${{ github.event.release.tag_name || github.event.inputs.tag }}
cancel-in-progress: true
permissions:
contents: read
packages: write
env:
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
IMAGE_NAME: ghcr.io/inclusionai/areal-runtime
jobs:
start-builder:
name: Start areal-docker-builder instance
runs-on: ubuntu-latest
env:
INSTANCE_NAME: areal-docker-builder
INSTANCE_ZONE: us-central1-f
steps:
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: Start builder instance if stopped
run: |
set -euo pipefail
# Check instance status
status=$(gcloud compute instances describe "$INSTANCE_NAME" \
--project "$GCP_PROJECT_ID" \
--zone "$INSTANCE_ZONE" \
--format="get(status)" || echo "NOT_FOUND")
if [ "$status" = "NOT_FOUND" ]; then
echo "Error: Instance $INSTANCE_NAME not found in zone $INSTANCE_ZONE" >&2
exit 1
fi
if [ "$status" = "RUNNING" ]; then
echo "Instance $INSTANCE_NAME is already running."
elif [ "$status" = "TERMINATED" ] || [ "$status" = "SUSPENDED" ]; then
echo "Instance $INSTANCE_NAME is $status. Starting it..."
gcloud compute instances start "$INSTANCE_NAME" \
--project "$GCP_PROJECT_ID" \
--zone "$INSTANCE_ZONE"
echo "Instance started successfully."
else
echo "Instance $INSTANCE_NAME has unexpected status: $status" >&2
exit 1
fi
- name: Wait for builder runner to be online
uses: actions/github-script@v7
env:
INSTANCE_NAME: areal-docker-builder
GH_PAT: ${{ secrets.GH_PAT }}
with:
github-token: ${{ secrets.GH_PAT }}
script: |
const instanceName = process.env.INSTANCE_NAME;
const maxAttempts = 120;
const delayMs = 10000;
const pat = process.env.GH_PAT;
if (!pat) {
core.setFailed('GH_PAT secret is not configured.');
return;
}
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
const response = await github.rest.actions.listSelfHostedRunnersForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
request: {
headers: {
authorization: `token ${pat}`,
},
},
});
const found = response.data.runners.find((runner) => runner.name === instanceName);
if (found && found.status === 'online') {
core.info(`Builder runner ${instanceName} is online.`);
return;
}
core.info(`Builder runner ${instanceName} not ready yet (attempt ${attempt}/${maxAttempts}).`);
await wait(delayMs);
}
throw new Error(`Timed out waiting for builder runner ${instanceName} to come online.`);
build-and-push-release:
needs:
- start-builder
name: Build and push release Docker image
runs-on: [self-hosted, areal-docker-builder]
timeout-minutes: 180
outputs:
package_version: ${{ steps.get-version.outputs.version }}
release_tag: ${{ steps.get-version.outputs.release_tag }}
steps:
- name: Checkout code at release tag
uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name || github.event.inputs.tag }}
- name: Get package version
id: get-version
run: |
# Extract version from pyproject.toml (single source of truth)
VERSION=$(sed -n 's/^version *= *"\([^"]*\)"/\1/p' pyproject.toml)
RELEASE_TAG="${{ github.event.release.tag_name || github.event.inputs.tag }}"
echo "Package version: $VERSION"
echo "Release tag: $RELEASE_TAG"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: inclusionai
password: ${{ secrets.GHCR_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
tags: |
${{ env.IMAGE_NAME }}:${{ steps.get-version.outputs.release_tag }}
${{ env.IMAGE_NAME }}:latest
${{ env.IMAGE_NAME }}:dev
- name: Image details
run: |
echo "Docker image built and pushed successfully!"
echo "Image: ${{ env.IMAGE_NAME }}"
echo "Tags:"
echo " - ${{ steps.get-version.outputs.release_tag }}"
echo " - latest"
echo " - dev"
echo "Release: ${{ github.event.release.name || github.event.inputs.tag }}"
echo "Commit: ${{ github.sha }}"
stop-builder:
name: Stop areal-docker-builder instance
needs:
- build-and-push-release
- start-builder
if: always()
runs-on: ubuntu-latest
env:
INSTANCE_NAME: areal-docker-builder
INSTANCE_ZONE: us-central1-f
steps:
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT_KEY }}
- name: Set up Google Cloud SDK
uses: google-github-actions/setup-gcloud@v2
- name: Stop builder instance
run: |
# Check if instance is running
status=$(gcloud compute instances describe "$INSTANCE_NAME" \
--project "$GCP_PROJECT_ID" \
--zone "$INSTANCE_ZONE" \
--format="get(status)" 2>/dev/null || echo "NOT_FOUND")
if [ "$status" = "NOT_FOUND" ]; then
echo "Warning: Instance $INSTANCE_NAME not found in zone $INSTANCE_ZONE"
exit 0
fi
if [ "$status" = "RUNNING" ]; then
echo "Stopping instance $INSTANCE_NAME..."
gcloud compute instances stop "$INSTANCE_NAME" \
--project "$GCP_PROJECT_ID" \
--zone "$INSTANCE_ZONE"
echo "Instance stopped successfully."
else
echo "Instance $INSTANCE_NAME is already in status: $status"
fi