diff --git a/.forgejo/workflows/installer.yaml b/.forgejo/workflows/installer.yaml new file mode 100644 index 0000000..fb17ffc --- /dev/null +++ b/.forgejo/workflows/installer.yaml @@ -0,0 +1,75 @@ +# title: install +# desc: generate a guix installer image +# adapted from https://github.com/SystemCrafters/guix-installer/ + +name: installer + +on: + push: + branches: + - main + +jobs: + build: + runs-on: docker + + container: + image: alpine:3.21 + options: "--cap-add=all --privileged" # needed for guix + + steps: + - name: Install dependencies + run: | + apk add --no-cache git nodejs util-linux + + - name: Git checkout + uses: actions/checkout@v4 + + - name: Guix cache + uses: actions/cache/restore@v4 + with: + path: ~/.cache/guix + key: guix-cache-${{ github.sha }} + restore-keys: | + guix-cache- + + - name: Install guix + run: | + SUBSTITUTE_URLS="https://ci.guix.gnu.org https://bordeaux.guix.gnu.org https://substitutes.nonguix.org https://substitutes.freya.cat" + + apk add --no-cache guix openrc + + cat < /etc/init.d/guix-daemon + #!/sbin/openrc-run + start(){ guix-daemon --build-users-group=guixbuild --substitute-urls="$SUBSTITUTE_URLS" & } + EOF + chmod +x /etc/init.d/guix-daemon + + rc-update add guix-daemon + openrc boot + + - name: Setup channels + run: | + export GUIX_RETRY_NO_PROMPT=yes + export GUIX_RETRY_NO_TTY=yes + guix archive --authorize < ./files/keys/nonguix.pub + guix archive --authorize < ./files/keys/sakura.pub + ./scripts/guix-retry guix pull -C ./channels.scm + + - name: Build ISO + run: | + export GUIX_RETRY_NO_PROMPT=yes + export GUIX_RETRY_NO_TTY=yes + ./scripts/build-installer + + - name: Guix cache save + uses: actions/cache/save@v4 + with: + path: ~/.cache/guix + key: guix-cache-${{ github.sha }} + + - name: Save artifact + uses: actions/upload-artifact@v4 + with: + name: installer + path: guix-installer-*.iso diff --git a/channels.scm b/channels.scm index 2cc48a0..0c256cd 100644 --- a/channels.scm +++ b/channels.scm @@ -3,7 +3,7 @@ (url "https://git.savannah.gnu.org/git/guix.git") (branch "master") (commit - "a9003b8e6b40b59c9545ae87bb441d3549630db7") + "2b32a3809883a9b0fc38a79886921f1a53e00425") (introduction (make-channel-introduction "9edb3f66fd807b096b48283debdcddccfea34bad" @@ -14,7 +14,7 @@ (url "https://gitlab.com/nonguix/nonguix.git") (branch "master") (commit - "5a7e61a0a5bc191d8558a845bd724a0d41e0afbd") + "10e3c2bcaedaba121eec0e255d366a080082cf0a") (introduction (make-channel-introduction "897c1a470da759236cc11798f4e0a5f7d4d59fbc" @@ -25,7 +25,7 @@ (url "https://g.freya.cat/freya/sakura") (branch "main") (commit - "3caf3d17b1e5e76f1bf948e6799085b27d204bed") + "db9a1e89bf4d730232c5c8ab705a1bab01262a25") (introduction (make-channel-introduction "8fb2f9c2fa414754c41c1c73665e3e73e12693ab" diff --git a/scripts/build-installer b/scripts/build-installer index 10cd84c..4e4463c 100755 --- a/scripts/build-installer +++ b/scripts/build-installer @@ -1,28 +1,8 @@ #!/bin/sh +set -e -o pipefail retry="$(dirname $0)/guix-retry" repo="$(realpath "$(dirname $0)/..")" -extra_args="" - -if [ ! -d /gnu/store ]; then -# we are likely in a non guix system -# just for building the installer -# make sure to authorize the substitute -# servers for nonguix and sakura -guix archive --authorize < "$repo/files/keys/nonguix.pub" -guix archive --authorize < "$repo/files/keys/sakura.pub" -substitutes=$( -(cat <&1 # stdout -exec 22>&2 # stderr +# if the error output matches this regex, auto retry +# and dont prompt user. +auto_retry_regex="write_to_session_record_port" # Guix does not know how to + # gracefully reconnect TLS... +# run dir +run="${XDG_RUNTIME_DIR:-/tmp}/guix-retry/$$" +mkdir -p "$run" +# delete run dir on exit +function cleanup { + real="$(realpath "$run")" + if [[ ! "$real" = "/" ]]; then + rm -fr "$real" + fi +} + +trap cleanup EXIT + +# get error stream +stderr="$run/stderr" +mkfifo -m 600 "$stderr" + +log="$run/log" + +# unset fail on errors +set +e + +# retry command forever +# until success or abort while true; do - # send stdout to stdout - # send stderr though pipe - output=$("$@" 2>&1 1>&11 | tee >(cat - >&22)) # return stderr to - # normal stderr as well - # check if error is in stderr - if echo "$output" | grep -q "$error"; then + # execute command + if [[ ! -z "$GUIX_RETRY_NO_TTY" ]]; then + "$@" 2>"$stderr" & + else + command="$@" + script -q -c "$command" 2>"$stderr" "$log" & + fi + pid="$!" + output="$(cat "$stderr" | tee /dev/stderr)" + wait "$pid" + err="$?" + if [[ -z "$GUIX_RETRY_NO_TTY" ]]; then + err="$(tail -n1 "$log" | awk -F '"' '{ print $2 }')" + fi + + if [[ "$err" -eq 0 ]]; then + # command succeeded, break loop + break + fi + + if [[ "$output" =~ "$auto_retry_regex" ]]; then + # command errored and is set to auto retry continue fi - break + + if [[ ! -z "$GUIX_RETRY_NO_PROMPT" ]]; then + # do not prompt, just fail + exit 1 + fi + + # check if user wants to retry + read -p "Command failed. Retry? (y/N): " response + if [[ ! "$response" = "y" ]]; then + # command failed and told to abort, break loop + exit 1 + fi done