Skip to content

Build Expt Images Or Runtimes #28

Build Expt Images Or Runtimes

Build Expt Images Or Runtimes #28

name: Build Expt Images Or Runtimes
on:
workflow_dispatch:
inputs:
tag:
description: 'Tag for the Docker image'
required: true
default: 'latest'
kind:
description: 'Type of packages to build'
required: false
type: choice
options:
- operating-systems
- languages
- frameworks
default: 'operating-systems'
name:
required: false
description: 'Specific package folder; leave empty to build all packages of the selected kind'
type: string
default: ''
build_type:
description: 'Type of build to perform'
required: false
type: choice
options:
- images
- runtimes
default: 'images'
tools_version:
description: 'Base tools version (optional, defaults to tag if not specified)'
required: false
type: string
default: ''
os_version:
description: 'OS image version (optional, defaults to tag if not specified)'
required: false
type: string
default: ''
framework_image_version:
description: 'Framework image version (optional, defaults to tag if not specified)'
required: false
type: string
default: ''
l10n:
description: 'Localization setting (choose one or both)'
required: false
type: choice
options:
- en_US
- zh_CN
- both
default: 'en_US'
arch:
description: 'System architecture (choose one or both)'
required: false
type: choice
options:
- amd64
- arm64
- both
default: 'amd64'
aliyun_enabled:
description: 'Enable Aliyun ACR builds'
required: false
type: boolean
default: false
jobs:
# Define expt image matrix
define-matrix:
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.set_tag.outputs.tag }}
framework_image_version: ${{ steps.set_tag.outputs.framework_image_version }}
tools_version: ${{ steps.set_tag.outputs.tools_version }}
os_version: ${{ steps.set_tag.outputs.os_version }}
l10n_matrix: ${{ steps.set_matrix.outputs.l10n_matrix }}
arch_matrix: ${{ steps.set_matrix.outputs.arch_matrix }}
packages: ${{ steps.get_packages.outputs.packages }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up tag
id: set_tag
run: |
if [ -n "${{ inputs.tag }}" ]; then
tag=${{ inputs.tag }}
else
tag=$(echo "${{ github.sha }}" | cut -c1-7)
fi
# Set tools_version: use inputs.tools_version if provided, otherwise use tag
if [ -n "${{ inputs.tools_version }}" ]; then
tools_version=${{ inputs.tools_version }}
else
tools_version=$tag
fi
# Set os_version: use inputs.os_version if provided, otherwise use tag
if [ -n "${{ inputs.os_version }}" ]; then
os_version=${{ inputs.os_version }}
else
os_version=$tag
fi
# Set framework_image_version: use inputs.framework_image_version if provided, otherwise use tag
if [ -n "${{ inputs.framework_image_version }}" ]; then
framework_image_version=${{ inputs.framework_image_version }}
else
framework_image_version=$tag
fi
echo "tag=$tag" >> $GITHUB_OUTPUT
echo "framework_image_version=$framework_image_version" >> $GITHUB_OUTPUT
echo "tools_version=$tools_version" >> $GITHUB_OUTPUT
echo "os_version=$os_version" >> $GITHUB_OUTPUT
- name: Build localization and architecture matrix
id: set_matrix
run: |
l10n_values=()
case "${{ inputs.l10n }}" in
en_US)
l10n_values+=('{"display":"en_US","normalized":"en-us"}')
;;
zh_CN)
l10n_values+=('{"display":"zh_CN","normalized":"zh-cn"}')
;;
both)
l10n_values+=('{"display":"en_US","normalized":"en-us"}')
l10n_values+=('{"display":"zh_CN","normalized":"zh-cn"}')
;;
*)
echo "Error: Unknown l10n option '${{ inputs.l10n }}'." >&2
exit 1
;;
esac
l10n_matrix=$(printf '%s\n' "${l10n_values[@]}" | jq -s -c '.')
arch_values=()
case "${{ inputs.arch }}" in
amd64)
arch_values+=("amd64")
;;
arm64)
arch_values+=("arm64")
;;
both)
arch_values+=("amd64")
arch_values+=("arm64")
;;
*)
echo "Error: Unknown arch option '${{ inputs.arch }}'." >&2
exit 1
;;
esac
arch_matrix=$(printf '%s\n' "${arch_values[@]}" | jq -R -s -c 'split("\n")[:-1]')
echo "l10n_matrix=$l10n_matrix" >> $GITHUB_OUTPUT
echo "arch_matrix=$arch_matrix" >> $GITHUB_OUTPUT
- name: Get packages
id: get_packages
run: |
# Get all packages
kind=${{ inputs.kind }}
name=${{ inputs.name }}
build_type=${{ inputs.build_type }}
if [ -n "$name" ]; then
echo "Looking for specific package: $name"
target_dockerfiles=$(find experimental/$build_type/$kind/$name -name "Dockerfile")
if [ -z "$target_dockerfiles" ]; then
echo "Error: No Dockerfile found for package '$name' in kind '$kind'" >&2
exit 1
fi
else
echo "No specific package provided, gathering all packages of kind: $kind"
target_dockerfiles=$(find experimental/$build_type/$kind -name "Dockerfile")
fi
# Convert to JSON array
packages=$(echo "$target_dockerfiles" | jq -R -s 'split("\n")[:-1]')
echo "packages<<EOF" >> $GITHUB_OUTPUT
echo "$packages" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
package_count=$(echo "$packages" | jq 'length // 0')
echo "Found $package_count packages to build"
# Build expt images
build-expt-images:
runs-on: ubuntu-latest
needs: define-matrix
strategy:
fail-fast: false
matrix:
packages: ${{ fromJson(needs.define-matrix.outputs.packages) }}
l10n: ${{ fromJson(needs.define-matrix.outputs.l10n_matrix) }}
arch: ${{ fromJson(needs.define-matrix.outputs.arch_matrix) }}
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate image names (standard)
id: generate-standard
uses: ./.github/actions/generate-image-names
with:
dockerfile: ${{ matrix.packages }}
tag: ${{ format('{0}-{1}', needs.define-matrix.outputs.tag, matrix.l10n.normalized) }}
ghcr_credentials: ${{ format('{{"registry":"{0}","username":"{1}","password":"{2}"}}', 'ghcr.io', github.repository_owner, secrets.GITHUB_TOKEN) || '{}' }}
aliyun_credentials: ${{ inputs.aliyun_enabled == 'true' && format('{{"registry":"{0}","username":"{1}","password":"{2}", "namespace":"{3}"}}', secrets.ALIYUN_REGISTRY, secrets.ALIYUN_USERNAME, secrets.ALIYUN_PASSWORD, secrets.ALIYUN_NAMESPACE) || '{}' }}
expt_image_naming: ${{ inputs.build_type }}
- name: Build and push standard images
uses: ./.github/actions/build-and-push
with:
build_args: |
REPO=${{ github.repository_owner }}/devbox-base-expt
L10N=${{ matrix.l10n.display }}
L10N_NORMALIZED=${{ matrix.l10n.normalized }}
ARCH=${{ matrix.arch }}
BASE_TOOLS_VERSION=${{ needs.define-matrix.outputs.tools_version }}
OS_IMAGE_VERSION=${{ needs.define-matrix.outputs.os_version }}-${{ matrix.l10n.normalized }}
FRAMEWORK_IMAGE_VERSION=${{ needs.define-matrix.outputs.framework_image_version }}-${{ matrix.l10n.normalized }}
RUNTIME_IMAGE_VERSION=${{ format('{0}-{1}', needs.define-matrix.outputs.tag, matrix.l10n.normalized) }}
dockerfile: ${{ matrix.packages }}
ghcr_credentials: ${{ format('{{"registry":"{0}","username":"{1}","password":"{2}"}}', 'ghcr.io', github.repository_owner, secrets.GITHUB_TOKEN) || '{}' }}
ghcr_image_name: ${{ steps.generate-standard.outputs.ghcr_image_name }}
aliyun_credentials: ${{ inputs.aliyun_enabled == 'true' && format('{{"registry":"{0}","username":"{1}","password":"{2}", "namespace":"{3}"}}', secrets.ALIYUN_REGISTRY, secrets.ALIYUN_USERNAME, secrets.ALIYUN_PASSWORD, secrets.ALIYUN_NAMESPACE) || '{}' }}
acr_image_name: ${{ steps.generate-standard.outputs.acr_image_name }}
- name: Clean up images (standard)
if: always()
run: |
set -eux
# Remove GHCR image by tag if present
if [ -n "${{ steps.generate-standard.outputs.ghcr_image_name }}" ]; then
echo "Removing local image: ${{ steps.generate-standard.outputs.ghcr_image_name }} (if exists)"
docker image rm -f "${{ steps.generate-standard.outputs.ghcr_image_name }}" || true
fi
# Remove Aliyun/ACR image by tag if present
if [ -n "${{ steps.generate-standard.outputs.acr_image_name }}" ]; then
echo "Removing local image: ${{ steps.generate-standard.outputs.acr_image_name }} (if exists)"
docker image rm -f "${{ steps.generate-standard.outputs.acr_image_name }}" || true
fi
# Remove dangling images and builder cache to free space
docker image prune -af || true
# If docker buildx was used, prune builder cache as well
docker builder prune -af || true
- name: Output built image names (standard)
run: |
echo "## 🐳 Built OS Base Images (Standard)" >> $GITHUB_STEP_SUMMARY
echo "Localization: ${{ matrix.l10n.display }} (normalized: ${{ matrix.l10n.normalized }}), Arch: ${{ matrix.arch }}" >> $GITHUB_STEP_SUMMARY
echo "| Image Name | Registry |" >> $GITHUB_STEP_SUMMARY
echo "|------------|----------|" >> $GITHUB_STEP_SUMMARY
echo "| ${{ steps.generate-standard.outputs.ghcr_image_name }} | GHCR |" >> $GITHUB_STEP_SUMMARY
if [ "${{ steps.generate-standard.outputs.acr_image_name }}" != "" ]; then
echo "| ${{ steps.generate-standard.outputs.acr_image_name }} | Aliyun ACR |" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🚀 Pull Command" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull ${{ steps.generate-standard.outputs.ghcr_image_name }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY