Merge pull request #25 from chaos-jetzt/gha-diff-new-hosts
Rework host diffing Now it'll detect wether there are changes to a hosts closure at all, lists build failures as such and is able to handle newly added or removed hosts. https://github.com/chaos-jetzt/chaos-jetzt-nixfiles/actions/runs/5770703946 shows the intended behavior when hosts are added, removed, builds fail or changes are made.
This commit is contained in:
commit
e58bfa3c35
2 changed files with 135 additions and 34 deletions
112
.github/scripts/diff-hosts.sh
vendored
Executable file
112
.github/scripts/diff-hosts.sh
vendored
Executable file
|
@ -0,0 +1,112 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# host_exists(flake, host)
|
||||||
|
# Checks if ${flake}#nixosConfigurations.$host
|
||||||
|
# Returns 0 if it does, 1 if it does not
|
||||||
|
function host_exists() {
|
||||||
|
local cmd="nix eval $1#nixosConfigurations --apply 'builtins.hasAttr \"$2\"'"
|
||||||
|
# echo "$cmd"
|
||||||
|
has_host=$(eval "$cmd")
|
||||||
|
if [[ $has_host == "true" ]]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# get_hosts(flake, available_hosts)
|
||||||
|
# Store a list of all available hosts in flake to $available_hosts
|
||||||
|
function get_hosts() {
|
||||||
|
local -n hosts=$2
|
||||||
|
IFS=" " read -r -a hosts <<< "$(nix eval $1#nixosConfigurations --raw --apply 'x: builtins.concatStringsSep " " (builtins.attrNames x)')"
|
||||||
|
}
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
# When using to check local changes, the step summary is not needed
|
||||||
|
step_summary="${GITHUB_STEP_SUMMARY-/dev/null}"
|
||||||
|
|
||||||
|
before_ref="${GITHUB_BASE_REF-main}"
|
||||||
|
before_ref="origin/${before_ref/#refs\/heads\//}"
|
||||||
|
if [[ $GITHUB_REF == "target/refs/main" ]]; then
|
||||||
|
# If triggered on main, compare with the previous commit
|
||||||
|
before_ref="$(git log HEAD~1 -1 --format=format:"%H")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
before_rev="$(git rev-parse "$before_ref")"
|
||||||
|
before_rev_abbr="$before_ref"
|
||||||
|
before_flake="git+file:.?ref=${before_rev}"
|
||||||
|
|
||||||
|
after_rev="$(git rev-parse --verify HEAD)"
|
||||||
|
after_rev_abbr="$(git rev-parse --abbrev-ref HEAD)"
|
||||||
|
if [[ -z $(git status --short) ]]; then
|
||||||
|
# If the working tree is clean, we can use the latest commit hash directly
|
||||||
|
# and thus profit from even more reduced build times
|
||||||
|
after_flake="git+file:.?ref=${after_rev}"
|
||||||
|
else
|
||||||
|
# That way the script can be used to check local (non commited) changes
|
||||||
|
after_flake="."
|
||||||
|
fi
|
||||||
|
|
||||||
|
before_hosts=()
|
||||||
|
get_hosts "$before_flake" before_hosts
|
||||||
|
after_hosts=()
|
||||||
|
get_hosts "$after_flake" after_hosts
|
||||||
|
all_hosts=( "${before_hosts[@]}" "${after_hosts[@]}" )
|
||||||
|
|
||||||
|
# Unite both arrays
|
||||||
|
# From https://stackoverflow.com/a/33153989
|
||||||
|
declare -A _all_hosts
|
||||||
|
for k in "${all_hosts[@]}"; do _all_hosts["$k"]=1; done
|
||||||
|
all_hosts=("${!_all_hosts[@]}")
|
||||||
|
|
||||||
|
echo -e "## Closure differences\n" >> "$step_summary"
|
||||||
|
dirty=""
|
||||||
|
if [[ -n $(git status --short) ]]; then
|
||||||
|
dirty="-DIRTY"
|
||||||
|
fi
|
||||||
|
echo -e "_Comparing prior $before_rev_abbr ([$before_rev]) with current $after_rev_abbr ([$after_rev]$dirty)_\n" | tee -a "$step_summary"
|
||||||
|
repo_url="${GITHUB_SERVER_URL}/$GITHUB_REPOSITORY"
|
||||||
|
{
|
||||||
|
echo "[$before_rev]: $repo_url/commit/$before_rev";
|
||||||
|
echo "[$after_rev]: $repo_url/commit/$after_rev";
|
||||||
|
} >> "$step_summary"
|
||||||
|
|
||||||
|
|
||||||
|
for host in "${all_hosts[@]}"; do
|
||||||
|
host_exists "$before_flake" "$host" && a_exists=true || a_exists=false
|
||||||
|
host_exists "$after_flake" "$host" && b_exists=true || b_exists=false
|
||||||
|
if $a_exists && ! $b_exists; then
|
||||||
|
echo -e "**${host}** was removed\n" | tee -a "$step_summary"
|
||||||
|
elif ! $a_exists && $b_exists; then
|
||||||
|
echo -e "**${host}** was added\n" | tee -a "$step_summary"
|
||||||
|
else
|
||||||
|
echo "::group::Diff-closures for ${host}"
|
||||||
|
drv="nixosConfigurations.$host.config.system.build.toplevel"
|
||||||
|
diff_cmd="nix store diff-closures ${before_flake}#${drv} ${after_flake}#${drv}"
|
||||||
|
# Initially build host so that we don't spam the log
|
||||||
|
change_lines=$($diff_cmd 2>&1 | wc -l)
|
||||||
|
# Run once so that we have the colorful output in the github actions log
|
||||||
|
$diff_cmd && build_ok=true || build_ok=false
|
||||||
|
if [[ $change_lines -gt 0 ]] || [[ ! $build_ok ]]; then
|
||||||
|
if $build_ok; then
|
||||||
|
echo "ok"
|
||||||
|
echo "${host} changed"
|
||||||
|
echo -e "<details>\n<summary><b>${host}</b> changed</summary>\n\n" >> "$step_summary"
|
||||||
|
else
|
||||||
|
echo "${host} failed to build"
|
||||||
|
echo -e "<details>\n<summary><b>${host}</b> failed to build</summary>\n\n" >> "$step_summary"
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo '```';
|
||||||
|
$diff_cmd --show-trace | sed -e 's/\x1b\[[0-9;]*m//g';
|
||||||
|
echo '```';
|
||||||
|
echo -e "\n</details>\n";
|
||||||
|
} >> "$step_summary" 2>&1
|
||||||
|
else
|
||||||
|
echo -e "**${host}** has not changed\n" | tee -a "$step_summary"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "::endgroup::"
|
||||||
|
fi
|
||||||
|
done
|
53
.github/workflows/build-systems.yaml
vendored
53
.github/workflows/build-systems.yaml
vendored
|
@ -26,46 +26,35 @@ jobs:
|
||||||
echo Discovered the following system configs
|
echo Discovered the following system configs
|
||||||
nix flake show . --json | jq ".nixosConfigurations|keys[]" -r
|
nix flake show . --json | jq ".nixosConfigurations|keys[]" -r
|
||||||
- name: Build systems
|
- name: Build systems
|
||||||
|
id: build
|
||||||
run: |
|
run: |
|
||||||
echo "## Builds succeeded" >> $GITHUB_STEP_SUMMARY
|
echo "## Building" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "" >> $GITHUB_STEP_SUMMARY
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| Host | Out path |" >> $GITHUB_STEP_SUMMARY
|
echo "| | Host | Out path |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "| ---- | -------- |" >> $GITHUB_STEP_SUMMARY
|
echo "| --- | ---- | -------- |" >> $GITHUB_STEP_SUMMARY
|
||||||
|
any_failed=false
|
||||||
for host in $(nix flake show . --json | jq ".nixosConfigurations|keys[]" -r); do
|
for host in $(nix flake show . --json | jq ".nixosConfigurations|keys[]" -r); do
|
||||||
echo "::group::Building ${host}"
|
echo "::group::Building ${host}"
|
||||||
drv=".#nixosConfigurations.$host.config.system.build.toplevel"
|
drv=".#nixosConfigurations.$host.config.system.build.toplevel"
|
||||||
build_cmd="nix build ${drv}"
|
build_cmd="nix build ${drv}"
|
||||||
#cachix watch-exec chaos-jetzt-nixfiles -- $build_cmd
|
failed=false
|
||||||
$build_cmd
|
$build_cmd --show-trace || { failed=true; any_failed=true; }
|
||||||
echo "::endgroup::"
|
echo "::endgroup::"
|
||||||
|
if ! $failed; then
|
||||||
|
symbol="✅"
|
||||||
out_path=$($build_cmd --print-out-paths)
|
out_path=$($build_cmd --print-out-paths)
|
||||||
|
out_path="\`${out_path}\`"
|
||||||
echo -e "\x1b[32;1mSuccessfully built .#nixosConfigurations.${host}\x1b[0m"
|
echo -e "\x1b[32;1mSuccessfully built .#nixosConfigurations.${host}\x1b[0m"
|
||||||
echo "| ${host} | \`${out_path}\` |" >> $GITHUB_STEP_SUMMARY
|
else
|
||||||
done
|
symbol="❌"
|
||||||
- name: Diff closures
|
out_path="_build failed_"
|
||||||
# Since this is only triggered by pushes to main, no need to compare to main for pushes
|
echo -e "\x1b[31;1mFailed to build .#nixosConfigurations.${host}\x1b[0m"
|
||||||
if: github.event_name != 'push'
|
|
||||||
run: |
|
|
||||||
# Compare to pull_request_target or, if this has no PR-Target, main
|
|
||||||
target_ref="${GITHUB_BASE_REF-main}"
|
|
||||||
target_ref="origin/${target_ref/#refs\/heads\//}"
|
|
||||||
if [[ $GITHUB_REF == "target/refs/main" ]]; then
|
|
||||||
# If triggered on main, compare with the previous commit
|
|
||||||
target_ref="$(git log HEAD~1 -1 --format=format:"%H")"
|
|
||||||
fi
|
fi
|
||||||
echo -e "## Closure differences\n" >> $GITHUB_STEP_SUMMARY
|
echo "| $symbol | ${host} | ${out_path} |" >> $GITHUB_STEP_SUMMARY
|
||||||
echo "_Comparing current $(git rev-parse --abbrev-ref HEAD) ($(git rev-parse --verify HEAD)) to ${target_ref} ($(git rev-parse $target_ref))_" | tee -a $GITHUB_STEP_SUMMARY
|
|
||||||
for host in $(nix flake show . --json | jq ".nixosConfigurations|keys[]" -r); do
|
|
||||||
echo "::group::Diff-closures for ${host}"
|
|
||||||
drv="nixosConfigurations.$host.config.system.build.toplevel"
|
|
||||||
diff_cmd="nix store diff-closures git+file:.?ref=${target_ref}#${drv} .#${drv}"
|
|
||||||
# Get the nice and colorfull output for the logs, running twice won't (significantly) prolong the runtime
|
|
||||||
$diff_cmd
|
|
||||||
echo -e "<details>\n<summary>Diff for ${host}</summary>\n" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
# Strip color codes so that the summary stays readable
|
|
||||||
$diff_cmd | sed -e 's/\x1b\[[0-9;]*m//g' >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo -e "\n</details>" >> $GITHUB_STEP_SUMMARY
|
|
||||||
echo "::endgroup::"
|
|
||||||
done
|
done
|
||||||
|
# Set return-code to 1 if any failed
|
||||||
|
! $any_failed
|
||||||
|
- name: Diff closures
|
||||||
|
# Still would like to see the changes for the non-failing hosts
|
||||||
|
if: ${{ success() }} || ${{ failure() }}
|
||||||
|
run: ./.github/scripts/diff-hosts.sh
|
||||||
|
|
Loading…
Reference in a new issue