Skip to content

v1 build · hygon-dtk26.04 · push #107

v1 build · hygon-dtk26.04 · push

v1 build · hygon-dtk26.04 · push #107

# Copyright 2026 FlagOS Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Builid Runtime Image (manual)
# The run title self-labels each dispatch so v1 (build, no flag_gems) and v2
# (full, with flag_gems) are told apart at a glance in the Actions run list —
# the two produce identical job names, so without this they are indistinguishable.
# Shows: layer (v1/v2) · backend · push/no-push · no-cache · pinned flaggems ver.
run-name: >-
${{ inputs.no_flaggems && 'v1 build' || 'v2 flag_gems' }}
· ${{ inputs.backend }}
· ${{ inputs.push && 'push' || 'no-push' }}${{ inputs.no_cache && ' · no-cache' || '' }}${{ inputs.flaggems != '' && format(' · fg={0}', inputs.flaggems) || '' }}
# Runtime images are built on demand, not on every push/PR. They layer
# FlagGems (pure Python + optional C++ extension) on top of a base image
# via wheel install. Trigger this manually to build a backend (or all).
on:
workflow_dispatch:
inputs:
backend:
description: 'Backend to build (e.g. nvidia-cuda12.8), or "all"'
type: string
default: all
push:
description: 'Push image(s) to the registry'
type: boolean
default: false
flaggems:
description: 'FlagGems wheel version to install (e.g. 5.3.2)'
type: string
default: ''
no_flaggems:
description: 'Skip flag_gems install — produce -build image'
type: boolean
default: false
skip_cpp:
description: 'Skip flag_gems C++ extension install (Python wheel only)'
type: boolean
default: false
no_cache:
description: 'Disable Docker build cache (use for rebuild wheels with same version)'
type: boolean
default: false
jobs:
authorize:
# Only accounts listed in .github/builders.txt may trigger this workflow
# manually; see .github/actions/check-trigger-author for the check.
# actions/checkout is required: local composite actions are resolved from
# the workspace, so the repo must exist before the action step runs.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: ./.github/actions/check-trigger-author
set-matrix:
needs: authorize
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
harbor_host: ${{ steps.harbor-host.outputs.host }}
runtime_prereqs: ${{ steps.runtime-prereqs.outputs.prereqs }}
steps:
- name: Checkout Code
uses: actions/checkout@v7
- name: Install PyYAML
run: python3 -m pip install --user pyyaml
- id: set-matrix
shell: bash
run: |
if [[ "${{ inputs.backend }}" == "all" ]]; then
python3 scripts/generate_matrix.py --runtime > matrix.json
else
python3 scripts/generate_matrix.py --runtime ${{ inputs.backend }} > matrix.json
fi
cat matrix.json
echo "matrix=$(jq -c . matrix.json)" >> "$GITHUB_OUTPUT"
- id: runtime-prereqs
shell: bash
run: |
prereqs=$(python3 -c "import yaml; print(' '.join(yaml.safe_load(open('configs.yaml'))['runtime_prereqs']))")
echo "prereqs=$prereqs" >> "$GITHUB_OUTPUT"
- id: harbor-host
shell: bash
run: |
host=$(python3 -c "import yaml;print(yaml.safe_load(open('.github/build-config.yml'))['registry']['host'])")
echo "host=$host" >> "$GITHUB_OUTPUT"
build-matrix:
needs: set-matrix
if: ${{ fromJSON(needs.set-matrix.outputs.matrix).include[0] != null }}
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.set-matrix.outputs.matrix) }}
name: runtime-${{ matrix.name }}
runs-on: ${{ fromJSON(matrix.runson) }}
steps:
- name: Checkout build-infra
uses: actions/checkout@v7
- name: Harbor login (push only)
if: ${{ inputs.push }}
env:
HARBOR_USER: ${{ secrets.HARBOR_USER }}
HARBOR_PW: ${{ secrets.HARBOR_PASSWORD }}
run: |
host="${{ needs.set-matrix.outputs.harbor_host }}"
for i in 1 2 3; do
if printf '%s' "$HARBOR_PW" | docker login "$host" -u "$HARBOR_USER" --password-stdin; then
exit 0
fi
echo "Harbor login attempt $i failed, retrying..."
sleep 30
done
echo "::error::Harbor login failed after 3 attempts"
exit 1
- name: Env + parameters
run: |
flaggems_ver="${{ inputs.flaggems }}"
[[ -z "$flaggems_ver" ]] && flaggems_ver="${{ matrix.flaggems_version }}"
echo "hostname: $(hostname)"
echo "arch: $(uname -m)"
docker version --format 'docker: {{.Server.Version}}' 2>/dev/null || echo "docker: unavailable"
echo "base_image: ${{ matrix.base_image }}"
echo "image_tag: ${{ matrix.image_tag }}"
echo "flaggems_version: ${flaggems_ver}"
echo "no_flaggems: ${{ inputs.no_flaggems }}"
echo "python_version: ${{ matrix.python_version }}"
echo "deps: ${{ matrix.deps }}"
echo "cpp_extra: ${{ matrix.cpp_extra }}"
echo "flagtree_pkg: ${{ matrix.flagtree_pkg }}"
echo "triton_pkg: ${{ matrix.triton_pkg }}"
- name: Pull base image
run: |
docker pull "${{ matrix.base_image }}" || {
echo "::error::Failed to pull base image ${{ matrix.base_image }}"
exit 1
}
- name: Build runtime image
run: |
flaggems_ver="${{ inputs.flaggems }}"
[[ -z "$flaggems_ver" ]] && flaggems_ver="${{ matrix.flaggems_version }}"
no_flaggems_arg=""
image_tag="${{ matrix.image_tag }}"
[[ "${{ inputs.no_flaggems }}" == "true" ]] && no_flaggems_arg='--build-arg NO_FLAGGEMS=1' && image_tag="${image_tag}-build"
cpp_extra="${{ matrix.cpp_extra }}"
[[ "${{ inputs.skip_cpp }}" == "true" ]] && cpp_extra=""
no_cache_arg=""
[[ "${{ inputs.no_cache }}" == "true" ]] && no_cache_arg="--no-cache"
# OCI provenance labels (mirrors scripts/build_base.py). revision is
# the runtime build commit — stamped via CLI --label because the
# multi-stage runtime/Containerfile inherits the base image's labels.
git_revision="${{ github.sha }}"
git_created="$(git show -s --format=%cI HEAD)"
label_args="--label org.opencontainers.image.version=${{ matrix.version }} \
--label org.opencontainers.image.revision=${git_revision} \
--label org.opencontainers.image.created=${git_created} \
--label last-updated=${git_created} \
--label org.opencontainers.image.source=https://github.com/flagos-ai/build-infra \
--label flagos.base=${{ matrix.base_image }}"
[[ "${{ inputs.no_flaggems }}" != "true" ]] && label_args="${label_args} --label flagos.flaggems=${flaggems_ver}"
docker build \
${no_cache_arg} \
${label_args} \
--build-arg "BASE_IMAGE=${{ matrix.base_image }}" \
--build-arg "PYTHON_VERSION=${{ matrix.python_version }}" \
--build-arg "FLAGOS_PYPI=${{ matrix.flagos_pypi }}" \
--build-arg "DAILY_PYPI=${{ matrix.daily_pypi }}" \
--build-arg "EXTRA_PYPI=${{ matrix.extra_pypi }}" \
--build-arg "DEPS=${{ matrix.deps }}" \
--build-arg "RUNTIME_PREREQS=${{ needs.set-matrix.outputs.runtime_prereqs }}" \
--build-arg "CPP_EXTRA=${cpp_extra}" \
--build-arg "FLAGTREE_PKG=${{ matrix.flagtree_pkg }}" \
--build-arg "TRITON_PKG=${{ matrix.triton_pkg }}" \
--build-arg "TRITON_EXTRA_PKGS=${{ matrix.triton_extra_pkgs }}" \
--build-arg "INCLUDE_TESTS=false" \
--build-arg "FLAGGEMS_VERSION=${flaggems_ver}" \
--build-arg "RUNTIME_ENV=${{ matrix.runtime_env }}" \
${no_flaggems_arg} \
-t "${image_tag}" \
-f runtime/Containerfile runtime/
- name: Push runtime image
if: ${{ inputs.push }}
run: |
image_tag="${{ matrix.image_tag }}"
[[ "${{ inputs.no_flaggems }}" == "true" ]] && image_tag="${image_tag}-build"
docker push "${image_tag}"