Skip to content

Commit 4708306

Browse files
authored
release with koalabear fields
feat: Add semantic versioning and proper export of koalabear fields (#3)
2 parents 1d909de + a21f7d5 commit 4708306

File tree

8 files changed

+249
-17
lines changed

8 files changed

+249
-17
lines changed

.github/workflows/auto-release.yml

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
name: Auto Release on Release Branch
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
branches:
7+
- release
8+
9+
permissions:
10+
contents: write
11+
12+
jobs:
13+
auto-release:
14+
# Only run if PR was merged to release branch (not just closed)
15+
if: github.event.pull_request.merged == true
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v4
21+
with:
22+
fetch-depth: 0 # Fetch all history for versioning
23+
24+
- name: Setup Zig
25+
uses: goto-bus-stop/setup-zig@v2
26+
with:
27+
version: 0.14.1
28+
29+
- name: Read VERSION file
30+
id: get_version
31+
run: |
32+
VERSION=$(cat VERSION)
33+
echo "version=$VERSION" >> $GITHUB_OUTPUT
34+
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
35+
36+
- name: Check if tag exists
37+
id: check_tag
38+
run: |
39+
if git rev-parse "v${{ steps.get_version.outputs.version }}" >/dev/null 2>&1; then
40+
echo "exists=true" >> $GITHUB_OUTPUT
41+
echo "⚠️ Tag v${{ steps.get_version.outputs.version }} already exists"
42+
else
43+
echo "exists=false" >> $GITHUB_OUTPUT
44+
echo "✅ Tag v${{ steps.get_version.outputs.version }} does not exist"
45+
fi
46+
47+
- name: Run tests
48+
if: steps.check_tag.outputs.exists == 'false'
49+
run: zig build test
50+
51+
- name: Build library
52+
if: steps.check_tag.outputs.exists == 'false'
53+
run: zig build
54+
55+
- name: Update build.zig.zon version
56+
if: steps.check_tag.outputs.exists == 'false'
57+
run: |
58+
VERSION="${{ steps.get_version.outputs.version }}"
59+
sed -i "s/\.version = \".*\"/\.version = \"$VERSION\"/" build.zig.zon
60+
61+
- name: Generate changelog
62+
if: steps.check_tag.outputs.exists == 'false'
63+
id: changelog
64+
run: |
65+
VERSION="${{ steps.get_version.outputs.version }}"
66+
67+
# Get previous tag
68+
PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
69+
70+
if [ -z "$PREV_TAG" ]; then
71+
echo "## 🎉 Initial Release" > CHANGELOG.md
72+
echo "" >> CHANGELOG.md
73+
echo "First release of zig-poseidon - A Zig implementation of Poseidon2 hash function." >> CHANGELOG.md
74+
echo "" >> CHANGELOG.md
75+
echo "### Features" >> CHANGELOG.md
76+
echo "- BabyBear field (p = 2³¹ - 2²⁷ + 1) for Ethereum Lean chain" >> CHANGELOG.md
77+
echo "- KoalaBear field (p = 2³¹ - 2²⁴ + 1) for plonky3 and Rust hash-sig compatibility" >> CHANGELOG.md
78+
echo "- Generic Montgomery form implementation" >> CHANGELOG.md
79+
echo "- Compression mode for Merkle Trees" >> CHANGELOG.md
80+
echo "- Comprehensive test suite" >> CHANGELOG.md
81+
else
82+
echo "## Changes since $PREV_TAG" > CHANGELOG.md
83+
echo "" >> CHANGELOG.md
84+
git log "$PREV_TAG"..HEAD --pretty=format:"- %s (%h)" >> CHANGELOG.md
85+
fi
86+
87+
cat CHANGELOG.md
88+
89+
- name: Create Git tag
90+
if: steps.check_tag.outputs.exists == 'false'
91+
run: |
92+
git config user.name "github-actions[bot]"
93+
git config user.email "github-actions[bot]@users.noreply.github.com"
94+
git tag -a "${{ steps.get_version.outputs.tag }}" -m "Release ${{ steps.get_version.outputs.tag }}"
95+
git push origin "${{ steps.get_version.outputs.tag }}"
96+
97+
- name: Create GitHub Release
98+
if: steps.check_tag.outputs.exists == 'false'
99+
uses: softprops/action-gh-release@v1
100+
with:
101+
tag_name: ${{ steps.get_version.outputs.tag }}
102+
name: Release ${{ steps.get_version.outputs.tag }}
103+
body_path: CHANGELOG.md
104+
draft: false
105+
prerelease: false
106+
env:
107+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
108+
109+
- name: Calculate tarball hash
110+
if: steps.check_tag.outputs.exists == 'false'
111+
id: tarball_hash
112+
run: |
113+
VERSION="${{ steps.get_version.outputs.version }}"
114+
TARBALL_URL="https://github.com/${{ github.repository }}/archive/v${VERSION}.tar.gz"
115+
116+
# Download and calculate hash
117+
curl -L "$TARBALL_URL" -o release.tar.gz
118+
HASH=$(zig fetch release.tar.gz 2>&1 | grep -o '12[0-9a-f]*' || echo "")
119+
120+
if [ -z "$HASH" ]; then
121+
echo "⚠️ Could not calculate hash automatically"
122+
echo "📦 Users can get the hash by running:"
123+
echo " zig fetch --save $TARBALL_URL"
124+
else
125+
echo "hash=$HASH" >> $GITHUB_OUTPUT
126+
echo "📦 Tarball hash: $HASH"
127+
fi
128+
129+
- name: Post release information
130+
if: steps.check_tag.outputs.exists == 'false'
131+
run: |
132+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
133+
echo "🎉 Release ${{ steps.get_version.outputs.tag }} created successfully!"
134+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
135+
echo ""
136+
echo "📦 To use this release in your project's build.zig.zon:"
137+
echo ""
138+
echo ".dependencies = .{"
139+
echo " .poseidon = .{"
140+
echo " .url = \"https://github.com/${{ github.repository }}/archive/${{ steps.get_version.outputs.tag }}.tar.gz\","
141+
echo " .hash = \"${{ steps.tarball_hash.outputs.hash }}\","
142+
echo " },"
143+
echo "},"
144+
echo ""
145+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
146+
147+
- name: Skip release (tag exists)
148+
if: steps.check_tag.outputs.exists == 'true'
149+
run: |
150+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
151+
echo "⚠️ Skipping release - tag ${{ steps.get_version.outputs.tag }} already exists"
152+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
153+
echo ""
154+
echo "To create a new release:"
155+
echo "1. Update the VERSION file with a new version number"
156+
echo "2. Commit the change"
157+
echo "3. Create and merge a PR"
158+
echo ""
159+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
160+

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
zig-version: 0.14.0
3232

3333
- name: Lint
34-
run: zig fmt --check src/*.zig
34+
run: zig fmt --check src/
3535

3636
test:
3737
runs-on: ubuntu-latest

README.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ Add `zig-poseidon` as a dependency in your `build.zig.zon`:
3636
```zig
3737
.dependencies = .{
3838
.poseidon = .{
39-
.url = "https://github.com/jsign/zig-poseidon/archive/<commit-hash>.tar.gz",
40-
.hash = "<hash>",
39+
.url = "https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz",
40+
.hash = "122...", // Get hash by running: zig fetch --save <url>
4141
},
4242
},
4343
```
4444

45+
**Get the correct hash:**
46+
```bash
47+
zig fetch --save https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz
48+
```
49+
50+
**Latest version:** See [Releases](https://github.com/blockblaz/zig-poseidon/releases) for the most recent version.
51+
4552
## Usage
4653

4754
### Using BabyBear16
@@ -150,6 +157,45 @@ Both implementations include tests ensuring the naive and optimized (Montgomery)
150157
- Add benchmarks and performance optimizations
151158
- Add more S-Box degrees as needed
152159

160+
## Versioning and Releases
161+
162+
This project follows [Semantic Versioning](https://semver.org/).
163+
164+
**Current version:** `0.2.0`
165+
166+
### Release Process
167+
168+
Releases are automatically created when Pull Requests from `main` are merged to the `release` branch:
169+
170+
1. Develop and merge features to `main` branch
171+
2. When ready to release, update the `VERSION` file on `main`
172+
3. Create a PR from `main` to `release` branch
173+
4. After merge to `release`, the workflow automatically:
174+
- Creates a Git tag (e.g., `v0.2.0`)
175+
- Generates a changelog
176+
- Creates a GitHub Release
177+
- Calculates the tarball hash for dependencies
178+
179+
**Why a release branch?**
180+
- ✅ Control when releases happen
181+
- ✅ Not every feature triggers a release
182+
- ✅ Batch multiple features into one release
183+
184+
See [RELEASING.md](RELEASING.md) for detailed release instructions.
185+
186+
### Using Specific Versions
187+
188+
Always pin to a specific version in your `build.zig.zon`:
189+
190+
```zig
191+
.poseidon = .{
192+
.url = "https://github.com/blockblaz/zig-poseidon/archive/v0.2.0.tar.gz",
193+
.hash = "122...", // specific hash for v0.2.0
194+
},
195+
```
196+
197+
**Find releases:** [GitHub Releases](https://github.com/blockblaz/zig-poseidon/releases)
198+
153199
## License
154200

155201
MIT

VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
0.2.0
2+

build.zig

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,11 @@ pub fn build(b: *std.Build) void {
44
const target = b.standardTargetOptions(.{});
55
const optimize = b.standardOptimizeOption(.{});
66

7-
// Generic Poseidon2 module
8-
_ = b.addModule("poseidon2", .{
9-
.root_source_file = b.path("src/poseidon2/poseidon2.zig"),
10-
});
11-
12-
// BabyBear16 instance
13-
_ = b.addModule("babybear16", .{
14-
.root_source_file = b.path("src/instances/babybear16.zig"),
15-
});
16-
17-
// KoalaBear16 instance (compatible with Rust hash-sig)
18-
_ = b.addModule("koalabear16", .{
19-
.root_source_file = b.path("src/instances/koalabear16.zig"),
7+
// Main module - exports everything
8+
_ = b.addModule("poseidon", .{
9+
.root_source_file = b.path("src/root.zig"),
10+
.target = target,
11+
.optimize = optimize,
2012
});
2113

2214
const lib = b.addStaticLibrary(.{

build.zig.zon

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.{
2+
.name = .zig_poseidon,
3+
.version = "0.2.0",
4+
.fingerprint = 0x4cb45c65d8967708,
5+
.minimum_zig_version = "0.14.0",
6+
7+
.dependencies = .{},
8+
9+
.paths = .{
10+
"build.zig",
11+
"build.zig.zon",
12+
"src",
13+
"README.md",
14+
"LICENSE",
15+
"VERSION",
16+
},
17+
}
18+

src/instances/koalabear16.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const DIAGONAL = [WIDTH]u32{
2929
parseHex("7fffff7f"), // -1/2^24
3030
};
3131

32-
const Poseidon2KoalaBear = poseidon2.Poseidon2(
32+
pub const Poseidon2KoalaBear = poseidon2.Poseidon2(
3333
koalabear,
3434
WIDTH,
3535
INTERNAL_ROUNDS,

src/root.zig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Root module for zig-poseidon
2+
// Re-exports all components
3+
4+
pub const babybear16 = @import("instances/babybear16.zig");
5+
pub const koalabear16 = @import("instances/koalabear16.zig");
6+
pub const poseidon2 = @import("poseidon2/poseidon2.zig");
7+
8+
// Convenience type exports
9+
pub const Poseidon2BabyBear = babybear16.Poseidon2BabyBear;
10+
pub const Poseidon2KoalaBear = koalabear16.Poseidon2KoalaBear;
11+
12+
test {
13+
@import("std").testing.refAllDecls(@This());
14+
}

0 commit comments

Comments
 (0)