Publish a latest alias beside the commit-pinned artifacts
A consumer pinning a URL by commit has to edit a digest to move. Naming a stable 'latest' lets its flake input find a new build through nix flake update while flake.lock still records the bytes it built against. GitLab keeps every upload under a version rather than replacing it and serves the newest, so the alias grows per pipeline; a cleanup policy is what bounds it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67d1728 parent: d970307 modified
.gitlab-ci.yml +17 -5 | @@ -77,13 +77,25 @@ check: | ||
| 77 | 77 | if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then |
| 78 | 78 | tar czf x86_64-linux.tar.gz -C artifacts include lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so |
| 79 | 79 | tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a |
| 80 | - base="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jolt-native/$CI_COMMIT_SHA" | |
| 80 | + # Twice: once under the commit, which is what a consumer pins and what | |
| 81 | + # never moves, and once under "latest", which is the URL a consumer's | |
| 82 | + # `flake = false` input names so that `nix flake update` can find a new | |
| 83 | + # build without anyone editing a digest. The lock file still pins the | |
| 84 | + # bytes -- "latest" decides what an update *finds*, not what it builds. | |
| 85 | + # | |
| 86 | + # Uploading the same version and filename again does not replace the | |
| 87 | + # old file, it adds a second one and downloads serve the newest, so the | |
| 88 | + # "latest" package grows by one set of tarballs per pipeline. A project | |
| 89 | + # cleanup policy is what keeps that bounded. | |
| 90 | + api="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jolt-native" | |
| 81 | 91 | nix shell nixpkgs#curl -c sh -eu -c ' |
| 82 | - for f in x86_64-linux.tar.gz android-arm64-v8a.tar.gz; do | |
| 83 | - curl --fail-with-body --header "JOB-TOKEN: $CI_JOB_TOKEN" \ | |
| 84 | - --upload-file "$f" "$1/$f" | |
| 92 | + for v in "$2" latest; do | |
| 93 | + for f in x86_64-linux.tar.gz android-arm64-v8a.tar.gz; do | |
| 94 | + curl --fail-with-body --header "JOB-TOKEN: $CI_JOB_TOKEN" \ | |
| 95 | + --upload-file "$f" "$1/$v/$f" | |
| 96 | + done | |
| 85 | 97 | done |
| 86 | - ' sh "$base" | |
| 98 | + ' sh "$api" "$CI_COMMIT_SHA" | |
| 87 | 99 | fi |
| 88 | 100 | artifacts: |
| 89 | 101 | name: "jolt-native-$CI_COMMIT_SHORT_SHA" |
| @@ -77,13 +77,25 @@ check: | |||
| 77 | if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then | 77 | if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then |
| 78 | tar czf x86_64-linux.tar.gz -C artifacts include lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so | 78 | tar czf x86_64-linux.tar.gz -C artifacts include lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so |
| 79 | tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a | 79 | tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a |
| 80 | - base="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jolt-native/$CI_COMMIT_SHA" | 80 | + # Twice: once under the commit, which is what a consumer pins and what |
| 81 | + # never moves, and once under "latest", which is the URL a consumer's | ||
| 82 | + # `flake = false` input names so that `nix flake update` can find a new | ||
| 83 | + # build without anyone editing a digest. The lock file still pins the | ||
| 84 | + # bytes -- "latest" decides what an update *finds*, not what it builds. | ||
| 85 | + # | ||
| 86 | + # Uploading the same version and filename again does not replace the | ||
| 87 | + # old file, it adds a second one and downloads serve the newest, so the | ||
| 88 | + # "latest" package grows by one set of tarballs per pipeline. A project | ||
| 89 | + # cleanup policy is what keeps that bounded. | ||
| 90 | + api="$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jolt-native" | ||
| 81 | nix shell nixpkgs#curl -c sh -eu -c ' | 91 | nix shell nixpkgs#curl -c sh -eu -c ' |
| 82 | - for f in x86_64-linux.tar.gz android-arm64-v8a.tar.gz; do | 92 | + for v in "$2" latest; do |
| 83 | - curl --fail-with-body --header "JOB-TOKEN: $CI_JOB_TOKEN" \ | 93 | + for f in x86_64-linux.tar.gz android-arm64-v8a.tar.gz; do |
| 84 | - --upload-file "$f" "$1/$f" | 94 | + curl --fail-with-body --header "JOB-TOKEN: $CI_JOB_TOKEN" \ |
| 95 | + --upload-file "$f" "$1/$v/$f" | ||
| 96 | + done | ||
| 85 | done | 97 | done |
| 86 | - ' sh "$base" | 98 | + ' sh "$api" "$CI_COMMIT_SHA" |
| 87 | fi | 99 | fi |
| 88 | artifacts: | 100 | artifacts: |
| 89 | name: "jolt-native-$CI_COMMIT_SHORT_SHA" | 101 | name: "jolt-native-$CI_COMMIT_SHORT_SHA" |