Skip to content

Commit ba11faf

Browse files
dfa1claude
andauthored
ci: smoke-test published releases on every supported OS/arch (#43)
* ci: smoke-test published releases on every supported OS/arch Add a manually-triggered workflow that pulls a released version from Maven Central and runs a JBang smoke test on one GitHub-hosted runner per native classifier: linux-x86_64 (ubuntu-latest), linux-aarch64 (ubuntu-24.04-arm), osx-x86_64 (macos-13), osx-aarch64 (macos-14), windows-x86_64 (windows-latest), windows-aarch64 (windows-11-arm). The smoke (.github/smoke/Smoke.java) exercises a core compress/decompress round-trip plus a dictionary train + round-trip, so it proves the bundled native library actually loads and works on real hardware for each arch — not a source build (no zig, no submodule), exactly what users consume. Verified locally end-to-end on osx-aarch64 against 0.6 (core 40000 -> 38 bytes, dictionary round-trip passed, zstd 1.5.7). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: default release smoke to the latest Maven Central version Make the version input optional: leave it blank to auto-resolve the latest release from zstd's maven-metadata.xml (<release>), or pass a specific version to override. A resolve job picks the version and feeds it to the matrix. Verified the metadata fetch returns 0.6. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * ci: run the release smoke test weekly Add a Monday 06:00 UTC schedule. Scheduled runs carry no input, so the resolve job auto-picks the latest Maven Central release — catching Central or runner-image drift against the published artifact without a manual run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent bdc7758 commit ba11faf

2 files changed

Lines changed: 138 additions & 0 deletions

File tree

.github/smoke/Smoke.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
///usr/bin/env jbang "$0" "$@" ; exit $?
2+
//JAVA 25
3+
//RUNTIME_OPTIONS --enable-native-access=ALL-UNNAMED
4+
// Dependencies are supplied at run time via `jbang --deps ...` so the workflow
5+
// can pin the released version and the per-arch native jar from the matrix.
6+
7+
import io.github.dfa1.zstd.Zstd;
8+
import io.github.dfa1.zstd.ZstdCompressCtx;
9+
import io.github.dfa1.zstd.ZstdDecompressCtx;
10+
import io.github.dfa1.zstd.ZstdDictionary;
11+
12+
import java.util.ArrayList;
13+
import java.util.Arrays;
14+
import java.util.List;
15+
16+
/// Smoke test for a published zstd-java release: proves the bundled native
17+
/// library loads on the host OS/arch and the core + dictionary paths work.
18+
/// Run against a release from Maven Central, one arch per CI matrix leg.
19+
public class Smoke {
20+
21+
public static void main(String[] args) {
22+
String platform = System.getProperty("os.name") + "/" + System.getProperty("os.arch");
23+
24+
// 1. Core round-trip — proves the native library loaded and compress/decompress work.
25+
byte[] original = "the quick brown fox ".repeat(2000).getBytes();
26+
byte[] compressed = Zstd.compress(original, 9);
27+
byte[] restored = Zstd.decompress(compressed);
28+
if (!Arrays.equals(original, restored)) {
29+
throw new AssertionError("core round-trip mismatch on " + platform);
30+
}
31+
if (compressed.length >= original.length) {
32+
throw new AssertionError("expected compression to shrink the input on " + platform);
33+
}
34+
35+
// 2. Dictionary round-trip — exercises the ZDICT training path (the library's differentiator).
36+
List<byte[]> samples = new ArrayList<>();
37+
for (int i = 0; i < 2000; i++) {
38+
samples.add(("{\"id\":" + i + ",\"user\":\"user_" + (i % 100) + "\",\"event\":\"click\"}").getBytes());
39+
}
40+
ZstdDictionary dict = ZstdDictionary.train(samples, 8 * 1024);
41+
try (ZstdCompressCtx cctx = new ZstdCompressCtx();
42+
ZstdDecompressCtx dctx = new ZstdDecompressCtx()) {
43+
byte[] message = samples.get(7);
44+
byte[] dictCompressed = cctx.compress(message, dict);
45+
byte[] dictRestored = dctx.decompress(dictCompressed, message.length, dict);
46+
if (!Arrays.equals(message, dictRestored)) {
47+
throw new AssertionError("dictionary round-trip mismatch on " + platform);
48+
}
49+
}
50+
51+
System.out.println("OK " + platform
52+
+ " | zstd " + Zstd.version()
53+
+ " | core " + original.length + " -> " + compressed.length + " bytes"
54+
+ " | dictionary round-trip passed");
55+
}
56+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: Release smoke test
2+
3+
# Verifies a PUBLISHED release on Maven Central actually loads and runs on every
4+
# supported OS/arch — one runner per native classifier. Pulls the release jars
5+
# from Central (no source build, no submodule, no zig), so it tests exactly what
6+
# users consume. Trigger manually and pass the version to check.
7+
8+
on:
9+
workflow_dispatch:
10+
inputs:
11+
version:
12+
description: Version to smoke-test. Leave blank to use the latest release on Maven Central.
13+
required: false
14+
default: ""
15+
schedule:
16+
# Weekly, Mondays 06:00 UTC. No input on scheduled runs, so the resolve job
17+
# picks the latest release on Maven Central — catches Central / runner-image
18+
# drift against the published release without a manual trigger.
19+
- cron: "0 6 * * 1"
20+
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
resolve:
26+
name: resolve version
27+
runs-on: ubuntu-latest
28+
outputs:
29+
version: ${{ steps.pick.outputs.version }}
30+
steps:
31+
- name: Resolve version (input, else latest on Maven Central)
32+
id: pick
33+
shell: bash
34+
run: |
35+
version="${{ inputs.version }}"
36+
if [ -z "$version" ]; then
37+
# <release> in maven-metadata.xml is the latest non-snapshot release.
38+
version=$(curl -fsSL https://repo1.maven.org/maven2/io/github/dfa1/zstd/zstd/maven-metadata.xml \
39+
| grep -oE '<release>[^<]+</release>' | sed -E 's/<\/?release>//g')
40+
fi
41+
if [ -z "$version" ]; then
42+
echo "could not resolve a version from Maven Central" >&2
43+
exit 1
44+
fi
45+
echo "Smoke-testing version: $version"
46+
echo "version=$version" >> "$GITHUB_OUTPUT"
47+
48+
smoke:
49+
name: ${{ matrix.classifier }}
50+
needs: resolve
51+
strategy:
52+
fail-fast: false
53+
matrix:
54+
include:
55+
- { os: ubuntu-latest, classifier: linux-x86_64 }
56+
- { os: ubuntu-24.04-arm, classifier: linux-aarch64 }
57+
- { os: macos-13, classifier: osx-x86_64 }
58+
- { os: macos-14, classifier: osx-aarch64 }
59+
- { os: windows-latest, classifier: windows-x86_64 }
60+
- { os: windows-11-arm, classifier: windows-aarch64 }
61+
runs-on: ${{ matrix.os }}
62+
steps:
63+
- name: Checkout (smoke sources only)
64+
uses: actions/checkout@v4
65+
66+
- name: Set up JDK 25
67+
uses: actions/setup-java@v4
68+
with:
69+
distribution: temurin
70+
java-version: '25'
71+
72+
- name: Set up JBang
73+
uses: jbangdev/setup-jbang@main
74+
75+
- name: Smoke-test ${{ needs.resolve.outputs.version }} on ${{ matrix.classifier }}
76+
shell: bash
77+
env:
78+
VERSION: ${{ needs.resolve.outputs.version }}
79+
run: |
80+
jbang --java 25 \
81+
--deps "io.github.dfa1.zstd:zstd:${VERSION},io.github.dfa1.zstd:zstd-native-${{ matrix.classifier }}:${VERSION}" \
82+
.github/smoke/Smoke.java

0 commit comments

Comments
 (0)