Skip to content

Commit

Permalink
Add the new CI workflow and related files
Browse files Browse the repository at this point in the history
In addition to the new CI workflow (`ci.yml`), some other files are
needed to run it:

- The inner part of the workflow is implemented as a separate reusable
  workflow (`ci-per-system.yml`); this reusable workflow is invoked
  separately for every supported `system` value.
- The common parts of various Nix build jobs are factored out to a
  composite action (`nix-build`).

The build job for `x86_64-darwin` is disabled for now (the first test
will be performed just for `x86_64-linux`).
  • Loading branch information
sigprof committed Jul 4, 2022
1 parent 7626644 commit bc619fa
Show file tree
Hide file tree
Showing 4 changed files with 680 additions and 1 deletion.
153 changes: 153 additions & 0 deletions .github/actions/nix-build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
name: 'Build Nix derivations'
description: >
Install Nix, set up binary caching using Cachix, then build Nix derivations
according to the specification in JSON format. After the build finishes,
save any build logs produced by Nix in an artifact.
inputs:
item:
required: true
description: The item to build specified in the JSON format.
system:
required: true
description: Nix system name.
channel:
required: false
description: Nixpkgs channel (used for NUR packages).

# Inputs passed to `cachix/install-nix-action`.
nix-install-url:
required: false
description: 'Installation URL that will contain a script to install Nix.'
nix-install-options:
required: false
description: 'Additional installer flags passed to the Nix installer script.'
nix-path:
required: false
description: 'Set NIX_PATH environment variable.'
nix-extra-config:
required: false
description: 'gets appended to `/etc/nix/nix.conf` if passed.'

# Inputs passed to `cachix/cachix-action`.
cachix-name:
required: false
description: 'Name of a Cachix cache to push and pull/substitute'
cachix-extra-pull-names:
required: false
description: 'Comma-separated list of names for extra Cachix caches to pull/substitute'
cachix-auth-token:
required: false
description: 'Authentication token for Cachix, needed only for private cache access'
cachix-signing-key:
required: false
description: 'Signing key secret retrieved after creating binary cache on https://cachix.org'
cachix-skip-push:
required: false
description: 'Set to true to disable pushing build results to the cache'
#cachix-paths-to-push:
# required: false
# description: 'Whitespace-separated list of paths to push. Leave empty to push every build result.'
cachix-push-filter:
required: false
description: >
Regular expression to exclude derivations for the cache push, for example
"(-source$|nixpkgs\.tar\.gz$)".
Warning: this filter does not guarantee it will not get pushed in case
the path is part of the closure of something that will get pushed.
#cachix-args:
# required: false
# description: 'Extra command-line arguments to pass to cachix. If empty, defaults to -j8'
cachix-install-command:
required: false
description: 'Override the default cachix installation method'

runs:
using: composite
steps:
- name: Install Nix
uses: sigprof/install-nix-action@6c5ba55bfdc791cfad61ac72e473340c1c3ac992
with:
install_url: ${{ inputs.nix-install-url }}
install_options: ${{ inputs.nix-install-options }}
nix_path: ${{ inputs.nix-path }}
extra_nix_config: ${{ inputs.nix-extra-config }}

- name: Setup Cachix
uses: cachix/cachix-action@v10
if: inputs.cachix-name
with:
name: ${{ inputs.cachix-name }}
extraPullNames: ${{ inputs.cachix-extra-pull-names }}
authToken: ${{ inputs.cachix-auth-token }}
signingKey: ${{ inputs.cachix-signing-key }}
skipPush: ${{ inputs.cachix-skip-push }}
#pathsToPush: ${{ inputs.cachix-paths-to-push }}
pushFilter: ${{ inputs.cachix-push-filter }}
#cachixArgs: ${{ inputs.cachix-args }}
installCommand: ${{ inputs.cachix-install-command }}

- name: Build
shell: bash
env:
ITEM: ${{ inputs.item }}
SYSTEM: ${{ inputs.system }}
CHANNEL: ${{ inputs.channel }}
run: |
# Build script
# Remove unrelated build logs left by the Nix installer
sudo rm -rf /nix/var/log/nix/drvs/* ||:
if [ -n "$CHANNEL" ]; then
export NIX_PATH="nixpkgs=channel:$CHANNEL"
fi
echo "::group::Determining arguments for 'nix build'"
build_args="$(
jq -rn --arg system "$SYSTEM" '
env.ITEM | fromjson |
([.nurPackages[]]? | ["-f default.nix"] + . | .[])?,
(.packages[] | @text ".#packages."+$system+".\(.)")?,
(.checks[] | @text ".#checks."+$system+".\(.)")?,
(.hosts[] | @text ".#nixosConfigurations.\(.).config.system.build.toplevel")?
'
)"
printf ' %s\n' $build_args
echo "::endgroup::"
echo "::group::Creating derivations for build"
build_output="$( nix build --dry-run --json $build_args )"
drv_list="$(
printf '%s' "$build_output" | jq -r '.[].drvPath'
)"
echo "::endgroup::"
echo "::group::Derivation list:"
printf ' %s\n' $drv_list
echo "::endgroup::"
echo "::group::Building derivations"
build_result=0
# Use nix-build-uncached from the locked version of nixpkgs
nix shell --impure --expr '(builtins.getFlake (toString ./.)).inputs.nixpkgs.legacyPackages.${builtins.currentSystem}.nix-build-uncached' \
-c nix-build-uncached $drv_list || build_result=$?
echo "::endgroup::"
echo "::group::Saving build logs"
mkdir -p .build/logs
( cd /nix/var/log/nix/drvs && find . -type f; ) |
while read log_src; do
log_src="${log_src##./}"
log_dst="${log_src//\//}"
printf '%s\n' "$log_dst"
cp /nix/var/log/nix/drvs/"$log_src" .build/logs/"$log_dst" || touch .build/logs_fail
done
echo "::endgroup::"
if [ -f .build/logs_fail ]; then
echo "Warning: Some log files could not be copied" 1>&2
fi
exit $build_result
- name: Upload build logs
if: always()
uses: actions/[email protected]
with:
name: build-logs-${{inputs.system}}-${{github.job}}-${{strategy.job-index}}
path: ".build/logs/*"
if-no-files-found: ignore
218 changes: 218 additions & 0 deletions .github/workflows/ci-per-system.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
name: CI per system
on:
workflow_call:
inputs:
system:
required: true
type: string
description: >
System name in the format used by Nix (e.g., `x86_64-linux`).
runs-on:
required: true
type: string
description: >
GitHub machine type to be used for the build (e.g., `ubuntu-latest`).
Needs to be compatible with the specified value of `system`.
flake-jobs:
type: string
default: ''
description: >
The description of flake-related build jobs in the JSON format, or an
empty string if no flake builds need to be performed.
nur-jobs:
type: string
default: ''
description: >
The description of NUR-related build jobs in the JSON format, or an
empty string if no NUR builds need to be performed.
cachix-name:
type: string
default: ''
description: >
Name of a Cachix cache to push and pull/substitute.
cachix-extra-pull-names:
type: string
default: ''
description: >
Comma-separated list of names for extra Cachix caches to
pull/substitute.
secrets:
cachix-auth-token:
required: false
description: >
Authentication token for Cachix; needed for private cache access and
for pushing objects to the cache.
cachix-signing-key:
required: false
description: >
Signing key secret for Cachix; needed for pushing objects to the
cache when signing is not managed by the Cachix service.
jobs:
early-checks:
runs-on: ${{ inputs.runs-on }}
if: fromJSON(inputs.flake-jobs).earlyChecks.item[0]
strategy:
matrix: ${{ fromJSON(inputs.flake-jobs).earlyChecks }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

pkgs:
runs-on: ${{ inputs.runs-on }}
if: fromJSON(inputs.flake-jobs).packages.item[0]
strategy:
matrix: ${{ fromJSON(inputs.flake-jobs).packages }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

nur:
runs-on: ${{ inputs.runs-on }}
if: fromJSON(inputs.nur-jobs).other.include[0]
strategy:
matrix: ${{ fromJSON(inputs.nur-jobs).other }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
channel: ${{ matrix.channel }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

nur1:
runs-on: ${{ inputs.runs-on }}
if: fromJSON(inputs.nur-jobs).stage1.include[0]
strategy:
matrix: ${{ fromJSON(inputs.nur-jobs).stage1 }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
channel: ${{ matrix.channel }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

nur2:
needs:
- pkgs
runs-on: ${{ inputs.runs-on }}
if: >
always() &&
(needs.pkgs.result == 'success' || needs.pkgs.result == 'skipped') &&
fromJSON(inputs.nur-jobs).stage2.include[0]
strategy:
matrix: ${{ fromJSON(inputs.nur-jobs).stage2 }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
channel: ${{ matrix.channel }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

nur3:
needs:
- nur1
runs-on: ${{ inputs.runs-on }}
if: >
always() &&
(needs.nur1.result == 'success' || needs.nur1.result == 'skipped') &&
fromJSON(inputs.nur-jobs).stage3.include[0]
strategy:
matrix: ${{ fromJSON(inputs.nur-jobs).stage3 }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
channel: ${{ matrix.channel }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

hosts:
needs:
- pkgs
runs-on: ${{ inputs.runs-on }}
if: >
always() &&
(needs.pkgs.result == 'success' || needs.pkgs.result == 'skipped') &&
fromJSON(inputs.flake-jobs).hosts.item[0]
strategy:
matrix: ${{ fromJSON(inputs.flake-jobs).hosts }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}

checks:
needs:
- pkgs
runs-on: ${{ inputs.runs-on }}
if: >
always() &&
(needs.pkgs.result == 'success' || needs.pkgs.result == 'skipped') &&
fromJSON(inputs.flake-jobs).checks.item[0]
strategy:
matrix: ${{ fromJSON(inputs.flake-jobs).checks }}
steps:
- name: Checkout
uses: actions/[email protected]
- name: Build
uses: ./.github/actions/nix-build
with:
item: ${{ toJSON(matrix.item) }}
system: ${{ inputs.system }}
cachix-name: ${{ inputs.cachix-name }}
cachix-extra-pull-names: ${{ inputs.cachix-extra-pull-names }}
cachix-auth-token: ${{ secrets.cachix-auth-token }}
cachix-signing-key: ${{ secrets.cachix-signing-key }}
Loading

0 comments on commit bc619fa

Please sign in to comment.