From bb07a0a2220b44fc89f5a94dac13e57563b20a27 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 32635e4449f3d3383681a736a181396c8a4c1c42 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 68de3b677..c9eb44bfb 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 e999426f05fc0c86f57e805cbe746c5d96fd444f 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 1e6dad7e2fc8a44ed1032ef4cf4e3c4fd958efcc 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 c9eb44bfb..b273fc09d 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 9b49b5c050e16582eac6ad2d427aa1a3b197070e 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 6e098682bdf94e33aa34e0cf8d57be3dc9f82cde 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 b273fc09d..f8b6b6bec 100644 --- a/maintainers/release-process.md +++ b/maintainers/release-process.md @@ -104,21 +104,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/ @@ -181,16 +177,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`).