Follow jolt-native's latest build nightly
The Android objects arrive as a flake input at a 'latest' alias, and a flake input stays where it was locked -- so main's lock drifts further behind every jolt-native build until someone runs an APK build. A scheduled job re-resolves that one input and commits the lock if it moved, so the default branch names a recent build on its own. It builds nothing: whether the new objects work is what an APK build answers. Needs FRQ_PUSH_TOKEN, a project access token with write_repository, because CI_JOB_TOKEN cannot push. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2e25898 parent: 76dcc6c added
.gitlab-ci.yml +53 -0 | new file mode 100644 | ||
| @@ -0,0 +1,53 @@ | ||
| 1 | +# One job, and it only ever runs on a schedule. | |
| 2 | +# | |
| 3 | +# jolt-native publishes its Android objects under a "latest" alias on every | |
| 4 | +# default-branch build, and frq takes them as a flake input. A flake input is | |
| 5 | +# locked once and then stays put, so "latest" only means latest when something | |
| 6 | +# re-resolves it. The `apk` recipe does that for the machine building an APK; | |
| 7 | +# this does it for the repository, so main's flake.lock names a recent build | |
| 8 | +# rather than whichever one it was first locked against. | |
| 9 | +# | |
| 10 | +# Nothing is built here. The job resolves one input, and if that moved, commits | |
| 11 | +# the lock file. Whether the new objects actually work is what an APK build | |
| 12 | +# answers, and that is deliberately not this job's business. | |
| 13 | +stages: [update] | |
| 14 | + | |
| 15 | +update-jolt-native: | |
| 16 | + stage: update | |
| 17 | + image: nixos/nix:latest | |
| 18 | + # Schedules only: on a push this would race whoever pushed, and on a merge | |
| 19 | + # request it would commit to a branch nobody asked it to touch. | |
| 20 | + rules: | |
| 21 | + - if: $CI_PIPELINE_SOURCE == "schedule" | |
| 22 | + variables: | |
| 23 | + # Committing reads the previous lock, so the checkout needs the git tree | |
| 24 | + # rather than a shallow single commit. | |
| 25 | + GIT_DEPTH: "0" | |
| 26 | + before_script: | |
| 27 | + - echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf | |
| 28 | + script: | |
| 29 | + - | | |
| 30 | + set -eu | |
| 31 | + nix flake update jolt-native-android | |
| 32 | + if git diff --quiet -- flake.lock; then | |
| 33 | + echo "already on the newest build; nothing to commit." | |
| 34 | + exit 0 | |
| 35 | + fi | |
| 36 | + # The alias moves whenever jolt-native builds, so name *which* build this | |
| 37 | + # landed on rather than saying "update flake.lock". lastModified is the | |
| 38 | + # only readable identity a tarball input carries — the jolt-native commit | |
| 39 | + # that produced it is not in the archive's metadata. | |
| 40 | + epoch=$(nix eval --raw --impure --expr \ | |
| 41 | + "builtins.toString (builtins.fromJSON (builtins.readFile ./flake.lock) | |
| 42 | + ).nodes.jolt-native-android.locked.lastModified") | |
| 43 | + stamp=$(date -u -d "@$epoch" +%Y-%m-%dT%H:%MZ) | |
| 44 | + git config user.email "$GITLAB_USER_EMAIL" | |
| 45 | + git config user.name "nightly" | |
| 46 | + git add flake.lock | |
| 47 | + # [skip ci] because this pushes to the default branch, and the only job | |
| 48 | + # in this file is the one already running. | |
| 49 | + git commit -m "Follow jolt-native to its $stamp build [skip ci]" | |
| 50 | + # CI_JOB_TOKEN cannot push. FRQ_PUSH_TOKEN is a project access token with | |
| 51 | + # write_repository, which is the one thing this job needs configured. | |
| 52 | + git push "https://oauth2:$FRQ_PUSH_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" \ | |
| 53 | + "HEAD:$CI_DEFAULT_BRANCH" | |
| new file mode 100644 | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | +# One job, and it only ever runs on a schedule. | ||
| 2 | +# | ||
| 3 | +# jolt-native publishes its Android objects under a "latest" alias on every | ||
| 4 | +# default-branch build, and frq takes them as a flake input. A flake input is | ||
| 5 | +# locked once and then stays put, so "latest" only means latest when something | ||
| 6 | +# re-resolves it. The `apk` recipe does that for the machine building an APK; | ||
| 7 | +# this does it for the repository, so main's flake.lock names a recent build | ||
| 8 | +# rather than whichever one it was first locked against. | ||
| 9 | +# | ||
| 10 | +# Nothing is built here. The job resolves one input, and if that moved, commits | ||
| 11 | +# the lock file. Whether the new objects actually work is what an APK build | ||
| 12 | +# answers, and that is deliberately not this job's business. | ||
| 13 | +stages: [update] | ||
| 14 | + | ||
| 15 | +update-jolt-native: | ||
| 16 | + stage: update | ||
| 17 | + image: nixos/nix:latest | ||
| 18 | + # Schedules only: on a push this would race whoever pushed, and on a merge | ||
| 19 | + # request it would commit to a branch nobody asked it to touch. | ||
| 20 | + rules: | ||
| 21 | + - if: $CI_PIPELINE_SOURCE == "schedule" | ||
| 22 | + variables: | ||
| 23 | + # Committing reads the previous lock, so the checkout needs the git tree | ||
| 24 | + # rather than a shallow single commit. | ||
| 25 | + GIT_DEPTH: "0" | ||
| 26 | + before_script: | ||
| 27 | + - echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf | ||
| 28 | + script: | ||
| 29 | + - | | ||
| 30 | + set -eu | ||
| 31 | + nix flake update jolt-native-android | ||
| 32 | + if git diff --quiet -- flake.lock; then | ||
| 33 | + echo "already on the newest build; nothing to commit." | ||
| 34 | + exit 0 | ||
| 35 | + fi | ||
| 36 | + # The alias moves whenever jolt-native builds, so name *which* build this | ||
| 37 | + # landed on rather than saying "update flake.lock". lastModified is the | ||
| 38 | + # only readable identity a tarball input carries — the jolt-native commit | ||
| 39 | + # that produced it is not in the archive's metadata. | ||
| 40 | + epoch=$(nix eval --raw --impure --expr \ | ||
| 41 | + "builtins.toString (builtins.fromJSON (builtins.readFile ./flake.lock) | ||
| 42 | + ).nodes.jolt-native-android.locked.lastModified") | ||
| 43 | + stamp=$(date -u -d "@$epoch" +%Y-%m-%dT%H:%MZ) | ||
| 44 | + git config user.email "$GITLAB_USER_EMAIL" | ||
| 45 | + git config user.name "nightly" | ||
| 46 | + git add flake.lock | ||
| 47 | + # [skip ci] because this pushes to the default branch, and the only job | ||
| 48 | + # in this file is the one already running. | ||
| 49 | + git commit -m "Follow jolt-native to its $stamp build [skip ci]" | ||
| 50 | + # CI_JOB_TOKEN cannot push. FRQ_PUSH_TOKEN is a project access token with | ||
| 51 | + # write_repository, which is the one thing this job needs configured. | ||
| 52 | + git push "https://oauth2:$FRQ_PUSH_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" \ | ||
| 53 | + "HEAD:$CI_DEFAULT_BRANCH" | ||