From d79461ab84e201877b42296f7a065401376ef6d6 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 29 Dec 2025 02:26:49 +0300 Subject: [PATCH 1/6] maintainers/upload-release.pl: Make more configurable This allows for testing with a local minio deployment like: ./upload-release.pl --skip-docker --skip-git --s3-endpoint http://localhost:9000 --s3-host localhost:9000 1821360 (cherry picked from commit d19b8d5f992f68ede23f928a296f7872971041e7) --- maintainers/upload-release.pl | 210 +++++++++++++++++++++------------- 1 file changed, 128 insertions(+), 82 deletions(-) diff --git a/maintainers/upload-release.pl b/maintainers/upload-release.pl index 31a9c71d5..19666590e 100755 --- a/maintainers/upload-release.pl +++ b/maintainers/upload-release.pl @@ -1,7 +1,8 @@ #! /usr/bin/env nix-shell -#! nix-shell -i perl -p perl perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.FileSlurp perlPackages.NetAmazonS3 gnupg1 +#! nix-shell -i perl -p awscli perl perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.FileSlurp perlPackages.NetAmazonS3 perlPackages.GetoptLongDescriptive gnupg1 use strict; +use Getopt::Long::Descriptive; use Data::Dumper; use File::Basename; use File::Path; @@ -13,7 +14,30 @@ use Net::Amazon::S3; delete $ENV{'shell'}; # shut up a LWP::UserAgent.pm warning -my $evalId = $ARGV[0] or die "Usage: $0 EVAL-ID\n"; +my ($opt, $usage) = describe_options( + '%c %o ', + [ 'skip-docker', 'Skip Docker image upload' ], + [ 'skip-git', 'Skip Git tagging' ], + [ 'skip-s3', 'Skip S3 upload' ], + [ 'docker-owner=s', 'Docker image owner', { default => 'nixos/nix' } ], + [ 'project-root=s', 'Pristine git repository path' ], + [ 's3-endpoint=s', 'Custom S3 endpoint' ], + [ 's3-host=s', 'S3 host', { default => 's3-eu-west-1.amazonaws.com' } ], + [], + [ 'help|h', 'Show this help message', { shortcircuit => 1 } ], + [], + [ 'Environment variables:' ], + [ 'AWS_ACCESS_KEY_ID' ], + [ 'AWS_SECRET_ACCESS_KEY' ], + [ 'AWS_SESSION_TOKEN For OIDC' ], + [ 'IS_LATEST Set to "1" to mark as latest release' ], +); + +print($usage->text), exit if $opt->help; + +my $evalId = $ARGV[0] or do { print STDERR $usage->text; exit 1 }; + +die "--project-root is required unless --skip-git is specified\n" unless $opt->skip_git || $opt->project_root; my $releasesBucketName = "nix-releases"; my $channelsBucketName = "nix-channels"; @@ -62,25 +86,38 @@ File::Path::make_path($narCache); my $binaryCache = "https://cache.nixos.org/?local-nar-cache=$narCache"; # S3 setup. -my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'} or die "No AWS_ACCESS_KEY_ID given."; -my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'} or die "No AWS_SECRET_ACCESS_KEY given."; +my $aws_access_key_id = $ENV{'AWS_ACCESS_KEY_ID'}; +my $aws_secret_access_key = $ENV{'AWS_SECRET_ACCESS_KEY'}; +my $aws_session_token = $ENV{'AWS_SESSION_TOKEN'}; -my $s3 = Net::Amazon::S3->new( - { aws_access_key_id => $aws_access_key_id, - aws_secret_access_key => $aws_secret_access_key, - retry => 1, - host => "s3-eu-west-1.amazonaws.com", - }); +my ($s3, $releasesBucket, $s3_channels, $channelsBucket); -my $releasesBucket = $s3->bucket($releasesBucketName) or die; +unless ($opt->skip_s3) { + $aws_access_key_id or die "No AWS_ACCESS_KEY_ID given."; + $aws_secret_access_key or die "No AWS_SECRET_ACCESS_KEY given."; -my $s3_us = Net::Amazon::S3->new( - { aws_access_key_id => $aws_access_key_id, - aws_secret_access_key => $aws_secret_access_key, - retry => 1, - }); + $s3 = Net::Amazon::S3->new( + { aws_access_key_id => $aws_access_key_id, + aws_secret_access_key => $aws_secret_access_key, + $aws_session_token ? (aws_session_token => $aws_session_token) : (), + retry => 1, + host => $opt->s3_host, + secure => ($opt->s3_endpoint && $opt->s3_endpoint =~ /^http:/) ? 0 : 1, + }); -my $channelsBucket = $s3_us->bucket($channelsBucketName) or die; + $releasesBucket = $s3->bucket($releasesBucketName) or die; + + $s3_channels = Net::Amazon::S3->new( + { aws_access_key_id => $aws_access_key_id, + aws_secret_access_key => $aws_secret_access_key, + $aws_session_token ? (aws_session_token => $aws_session_token) : (), + retry => 1, + host => $opt->s3_host, + secure => ($opt->s3_endpoint && $opt->s3_endpoint =~ /^http:/) ? 0 : 1, + }); + + $channelsBucket = $s3_channels->bucket($channelsBucketName) or die; +} sub getStorePath { my ($jobName, $output) = @_; @@ -115,11 +152,12 @@ sub copyManual { File::Path::remove_tree("$tmpDir/manual.tmp", {safe => 1}); } - system("aws s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0 + my $awsEndpoint = $opt->s3_endpoint ? "--endpoint-url " . $opt->s3_endpoint : ""; + system("aws $awsEndpoint s3 sync '$tmpDir/manual' s3://$releasesBucketName/$releaseDir/manual") == 0 or die "syncing manual to S3\n"; } -copyManual; +copyManual unless $opt->skip_s3; sub downloadFile { my ($jobName, $productNr, $dstName) = @_; @@ -158,30 +196,12 @@ sub downloadFile { return $sha256_expected; } -downloadFile("binaryTarball.i686-linux", "1"); -downloadFile("binaryTarball.x86_64-linux", "1"); -downloadFile("binaryTarball.aarch64-linux", "1"); -downloadFile("binaryTarball.x86_64-darwin", "1"); -downloadFile("binaryTarball.aarch64-darwin", "1"); -eval { - downloadFile("binaryTarballCross.x86_64-linux.armv6l-unknown-linux-gnueabihf", "1"); -}; -warn "$@" if $@; -eval { - downloadFile("binaryTarballCross.x86_64-linux.armv7l-unknown-linux-gnueabihf", "1"); -}; -warn "$@" if $@; -eval { - downloadFile("binaryTarballCross.x86_64-linux.riscv64-unknown-linux-gnu", "1"); -}; -warn "$@" if $@; -downloadFile("installerScript", "1"); - -# Upload docker images to dockerhub. +# Upload docker images. my $dockerManifest = ""; my $dockerManifestLatest = ""; my $haveDocker = 0; +unless ($opt->skip_docker) { for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) { my $system = $platforms->[0]; my $dockerPlatform = $platforms->[1]; @@ -195,8 +215,8 @@ for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) { print STDERR "loading docker image for $dockerPlatform...\n"; system("docker load -i $tmpDir/$fn") == 0 or die; - my $tag = "nixos/nix:$version-$dockerPlatform"; - my $latestTag = "nixos/nix:latest-$dockerPlatform"; + my $tag = $opt->docker_owner . ":$version-$dockerPlatform"; + my $latestTag = $opt->docker_owner . ":latest-$dockerPlatform"; print STDERR "tagging $version docker image for $dockerPlatform...\n"; system("docker tag nix:$version $tag") == 0 or die; @@ -219,68 +239,94 @@ for my $platforms (["x86_64-linux", "amd64"], ["aarch64-linux", "arm64"]) { } if ($haveDocker) { + my $dockerOwner = $opt->docker_owner; print STDERR "creating multi-platform docker manifest...\n"; - system("docker manifest rm nixos/nix:$version"); - system("docker manifest create nixos/nix:$version $dockerManifest") == 0 or die; + system("docker manifest rm $dockerOwner:$version"); + system("docker manifest create $dockerOwner:$version $dockerManifest") == 0 or die; if ($isLatest) { print STDERR "creating latest multi-platform docker manifest...\n"; - system("docker manifest rm nixos/nix:latest"); - system("docker manifest create nixos/nix:latest $dockerManifestLatest") == 0 or die; + system("docker manifest rm $dockerOwner:latest"); + system("docker manifest create $dockerOwner:latest $dockerManifestLatest") == 0 or die; } print STDERR "pushing multi-platform docker manifest...\n"; - system("docker manifest push nixos/nix:$version") == 0 or die; + system("docker manifest push $dockerOwner:$version") == 0 or die; if ($isLatest) { print STDERR "pushing latest multi-platform docker manifest...\n"; - system("docker manifest push nixos/nix:latest") == 0 or die; + system("docker manifest push $dockerOwner:latest") == 0 or die; } } +} -# Upload nix-fallback-paths.nix. -write_file("$tmpDir/fallback-paths.nix", - "{\n" . - " x86_64-linux = \"" . getStorePath("build.nix-everything.x86_64-linux") . "\";\n" . - " i686-linux = \"" . getStorePath("build.nix-everything.i686-linux") . "\";\n" . - " aarch64-linux = \"" . getStorePath("build.nix-everything.aarch64-linux") . "\";\n" . - " riscv64-linux = \"" . getStorePath("buildCross.nix-everything.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" . - " x86_64-darwin = \"" . getStorePath("build.nix-everything.x86_64-darwin") . "\";\n" . - " aarch64-darwin = \"" . getStorePath("build.nix-everything.aarch64-darwin") . "\";\n" . - "}\n"); # Upload release files to S3. -for my $fn (glob "$tmpDir/*") { - my $name = basename($fn); - next if $name eq "manual"; - my $dstKey = "$releaseDir/" . $name; - unless (defined $releasesBucket->head_key($dstKey)) { - print STDERR "uploading $fn to s3://$releasesBucketName/$dstKey...\n"; +unless ($opt->skip_s3) { + downloadFile("binaryTarball.i686-linux", "1"); + downloadFile("binaryTarball.x86_64-linux", "1"); + downloadFile("binaryTarball.aarch64-linux", "1"); + downloadFile("binaryTarball.x86_64-darwin", "1"); + downloadFile("binaryTarball.aarch64-darwin", "1"); + eval { + downloadFile("binaryTarballCross.x86_64-linux.armv6l-unknown-linux-gnueabihf", "1"); + }; + warn "$@" if $@; + eval { + downloadFile("binaryTarballCross.x86_64-linux.armv7l-unknown-linux-gnueabihf", "1"); + }; + warn "$@" if $@; + eval { + downloadFile("binaryTarballCross.x86_64-linux.riscv64-unknown-linux-gnu", "1"); + }; + warn "$@" if $@; + downloadFile("installerScript", "1"); - my $configuration = (); - $configuration->{content_type} = "application/octet-stream"; + # Upload nix-fallback-paths.nix. + write_file("$tmpDir/fallback-paths.nix", + "{\n" . + " x86_64-linux = \"" . getStorePath("build.nix-everything.x86_64-linux") . "\";\n" . + " i686-linux = \"" . getStorePath("build.nix-everything.i686-linux") . "\";\n" . + " aarch64-linux = \"" . getStorePath("build.nix-everything.aarch64-linux") . "\";\n" . + " riscv64-linux = \"" . getStorePath("buildCross.nix-everything.riscv64-unknown-linux-gnu.x86_64-linux") . "\";\n" . + " x86_64-darwin = \"" . getStorePath("build.nix-everything.x86_64-darwin") . "\";\n" . + " aarch64-darwin = \"" . getStorePath("build.nix-everything.aarch64-darwin") . "\";\n" . + "}\n"); - if ($fn =~ /.sha256|install|\.nix$/) { - $configuration->{content_type} = "text/plain"; + for my $fn (glob "$tmpDir/*") { + my $name = basename($fn); + next if $name eq "manual"; + my $dstKey = "$releaseDir/" . $name; + unless (defined $releasesBucket->head_key($dstKey)) { + print STDERR "uploading $fn to s3://$releasesBucketName/$dstKey...\n"; + + my $configuration = (); + $configuration->{content_type} = "application/octet-stream"; + + if ($fn =~ /.sha256|install|\.nix$/) { + $configuration->{content_type} = "text/plain"; + } + + $releasesBucket->add_key_filename($dstKey, $fn, $configuration) + or die $releasesBucket->err . ": " . $releasesBucket->errstr; } - - $releasesBucket->add_key_filename($dstKey, $fn, $configuration) - or die $releasesBucket->err . ": " . $releasesBucket->errstr; } + + # Update the "latest" symlink. + $channelsBucket->add_key( + "nix-latest/install", "", + { "x-amz-website-redirect-location" => "https://releases.nixos.org/$releaseDir/install" }) + or die $channelsBucket->err . ": " . $channelsBucket->errstr + if $isLatest; } -# Update the "latest" symlink. -$channelsBucket->add_key( - "nix-latest/install", "", - { "x-amz-website-redirect-location" => "https://releases.nixos.org/$releaseDir/install" }) - or die $channelsBucket->err . ": " . $channelsBucket->errstr - if $isLatest; - # Tag the release in Git. -chdir("/home/eelco/Dev/nix-pristine") or die; -system("git remote update origin") == 0 or die; -system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die; -system("git push --tags") == 0 or die; -system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest; +unless ($opt->skip_git) { + chdir($opt->project_root) or die "Cannot chdir to " . $opt->project_root . ": $!"; + system("git remote update origin") == 0 or die; + system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die; + system("git push --tags") == 0 or die; + system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest; +} File::Path::remove_tree($narCache, {safe => 1}); File::Path::remove_tree($tmpDir, {safe => 1}); From 184bcfbc7f7807393eec023553a6187f87e782a3 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 29 Dec 2025 03:34:16 +0300 Subject: [PATCH 2/6] maintainers: Document git tag signing Previously it was only Eeclo doing releases that were signed with B541D55301270E0BCF15CA5D8170B4726D7198DE. Other linux distributions have the expectation (rightfully so) that our tags are signed. Let's document this. We could do cross-signing to make tracing the chain of trust easier for all Nix team members [1]. [1]: https://nixos.org/community/teams/nix/ (cherry picked from commit 6cb8b58a47789a208b28e8590358cb95da90bbb3) --- ...8A6F530EA202E5F651611314FAEA63448E1DF9.asc | 110 ++++++++++++++++++ ...41D55301270E0BCF15CA5D8170B4726D7198DE.asc | 51 ++++++++ maintainers/keys/README.md | 13 +++ maintainers/release-process.md | 2 +- 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 maintainers/keys/158A6F530EA202E5F651611314FAEA63448E1DF9.asc create mode 100644 maintainers/keys/B541D55301270E0BCF15CA5D8170B4726D7198DE.asc create mode 100644 maintainers/keys/README.md diff --git a/maintainers/keys/158A6F530EA202E5F651611314FAEA63448E1DF9.asc b/maintainers/keys/158A6F530EA202E5F651611314FAEA63448E1DF9.asc new file mode 100644 index 000000000..ea00c2c3d --- /dev/null +++ b/maintainers/keys/158A6F530EA202E5F651611314FAEA63448E1DF9.asc @@ -0,0 +1,110 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +7w== +=mXYP +-----END PGP PUBLIC KEY BLOCK----- diff --git a/maintainers/keys/B541D55301270E0BCF15CA5D8170B4726D7198DE.asc b/maintainers/keys/B541D55301270E0BCF15CA5D8170B4726D7198DE.asc new file mode 100644 index 000000000..dee0aef4c --- /dev/null +++ b/maintainers/keys/B541D55301270E0BCF15CA5D8170B4726D7198DE.asc @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=u5cX +-----END PGP PUBLIC KEY BLOCK----- diff --git a/maintainers/keys/README.md b/maintainers/keys/README.md new file mode 100644 index 000000000..ef473eada --- /dev/null +++ b/maintainers/keys/README.md @@ -0,0 +1,13 @@ +# Maintainer GPG Keys + +Release tags are signed by members of the [Nix maintainer team](https://nixos.org/community/teams/nix/) as part of the [release process](../release-process.md). This directory contains the public GPG keys used for signing. + +## Keys + +- **Eelco Dolstra** + GPG Fingerprint: `B541 D553 0127 0E0B CF15 CA5D 8170 B472 6D71 98DE` + +- **Sergei Zimmerman** + GPG Fingerprint: [`158A 6F53 0EA2 02E5 F651 6113 14FA EA63 448E 1DF9`](https://keys.openpgp.org/vks/v1/by-fingerprint/158A6F530EA202E5F651611314FAEA63448E1DF9) + + diff --git a/maintainers/release-process.md b/maintainers/release-process.md index f2c61302b..44beb7ef4 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -5,7 +5,7 @@ The release process is intended to create the following for each release: -* A Git tag +* A signed Git tag (public keys in `maintainers/keys/`) * Binary tarballs in https://releases.nixos.org/?prefix=nix/ From ef0ea6002ae8486888c927a495bbedfcddb74c0d Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 29 Dec 2025 03:31:37 +0300 Subject: [PATCH 3/6] ci: Add upload-release.yml This workflow is supposed to automate release uploads by using OIDC for AWS setup. DockerHub still uses long-lived credentials, but that's not fixable. In a follow-up we could set up release uploads to GHCR too. (cherry picked from commit 4599daa10e29a0588ee410e1c72d0fd6b33adb81) --- .github/workflows/upload-release.yml | 52 ++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/upload-release.yml diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml new file mode 100644 index 000000000..7beb3e8c9 --- /dev/null +++ b/.github/workflows/upload-release.yml @@ -0,0 +1,52 @@ +name: Upload Release +on: + workflow_dispatch: + inputs: + eval_id: + description: "Hydra evaluation ID" + required: true + type: number + is_latest: + description: "Mark as latest release" + required: false + type: boolean + default: false +permissions: + contents: read + id-token: write +jobs: + release: + runs-on: ubuntu-24.04 + environment: releases + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - uses: ./.github/actions/install-nix-action + with: + dogfood: false # Use stable version + use_cache: false # Don't want any cache injection shenanigans + extra_nix_config: | + experimental-features = nix-command flakes + - name: Set NIX_PATH from flake input + run: | + NIXPKGS_PATH=$(nix build --inputs-from .# nixpkgs#path --print-out-paths --no-link) + # Shebangs with perl have issues. Pin nixpkgs this way. nix shell should maybe + # get the same uberhack that nix-shell has to support it. + echo "NIX_PATH=nixpkgs=$NIXPKGS_PATH" >> "$GITHUB_ENV" + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@61815dcd50bd041e203e49132bacad1fd04d2708 # v5.1.1 + with: + role-to-assume: "arn:aws:iam::080433136561:role/nix-release" + role-session-name: nix-release-oidc-${{ github.run_id }} + aws-region: eu-west-1 + - name: Login to Docker Hub + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Upload release + run: | + ./maintainers/upload-release.pl \ + ${{ inputs.eval_id }} \ + --skip-git + env: + IS_LATEST: ${{ inputs.is_latest && '1' || '' }} From c3c0c35ae10ab9e2f568aaa577794010377c67f1 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Mon, 29 Dec 2025 23:01:54 +0300 Subject: [PATCH 4/6] upload-release: Also push to GHCR as part of the release process (cherry picked from commit a1569458cccef17153f8f69dba7ef64c2f347b7c) --- .github/workflows/docker-push.yml | 5 ----- .github/workflows/upload-release.yml | 17 +++++++++++++++++ maintainers/release-process.md | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docker-push.yml b/.github/workflows/docker-push.yml index d83b391e5..c4ccd1fe0 100644 --- a/.github/workflows/docker-push.yml +++ b/.github/workflows/docker-push.yml @@ -96,11 +96,6 @@ jobs: docker tag nix:$NIX_VERSION $IMAGE_ID:$NIX_VERSION docker push $IMAGE_ID:$NIX_VERSION if [ "$IS_MASTER" = "true" ]; then - # FIXME: Do not tag master as latest. Upload to GHCR as part of - # releng instead. Possibly adapt this reusable workflow for the (yet - # nonexistent) release workflow. - docker tag nix:$NIX_VERSION $IMAGE_ID:latest docker tag nix:$NIX_VERSION $IMAGE_ID:master - docker push $IMAGE_ID:latest docker push $IMAGE_ID:master fi diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 7beb3e8c9..82ce0c40b 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -14,6 +14,7 @@ on: permissions: contents: read id-token: write + packages: write jobs: release: runs-on: ubuntu-24.04 @@ -43,6 +44,12 @@ jobs: with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Login to GitHub Container Registry + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Upload release run: | ./maintainers/upload-release.pl \ @@ -50,3 +57,13 @@ jobs: --skip-git env: IS_LATEST: ${{ inputs.is_latest && '1' || '' }} + - name: Push to GHCR + run: | + DOCKER_OWNER="ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[A-Z]' '[a-z]')/nix" + ./maintainers/upload-release.pl \ + ${{ inputs.eval_id }} \ + --skip-git \ + --skip-s3 \ + --docker-owner "$DOCKER_OWNER" + env: + IS_LATEST: ${{ inputs.is_latest && '1' || '' }} diff --git a/maintainers/release-process.md b/maintainers/release-process.md index 44beb7ef4..360bf5f3d 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -9,7 +9,7 @@ release: * Binary tarballs in https://releases.nixos.org/?prefix=nix/ -* Docker images +* Docker images (arm64 and amd64 variants, uploaded to DockerHub and GHCR) * Closures in https://cache.nixos.org From a8149019b653376065078ceb08b507bca7060336 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Tue, 30 Dec 2025 02:14:25 +0300 Subject: [PATCH 5/6] upload-release: Only upload the newly created tag (cherry picked from commit 3933e45d522f67328fd0756d75884df1ad368495) --- maintainers/upload-release.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maintainers/upload-release.pl b/maintainers/upload-release.pl index 19666590e..2bd99ded8 100755 --- a/maintainers/upload-release.pl +++ b/maintainers/upload-release.pl @@ -324,7 +324,7 @@ unless ($opt->skip_git) { chdir($opt->project_root) or die "Cannot chdir to " . $opt->project_root . ": $!"; system("git remote update origin") == 0 or die; system("git tag --force --sign $version $nixRev -m 'Tagging release $version'") == 0 or die; - system("git push --tags") == 0 or die; + system("git push origin refs/tags/$version") == 0 or die; system("git push --force-with-lease origin $nixRev:refs/heads/latest-release") == 0 or die if $isLatest; } From eee30e8a6cb21cf3fe850c01d5b1644880026681 Mon Sep 17 00:00:00 2001 From: Sergei Zimmerman Date: Tue, 30 Dec 2025 02:27:38 +0300 Subject: [PATCH 6/6] release-process: Document usage of upload-release.yml workflow (cherry picked from commit 84ff2ef34764abd643437096245042285fbcaf86) --- maintainers/release-process.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/maintainers/release-process.md b/maintainers/release-process.md index 360bf5f3d..75415207e 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -101,21 +101,17 @@ release: evaluation ID (e.g. `1780832` in `https://hydra.nixos.org/eval/1780832`). -* Tag the release and upload the release artifacts to - [`releases.nixos.org`](https://releases.nixos.org/) and [Docker Hub](https://hub.docker.com/): +* Tag the release: ```console - $ IS_LATEST=1 ./maintainers/upload-release.pl + $ IS_LATEST=1 ./maintainers/upload-release.pl --skip-docker --skip-s3 --project-root $PWD ``` Note: `IS_LATEST=1` causes the `latest-release` branch to be force-updated. This is used by the `nixos.org` website to get the [latest Nix manual](https://nixos.org/manual/nixpkgs/unstable/). - TODO: This script requires the right AWS credentials. Document. - - TODO: This script currently requires a - `/home/eelco/Dev/nix-pristine`. +* Trigger the [`upload-release.yml` workflow](https://github.com/NixOS/nix/actions/workflows/upload-release.yml) via `workflow_dispatch` trigger. At the top click `Run workflow` -> select the current release branch from `Use workflow from` -> fill in `Hydra evaluation ID` with `` value from previous steps -> click `Run workflow`. Wait for the run to be approved by `NixOS/nix-team` (or bypass checks if warranted). Wait for the workflow to succeed. TODO: trigger nixos.org netlify: https://docs.netlify.com/configure-builds/build-hooks/ @@ -180,16 +176,18 @@ release: * Wait for the desired evaluation of the maintenance jobset to finish building. -* Run +* Tag the release ```console - $ IS_LATEST=1 ./maintainers/upload-release.pl + $ IS_LATEST=1 ./maintainers/upload-release.pl --skip-docker --skip-s3 --project-root $PWD ``` Omit `IS_LATEST=1` when creating a point release that is not on the most recent stable branch. This prevents `nixos.org` to going back to an older release. +* Trigger the [`upload-release.yml` workflow](https://github.com/NixOS/nix/actions/workflows/upload-release.yml) via `workflow_dispatch` trigger. At the top click `Run workflow` -> select the current release branch from `Use workflow from` -> fill in `Hydra evaluation ID` with `` value from previous steps -> click `Run workflow`. Wait for the run to be approved by `NixOS/nix-team` (or bypass checks if warranted). Wait for the workflow to succeed. + * Bump the version number of the release branch as above (e.g. to `2.12.2`).