276 lines
9.8 KiB
YAML
276 lines
9.8 KiB
YAML
name: deploy-runner-images
|
|
|
|
on:
|
|
push:
|
|
tags: [boot-v*]
|
|
workflow_dispatch:
|
|
inputs:
|
|
release_tag:
|
|
description: "Release tag override (manual runs only)"
|
|
required: false
|
|
default: ""
|
|
publish_release:
|
|
description: "Publish artifacts to Forgejo release (true/false)"
|
|
required: false
|
|
default: "true"
|
|
build_x86_64_netboot:
|
|
description: "Build x86_64 netboot tarball (true/false)"
|
|
required: false
|
|
default: "true"
|
|
build_x86_64_iso:
|
|
description: "Build x86_64 installer ISO (true/false)"
|
|
required: false
|
|
default: "true"
|
|
|
|
concurrency:
|
|
group: runner-image-deploy-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build-and-release:
|
|
if: ${{ github.server_url != 'https://codeberg.org' }}
|
|
runs-on: codeberg-medium-lazy
|
|
steps:
|
|
- name: Fetch source (no git required)
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
|
|
echo "error: missing github.token"
|
|
exit 2
|
|
fi
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
echo "error: curl is required"
|
|
exit 2
|
|
fi
|
|
if ! command -v tar >/dev/null 2>&1; then
|
|
echo "error: tar is required"
|
|
exit 2
|
|
fi
|
|
if [[ -z "${GITHUB_SHA:-}" ]]; then
|
|
echo "error: missing GITHUB_SHA"
|
|
exit 2
|
|
fi
|
|
if [[ -z "${GITHUB_SERVER_URL:-}" ]]; then
|
|
echo "error: missing GITHUB_SERVER_URL"
|
|
exit 2
|
|
fi
|
|
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
|
echo "error: missing GITHUB_REPOSITORY"
|
|
exit 2
|
|
fi
|
|
|
|
rm -rf .repo
|
|
mkdir -p .repo
|
|
curl -fsSL -H "Authorization: token ${GITHUB_TOKEN}" \
|
|
"${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}/archive/${GITHUB_SHA}.tar.gz?rev=${GITHUB_SHA}" \
|
|
-o .repo/src.tgz
|
|
tar -xzf .repo/src.tgz -C .repo --strip-components=1
|
|
rm -f .repo/src.tgz
|
|
|
|
- name: Bootstrap Nix
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
if ! command -v nix >/dev/null 2>&1; then
|
|
curl -fsSL https://nixos.org/nix/install -o /tmp/install-nix.sh
|
|
sh /tmp/install-nix.sh --no-daemon --yes
|
|
fi
|
|
|
|
if [[ -f "$HOME/.nix-profile/etc/profile.d/nix.sh" ]]; then
|
|
# shellcheck disable=SC1091
|
|
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
|
|
fi
|
|
if [[ -d "$HOME/.nix-profile/bin" ]]; then
|
|
echo "PATH=$HOME/.nix-profile/bin:$PATH" >> "$GITHUB_ENV"
|
|
export PATH="$HOME/.nix-profile/bin:$PATH"
|
|
fi
|
|
nix --version
|
|
|
|
- name: Resolve build plan
|
|
id: plan
|
|
env:
|
|
INPUT_RELEASE_TAG: ${{ github.event.inputs.release_tag }}
|
|
INPUT_PUBLISH_RELEASE: ${{ github.event.inputs.publish_release }}
|
|
INPUT_BUILD_X86_64_NETBOOT: ${{ github.event.inputs.build_x86_64_netboot }}
|
|
INPUT_BUILD_X86_64_ISO: ${{ github.event.inputs.build_x86_64_iso }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
bool_norm() {
|
|
local raw
|
|
raw="$(printf '%s' "${1:-}" | tr '[:upper:]' '[:lower:]')"
|
|
case "${raw}" in
|
|
''|true|1|yes|y|on) echo "true" ;;
|
|
false|0|no|n|off) echo "false" ;;
|
|
*)
|
|
echo "error: invalid boolean value '${1}'" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
}
|
|
|
|
short_sha="${GITHUB_SHA:0:12}"
|
|
if [[ "${GITHUB_REF:-}" == refs/tags/* ]]; then
|
|
release_tag="${GITHUB_REF#refs/tags/}"
|
|
else
|
|
release_tag="${INPUT_RELEASE_TAG:-}"
|
|
if [[ -z "${release_tag}" ]]; then
|
|
release_tag="boot-${short_sha}"
|
|
fi
|
|
fi
|
|
|
|
if [[ ! "${release_tag}" =~ ^[A-Za-z0-9._-]+$ ]]; then
|
|
echo "error: release tag contains unsupported characters: ${release_tag}" >&2
|
|
exit 2
|
|
fi
|
|
|
|
publish_release="$(bool_norm "${INPUT_PUBLISH_RELEASE:-true}")"
|
|
build_x86_64_netboot="$(bool_norm "${INPUT_BUILD_X86_64_NETBOOT:-true}")"
|
|
build_x86_64_iso="$(bool_norm "${INPUT_BUILD_X86_64_ISO:-true}")"
|
|
|
|
if [[ "${build_x86_64_netboot}" != "true" && "${build_x86_64_iso}" != "true" ]]; then
|
|
echo "error: at least one image build must be enabled" >&2
|
|
exit 2
|
|
fi
|
|
|
|
artifact_suffix="${short_sha}-${GITHUB_RUN_NUMBER:-0}-${GITHUB_RUN_ATTEMPT:-1}"
|
|
|
|
echo "release_tag=${release_tag}" >> "$GITHUB_OUTPUT"
|
|
echo "publish_release=${publish_release}" >> "$GITHUB_OUTPUT"
|
|
echo "build_x86_64_netboot=${build_x86_64_netboot}" >> "$GITHUB_OUTPUT"
|
|
echo "build_x86_64_iso=${build_x86_64_iso}" >> "$GITHUB_OUTPUT"
|
|
echo "artifact_suffix=${artifact_suffix}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Build runner boot images
|
|
env:
|
|
BUILD_X86_64_NETBOOT: ${{ steps.plan.outputs.build_x86_64_netboot }}
|
|
BUILD_X86_64_ISO: ${{ steps.plan.outputs.build_x86_64_iso }}
|
|
ARTIFACT_SUFFIX: ${{ steps.plan.outputs.artifact_suffix }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
cd .repo
|
|
|
|
if [[ -f "$HOME/.nix-profile/etc/profile.d/nix.sh" ]]; then
|
|
# shellcheck disable=SC1091
|
|
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
|
|
fi
|
|
export PATH="$HOME/.nix-profile/bin:$PATH"
|
|
|
|
artifacts_dir="$PWD/.artifacts"
|
|
rm -rf "${artifacts_dir}"
|
|
mkdir -p "${artifacts_dir}"
|
|
|
|
nix_args=(--accept-flake-config --extra-experimental-features "nix-command flakes")
|
|
|
|
if [[ "${BUILD_X86_64_NETBOOT}" == "true" ]]; then
|
|
nix build "${nix_args[@]}" \
|
|
.#nixosConfigurations.ec-runner-x86_64-netboot.config.system.build.netboot \
|
|
-o result-netboot-x86_64
|
|
tar -C result-netboot-x86_64 \
|
|
-czf "${artifacts_dir}/ec-runner-x86_64-netboot-${ARTIFACT_SUFFIX}.tar.gz" \
|
|
kernel initrd netboot.ipxe
|
|
fi
|
|
|
|
if [[ "${BUILD_X86_64_ISO}" == "true" ]]; then
|
|
nix build "${nix_args[@]}" \
|
|
.#nixosConfigurations.ec-runner-x86_64-iso.config.system.build.isoImage \
|
|
-o result-iso-x86_64
|
|
iso_source=""
|
|
if [[ -f result-iso-x86_64 ]]; then
|
|
iso_source="result-iso-x86_64"
|
|
else
|
|
iso_source="$(find -L result-iso-x86_64 -type f -name '*.iso' | head -n 1 || true)"
|
|
fi
|
|
if [[ -z "${iso_source}" ]]; then
|
|
echo "error: could not locate ISO output from result-iso-x86_64" >&2
|
|
exit 2
|
|
fi
|
|
cp -f "${iso_source}" "${artifacts_dir}/ec-runner-x86_64-iso-${ARTIFACT_SUFFIX}.iso"
|
|
fi
|
|
|
|
if ! find "${artifacts_dir}" -maxdepth 1 -type f | grep -q .; then
|
|
echo "error: no image artifacts were produced" >&2
|
|
exit 2
|
|
fi
|
|
|
|
(
|
|
cd "${artifacts_dir}"
|
|
sha256sum -- * > SHA256SUMS.txt
|
|
ls -lh
|
|
)
|
|
|
|
- name: Publish artifacts to Forgejo release
|
|
if: ${{ steps.plan.outputs.publish_release == 'true' }}
|
|
env:
|
|
GITHUB_TOKEN: ${{ github.token }}
|
|
RELEASE_TAG: ${{ steps.plan.outputs.release_tag }}
|
|
shell: bash
|
|
run: |
|
|
set -euo pipefail
|
|
cd .repo
|
|
|
|
if [[ -z "${GITHUB_TOKEN:-}" ]]; then
|
|
echo "error: missing github.token"
|
|
exit 2
|
|
fi
|
|
if [[ -z "${GITHUB_SERVER_URL:-}" ]]; then
|
|
echo "error: missing GITHUB_SERVER_URL"
|
|
exit 2
|
|
fi
|
|
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
|
echo "error: missing GITHUB_REPOSITORY"
|
|
exit 2
|
|
fi
|
|
|
|
api_base="${GITHUB_SERVER_URL%/}/api/v1/repos/${GITHUB_REPOSITORY}"
|
|
release_json="$(curl -fsSL \
|
|
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
"${api_base}/releases/tags/${RELEASE_TAG}" 2>/dev/null || true)"
|
|
|
|
if [[ -z "${release_json}" ]]; then
|
|
payload="$(cat <<JSON
|
|
{
|
|
"tag_name": "${RELEASE_TAG}",
|
|
"name": "Boot images ${RELEASE_TAG}",
|
|
"body": "Automated runner boot image build from ${GITHUB_SHA}.",
|
|
"draft": false,
|
|
"prerelease": false
|
|
}
|
|
JSON
|
|
)"
|
|
release_json="$(curl -fsSL -X POST \
|
|
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
-H "content-type: application/json" \
|
|
"${api_base}/releases" \
|
|
-d "${payload}")"
|
|
fi
|
|
|
|
release_id=""
|
|
if command -v python3 >/dev/null 2>&1; then
|
|
release_id="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"${release_json}" 2>/dev/null || true)"
|
|
fi
|
|
if [[ -z "${release_id}" ]]; then
|
|
release_id="$(printf '%s' "${release_json}" \
|
|
| sed -nE 's/.*"id"[[:space:]]*:[[:space:]]*([0-9]+).*/\1/p' \
|
|
| head -n 1)"
|
|
fi
|
|
if [[ -z "${release_id}" ]]; then
|
|
echo "error: failed to resolve release id for ${RELEASE_TAG}" >&2
|
|
exit 2
|
|
fi
|
|
|
|
for asset_path in .artifacts/*; do
|
|
[[ -f "${asset_path}" ]] || continue
|
|
asset_name="$(basename "${asset_path}")"
|
|
curl -fsSL -X POST \
|
|
-H "Authorization: token ${GITHUB_TOKEN}" \
|
|
-H "content-type: application/octet-stream" \
|
|
--data-binary @"${asset_path}" \
|
|
"${api_base}/releases/${release_id}/assets?name=${asset_name}" >/dev/null
|
|
echo "uploaded: ${asset_name}"
|
|
done
|