Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,4 @@ jobs:
with:
nix_path: nixpkgs=channel:nixos-unstable

- run: nix flake show
- run: nix build
39 changes: 20 additions & 19 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,34 +159,35 @@ jobs:
working-directory: artifacts
run: cosign sign-blob --yes checksums.txt --bundle checksums.txt.bundle

- name: Update flake.nix
- uses: cachix/install-nix-action@526118121621777ccd86f79b04685a9319637641 # v31
with:
nix_path: nixpkgs=channel:nixos-unstable

- name: Regenerate scala.lock.json
run: |
VERSION="${{ inputs.version }}"
# Maven Central propagation can take a few minutes after publish.
for i in $(seq 1 10); do
nix run github:scala-nix/scala-cli-nix -- lock-coords \
--dep "org.virtuslab::cellar-cli:${VERSION}" \
--main-class cellar.cli.CellarApp && break
echo "Attempt $i failed, retrying in 30s..."
sleep 30
done

# Convert hex sha256 to Nix SRI format (sha256-<base64>)
sri_hash() {
echo -n "$1" | xxd -r -p | base64 | tr -d '\n' | sed 's/^/sha256-/'
}

LINUX_X86=$(sri_hash "$(grep "linux-x86_64.tar.gz" artifacts/checksums.txt | awk '{print $1}')")
LINUX_ARM=$(sri_hash "$(grep "linux-aarch64.tar.gz" artifacts/checksums.txt | awk '{print $1}')")
MACOS_ARM=$(sri_hash "$(grep "macos-arm64.tar.gz" artifacts/checksums.txt | awk '{print $1}')")
MACOS_X86=$(sri_hash "$(grep "macos-x86_64.tar.gz" artifacts/checksums.txt | awk '{print $1}')")

sed -i "0,/version = \".*\";/s|version = \".*\";|version = \"${VERSION}\";|" flake.nix
sed -i "/linux-x86_64/{n;s|hash = \".*\";|hash = \"${LINUX_X86}\";|}" flake.nix
sed -i "/linux-aarch64/{n;s|hash = \".*\";|hash = \"${LINUX_ARM}\";|}" flake.nix
sed -i "/macos-x86_64/{n;s|hash = \".*\";|hash = \"${MACOS_X86}\";|}" flake.nix
sed -i "/macos-arm64/{n;s|hash = \".*\";|hash = \"${MACOS_ARM}\";|}" flake.nix
- name: Update flake.nix
run: |
VERSION="${{ inputs.version }}"
sed -i "s/version = \".*\";/version = \"${VERSION}\";/" flake.nix

- name: Commit, tag, and push
run: |
VERSION="${{ inputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add flake.nix
git diff --cached --quiet && echo "No flake changes" && exit 0
git commit -m "Update flake.nix to ${VERSION}"
git add flake.nix scala.lock.json
git diff --cached --quiet && echo "No changes to commit" && exit 0
git commit -m "Release ${VERSION}"
git push origin main
git tag "v${VERSION}"
git push origin "v${VERSION}"
Expand Down
5 changes: 4 additions & 1 deletion RELEASING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,15 @@ This document describes how to cut a release, what artifacts are produced, and h
- Publishes the `lib` and `cli` modules to Maven Central as `org.virtuslab:cellar-lib_3:<version>` and `org.virtuslab:cellar-cli_3:<version>`.
- Generates a SHA256 checksum file.
- Signs the checksum file using cosign keyless (OIDC).
- Updates `flake.nix` with the new version and SRI hashes, commits to `main`.
- Regenerates `scala.lock.json` from the freshly published Maven coordinates using `scn lock-coords` ([scala-cli-nix](https://github.com/scala-nix/scala-cli-nix)).
- Updates `version` in `flake.nix`, commits `flake.nix` and `scala.lock.json` to `main`.
- Creates and pushes a `v<version>` git tag.
- Publishes a GitHub Release with all artifacts attached.

The Maven publish waits for the native-binary and JAR builds to succeed before uploading — a Sonatype release is immutable, so we must not publish a version whose corresponding GitHub Release assets (referenced by the coursier app descriptor) failed to build. If Sonatype then rejects the upload (e.g. duplicate version, namespace mismatch, signature failure), no GitHub Release is created and no tag is pushed.

The `scala.lock.json` regeneration step retries up to 10 times with 30-second intervals to account for Maven Central propagation delay after publish.

No container images are built or published by this release flow.

## Supported platforms
Expand Down
8 changes: 8 additions & 0 deletions derivation.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{ scala-cli-nix, version }:

scala-cli-nix.buildCoursierApp {
pname = "cellar";
inherit version;
lockFile = ./scala.lock.json;
mainClass = "cellar.cli.CellarApp";
}
23 changes: 22 additions & 1 deletion flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 14 additions & 86 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,102 +1,30 @@
{
description = "Look up the public API of any JVM dependency from the terminal";

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
scala-cli-nix = {
url = "github:scala-nix/scala-cli-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};

outputs = { self, nixpkgs }:
outputs = { self, nixpkgs, scala-cli-nix }:
let
version = "0.1.0-M9";

# Per-platform release artifact metadata
platforms = {
x86_64-linux = {
archive = "cellar-${version}-linux-x86_64.tar.gz";
hash = "sha256-40JX4uEavG0VO2yMaeJFLm8rt8EQYLhs3F9dygglvxY=";
};
aarch64-linux = {
archive = "cellar-${version}-linux-aarch64.tar.gz";
hash = "sha256-2XxcxjpnnOsPkg9lcMBZMc/PCbovujseL9NTIkScXiY=";
};
x86_64-darwin = {
archive = "cellar-${version}-macos-x86_64.tar.gz";
hash = "sha256-aGv5hOQOhRycrfjp7zAO3lgveS6T0AqaKDxi74pkmE0=";
};
aarch64-darwin = {
archive = "cellar-${version}-macos-arm64.tar.gz";
hash = "sha256-Q23mpapwujuBtfyk/d8oFjmw8796BZP/zxg85tgpXvw=";
};
};

eachSystem = nixpkgs.lib.genAttrs (builtins.attrNames platforms);
systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
eachSystem = nixpkgs.lib.genAttrs systems;
in
{
packages = eachSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
meta = platforms.${system};
src = pkgs.fetchurl {
url = "https://github.com/VirtusLab/cellar/releases/download/v${version}/${meta.archive}";
hash = meta.hash;
pkgs = import nixpkgs {
inherit system;
overlays = [ scala-cli-nix.overlays.default ];
};
in
{
default = pkgs.stdenv.mkDerivation {
pname = "cellar";
inherit version src;

sourceRoot = ".";

nativeBuildInputs = pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [
pkgs.autoPatchelfHook
pkgs.glibc
pkgs.zlib
];

unpackPhase = ''
tar xzf $src
'';

installPhase = ''
mkdir -p $out/bin
cp cellar $out/bin/cellar
chmod +x $out/bin/cellar
'';

meta = with pkgs.lib; {
description = "Look up the public API of any JVM dependency from the terminal";
homepage = "https://github.com/VirtusLab/cellar";
license = licenses.mpl20;
platforms = [ system ];
mainProgram = "cellar";
};
};

# Install a locally-built binary into the nix profile.
# Usage: ./mill cli.nativeImage && nix profile install --impure .#dev
dev = let
binary = builtins.path {
path = builtins.toPath "${builtins.getEnv "PWD"}/out/cli/nativeImage.dest/native-executable";
name = "cellar-native-executable";
};
in pkgs.stdenv.mkDerivation {
pname = "cellar";
version = "dev";
dontUnpack = true;

installPhase = ''
mkdir -p $out/bin
cp ${binary} $out/bin/cellar
chmod +x $out/bin/cellar
'';

meta = with pkgs.lib; {
description = "Look up the public API of any JVM dependency from the terminal (dev build)";
homepage = "https://github.com/VirtusLab/cellar";
license = licenses.mpl20;
platforms = [ system ];
mainProgram = "cellar";
};
};
default = pkgs.callPackage ./derivation.nix { inherit version; };
}
);

Expand Down
121 changes: 121 additions & 0 deletions scala.lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
{
"dependencies": [
{
"sha256": "OA529lAByYzWLHso5/iZtgkhhRmgKHkqSEviB371KnI=",
"url": "https://repo1.maven.org/maven2/ch/epfl/scala/tasty-query_3/1.7.0/tasty-query_3-1.7.0.jar"
},
{
"sha256": "K8oTN3Jp8zpXW/adfoSvW5EkMVZgYq2EWbvtye1TnTo=",
"url": "https://repo1.maven.org/maven2/co/fs2/fs2-core_3/3.11.0/fs2-core_3-3.11.0.jar"
},
{
"sha256": "iI6009BvNxzxSxwddOiA92nzdK4+M4KZV57WLYQIefk=",
"url": "https://repo1.maven.org/maven2/co/fs2/fs2-io_3/3.11.0/fs2-io_3-3.11.0.jar"
},
{
"sha256": "Cdz2y1DslaqBj+7G7YhRJjHB7cQOjLpA/h924SuXYgw=",
"url": "https://repo1.maven.org/maven2/com/comcast/ip4s-core_3/3.6.0/ip4s-core_3-3.6.0.jar"
},
{
"sha256": "MujJhkU2nQVICqSFSHwQ0zFH6FeHYKhbUgTbGLo/U10=",
"url": "https://repo1.maven.org/maven2/com/github/pureconfig/pureconfig-core_3/0.17.10/pureconfig-core_3-0.17.10.jar"
},
{
"sha256": "moeOOawIhNMK/w692tjlk1Tv92AOgz4v5SNzlm9YEmM=",
"url": "https://repo1.maven.org/maven2/com/monovore/decline-effect_3/2.4.1/decline-effect_3-2.4.1.jar"
},
{
"sha256": "FD3U1rV2G0CVVHHF948zcWS0u21Rlfm1fw4Ruu3TE00=",
"url": "https://repo1.maven.org/maven2/com/monovore/decline_3/2.4.1/decline_3-2.4.1.jar"
},
{
"sha256": "SksK/7IqlXJAnTpr3pnOPyBFxVHK3Byn/glpCJLFJsM=",
"url": "https://repo1.maven.org/maven2/com/typesafe/config/1.4.5/config-1.4.5.jar"
},
{
"sha256": "dZL+SceJtVQpSDGFrCKsbaQ2gKOcU7gYxQvKD7fdang=",
"url": "https://repo1.maven.org/maven2/io/get-coursier/interface/1.0.28/interface-1.0.28.jar"
},
{
"sha256": "daw2bo7LaR4Gp+hQQe7Q9nkZpkblJi+gkBIlaYwQQ3U=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/modules/scala-asm/9.9.0-scala-1/scala-asm-9.9.0-scala-1.jar"
},
{
"sha256": "p9n/OHsFlubmL+YJVEg+Mcu1h1ih7FcWerwsCYKM2gE=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala-library/3.8.1/scala-library-3.8.1.jar"
},
{
"sha256": "4SeOyxKgqhbnZEBURQJ5wlRux7dr27aIisgumm75rHE=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala3-compiler_3/3.8.1/scala3-compiler_3-3.8.1.jar"
},
{
"sha256": "ixyn2NtnhQqam1uDr6DlLPDQ1BuBGMY3oT0z8RHsga8=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala3-interfaces/3.8.1/scala3-interfaces-3.8.1.jar"
},
{
"sha256": "XpruRQyaFYDYYQl0RI6ewVJZJUt3rkUVBhnB4u2PATc=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala3-library_3/3.8.1/scala3-library_3-3.8.1.jar"
},
{
"sha256": "kHC+2OchuPiAJBNKyuWGs0v98gkq8jk016NZn/CF09U=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/scala3-tasty-inspector_3/3.8.1/scala3-tasty-inspector_3-3.8.1.jar"
},
{
"sha256": "OpQLU5cbO5CLt/EgL/pAnQ5cZ8++wD8xqlmS3hK0QL0=",
"url": "https://repo1.maven.org/maven2/org/scala-lang/tasty-core_3/3.8.1/tasty-core_3-3.8.1.jar"
},
{
"sha256": "K6zFdh4DkgoijlydILM9nFHUOq8vUuj4OezmMJZuuIA=",
"url": "https://repo1.maven.org/maven2/org/scala-sbt/compiler-interface/1.10.7/compiler-interface-1.10.7.jar"
},
{
"sha256": "HWuR76QrcPwGTK7W1iliN04Tsnc3+IWofITGZ7ML5iU=",
"url": "https://repo1.maven.org/maven2/org/scala-sbt/util-interface/1.10.7/util-interface-1.10.7.jar"
},
{
"sha256": "mR7vOKAZiT7WXXfY2O8WuF/615ntJ9XwzLVHM3/JbG0=",
"url": "https://repo1.maven.org/maven2/org/scodec/scodec-bits_3/1.1.38/scodec-bits_3-1.1.38.jar"
},
{
"sha256": "0+9XXj5JeWeNwBvx3M5RAhSTtNEft/G+itmCh3wWocA=",
"url": "https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar"
},
{
"sha256": "yFP3SjGdfbZH3LsfHATEt0yaQRZDoYZGXUa2PbA3M8Y=",
"url": "https://repo1.maven.org/maven2/org/typelevel/cats-core_3/2.11.0/cats-core_3-2.11.0.jar"
},
{
"sha256": "NapvXrU5w/opPF6A0GUBEtrDWG6pXZJ/JI7bhImLPdI=",
"url": "https://repo1.maven.org/maven2/org/typelevel/cats-effect-kernel_3/3.5.7/cats-effect-kernel_3-3.5.7.jar"
},
{
"sha256": "xkh/mJURMEmxpuzANedKBbcQ4CWMANFPLZiUq4pdam4=",
"url": "https://repo1.maven.org/maven2/org/typelevel/cats-effect-std_3/3.5.7/cats-effect-std_3-3.5.7.jar"
},
{
"sha256": "nU7cB0rXaOjImdXVoyJ2Xu0xgOsGy8JKCsjWdD8ZTnA=",
"url": "https://repo1.maven.org/maven2/org/typelevel/cats-effect_3/3.5.7/cats-effect_3-3.5.7.jar"
},
{
"sha256": "If5JZ1NaJ1jYAIdpxxsdbJtulDb083YxGV200DSoHiA=",
"url": "https://repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.11.0/cats-kernel_3-2.11.0.jar"
},
{
"sha256": "LLFM1L2XsfcwPH3Fs7j/b6o/vITOLwkWKI0hm42cFA0=",
"url": "https://repo1.maven.org/maven2/org/typelevel/literally_3/1.1.0/literally_3-1.1.0.jar"
},
{
"sha256": "uhx6r5q6Mhe5GUKRH/RQ46QVINvfUKttLqxRPH/zOH8=",
"url": "https://repo1.maven.org/maven2/org/virtuslab/cellar-cli_3/0.1.0-M9/cellar-cli_3-0.1.0-M9.jar"
},
{
"sha256": "+JKcnxZZU7YDKB/TX3nSaisOB/KzhCmst9sXVtIJjU0=",
"url": "https://repo1.maven.org/maven2/org/virtuslab/cellar-lib_3/0.1.0-M9/cellar-lib_3-0.1.0-M9.jar"
}
],
"javaOptions": [
],
"kind": "coursier-app",
"mainClass": "cellar.cli.CellarApp",
"version": 9
}