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 </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