Skip to content

GitHub Actions image format builds #155

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/actions/generate-format/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Generate Format
description: Build a NixOS configuration using the specified nixos-generators format
inputs:
nix-exec-path:
description: Path to the nix executable
default: nix
format:
description: nixos-generate format name
system:
description: Target nixpkgs system (e.g. x86_64-linux)
default: x86_64-linux
nixpkgs-name:
description: Flake input name for the target nixpkgs version
default: nixpkgs
nixpkgs:
description: Search path/URL for the target nixpkgs
default: 'https://github.com/nixos/nixpkgs/archive/nixpkgs-unstable.tar.gz'
force-build:
description: Build the target format even if no corresponding flake check exists
flake:
description: Nix flake URL
default: ${{ github.workspace }}
runs:
using: composite
steps:
- name: Build the "${{ inputs.format }}" format
id: generate
shell: bash
run: ${{ github.action_path }}/generate-format.sh
env:
NIX_EXEC_PATH: ${{ inputs.nix-exec-path }}
FORMAT: ${{ inputs.format }}
SYSTEM: ${{ inputs.system }}
NIXPKGS_NAME: ${{ inputs.nixpkgs-name }}
NIXPKGS: ${{ inputs.nixpkgs }}
FORCE_BUILD: ${{ inputs.force-build }}
FLAKE: ${{ inputs.flake }}
74 changes: 74 additions & 0 deletions .github/actions/generate-format/generate-format.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/sh

set -x

printenv

die() {
rc="$?"
echo "::error file=nixos-generate::$*"
exit "$rc"
}

generate() {
timeout 20m \
"${NIX_EXEC_PATH:-nix}" run . \
-- \
-I "nixpkgs=${NIXPKGS?}" \
"$@"
}

getCheck() {
"${NIX_EXEC_PATH:-nix}" eval --json "${FLAKE:-.}#checks.\"${1?}\"" --apply "(builtins.hasAttr \"${2?}\")"
}

hasCheck() {
has_check=$(getCheck "$@") || die "failed to confirm availablity of check output"
[ "$has_check" = true ]
}

buildCheck() {
"${NIX_EXEC_PATH:-nix}" build "${FLAKE:-.}#checks.\"${1?}\".\"${2?}\""
}

buildAnyway() {
[ -n "${FORCE_BUILD:-}" ]
}

checkOutputs() {
path_var="$1"
shift

path="$1"
shift

test_type="$1"
shift

test "$test_type" "$path" || die "path $path does not exist or is not the expected type"
real=$(readlink -f "$path") || die "unable to resolve path to $path"
store_paths=$(nix-store -q --outputs "$real") || die "unable to get store path of $real"
echo "::set-output name=${path_var}::$(echo "$store_paths" | head -n 1)"
}

format="${FORMAT?}"
system="${SYSTEM:-x86_64-linux}"
nixpkgs_name="${NIXPKGS_NAME:-nixpkgs}"
check="${format}-${nixpkgs_name}"
out_link="./result-${format}"

if hasCheck "$system" "$check"; then
: # NOP
elif buildAnyway; then
buildCheck() { : ; }
else
printf 1>&2 -- "No flake check defined for format '%s' on system '%s' using nixpkgs '%s', and force-building is not enabled; exiting.\\n" \
"$format" "$system" "$nixpkgs_name"

exit 0
fi

out=$(generate -f "$format" --system "$system" -o "$out_link") || die "build exited with status $?"
buildCheck "$system" "$check" || die "flake build exited with status $?"
checkOutputs out "$out" -f
checkOutputs out_link "$out_link" -e
27 changes: 27 additions & 0 deletions .github/actions/get-flake-input-rev/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Get Rev
description: Get a Nix flake input revision from the flake lock file
inputs:
nix-exec-path:
description: Path to the nix executable
default: nix
flake-input-name:
description: Name of the flake input whose revision should be retrieved
default: nixpkgs
flake:
description: Nix flake URL
default: ${{ github.workspace }}
outputs:
rev:
description: Locked revision of the flake input
value: ${{ steps.get-rev.outputs.rev }}
runs:
using: composite
steps:
- name: Get flake input revision for "${{ inputs.flake-input-name }}" from ${{ inputs.flake-lock-path }}
id: get-rev
shell: bash
env:
NIX_EXEC_PATH: ${{ inputs.nix-exec-path }}
FLAKE_INPUT_NAME: ${{ inputs.flake-input-name }}
FLAKE: ${{ inputs.flake }}
run: ${{ github.action_path }}/get-flake-input-rev.sh
18 changes: 18 additions & 0 deletions .github/actions/get-flake-input-rev/get-flake-input-rev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

getRev() {
# Run in nix shell in order to use jq
# shellcheck disable=SC2016
"${NIX_EXEC_PATH:-nix}" develop "${FLAKE:-.}" --command \
bash -c '"$1" flake metadata --json "$2" | jq -r --arg input "$3" ".locks.nodes[\$input].locked.rev"' \
"$0" "${NIX_EXEC_PATH:-nix}" "${FLAKE:-.}" "${1?}"
}

rev=$(getRev "${FLAKE_INPUT_NAME:-nixpkgs}") || exit

if [ "$rev" = null ]; then
echo "::error file=${FLAKE:-.}::unable to retrieve revision for flake input ${FLAKE_INPUT_NAME:-nixpkgs}"
exit 1
fi

echo "::set-output name=rev::${rev}"
27 changes: 27 additions & 0 deletions .github/actions/list-formats/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: List Formats
description: List available nixos-generators formats
inputs:
nixos-generate-exec-path:
description: Path to the nixos-generate executable
default: ${{ github.workspace }}/nixos-generate
nix-exec-path:
description: Path to the nix executable
default: nix
flake:
description: Nix flake URL
default: ${{ github.workspace }}
outputs:
formats:
description: Available nixos-generators formats
value: ${{ steps.list-formats.outputs.formats }}
runs:
using: composite
steps:
- name: List available nixos-generators formats
id: list-formats
shell: bash
env:
NIXOS_GENERATE_EXEC_PATH: ${{ inputs.nixos-generate-exec-path }}
NIX_EXEC_PATH: ${{ inputs.nix-exec-path }}
FLAKE: ${{ inputs.flake }}
run: ${{ github.action_path }}/list-formats.sh
12 changes: 12 additions & 0 deletions .github/actions/list-formats/list-formats.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh

listFormats() {
# Run in nix shell in order to use jq
# shellcheck disable=SC2016
"${NIX_EXEC_PATH:-nix}" develop "${FLAKE:-.}" --command \
bash -c '"$1" --list | jq -cnMR "[inputs]"' \
"$0" "${NIXOS_GENERATE_EXEC_PATH:-./nixos-generate}"
}

formats=$(listFormats) || exit
echo "::set-output name=formats::${formats}"
121 changes: 119 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,127 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
# Nix Flakes doesn't work on shallow clones
fetch-depth: 0
# Nix Flakes doesn't work on shallow clones
fetch-depth: 0
- uses: cachix/install-nix-action@v17
- name: List flake structure
run: nix flake show
- name: Run unit tests (flake)
run: nix build -L
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v17
- name: Run flake checks
run: nix flake check --no-build --keep-going
introspect:
runs-on: ubuntu-latest
outputs:
nixpkgs-rev: ${{ steps.nixpkgs-rev.outputs.rev }}
nixos-rev: ${{ steps.nixos-rev.outputs.rev }}
formats: ${{ steps.list-formats.outputs.formats }}
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v17
- name: Get nixpkgs flake input rev
id: nixpkgs-rev
uses: ./.github/actions/get-flake-input-rev
with:
flake-input-name: nixpkgs
- name: Get nixos flake input rev
id: nixos-rev
uses: ./.github/actions/get-flake-input-rev
with:
flake-input-name: nixos
- name: List available formats
id: list-formats
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
uses: ./.github/actions/list-formats
default-formats:
strategy:
matrix:
format:
- amazon
- docker
- iso
- kexec-bundle
nixpkgs-name:
- nixpkgs
- nixos
include:
- nixpkgs-name: nixpkgs
nixpkgs: 'https://github.com/nixos/nixpkgs/archive/${{ needs.introspect.outputs.nixpkgs-rev }}.tar.gz'
- nixpkgs-name: nixos
nixpkgs: 'https://github.com/nixos/nixpkgs/archive/${{ needs.introspect.outputs.nixos-rev }}.tar.gz'
- format: kexec-bundle
force-build: yes
runs-on: ubuntu-latest
needs: [ 'check', 'introspect' ]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: cachix/install-nix-action@v17
with:
# kvm required for a number of formats; big-parallel required for
# proxmox and possibly others.
extra_nix_config: |
system-features = big-parallel kvm
- name: Build the "${{ matrix.format }}" format
id: generate
uses: ./.github/actions/generate-format
with:
format: ${{ matrix.format }}
system: ${{ matrix.system }}
nixpkgs-name: ${{ matrix.nixpkgs-name }}
nixpkgs: ${{ matrix.nixpkgs }}
force-build: ${{ matrix.force-build }}
all-formats:
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
strategy:
matrix:
format: ${{ needs.introspect.outputs.formats && fromJSON(needs.introspect.outputs.formats) }}
nixpkgs-name:
- nixpkgs
- nixos
include:
- nixpkgs-name: nixpkgs
nixpkgs: 'https://github.com/nixos/nixpkgs/archive/${{ needs.introspect.outputs.nixpkgs-rev }}.tar.gz'
- nixpkgs-name: nixos
nixpkgs: 'https://github.com/nixos/nixpkgs/archive/${{ needs.introspect.outputs.nixos-rev }}.tar.gz'
- format: kexec-bundle
force-build: yes
- format: sd-aarch64-installer
system: aarch64-linux
- format: sd-aarch64
system: aarch64-linux
runs-on: ubuntu-latest
needs: [ 'check', 'introspect' ]
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
# set up qemu if we are targeting a non-native system
- uses: docker/setup-qemu-action@v2
if: ${{ matrix.system }}
- uses: cachix/install-nix-action@v17
with:
# kvm required for a number of formats; big-parallel required for
# proxmox and possibly others.
extra_nix_config: |
system-features = big-parallel kvm
extra-platforms = ${{ matrix.system }}
- name: Build the "${{ matrix.format }}" format
id: generate
uses: ./.github/actions/generate-format
with:
format: ${{ matrix.format }}
system: ${{ matrix.system }}
nixpkgs-name: ${{ matrix.nixpkgs-name }}
nixpkgs: ${{ matrix.nixpkgs }}
force-build: ${{ matrix.force-build }}
Loading