Skip to content

Commit 1af5ffc

Browse files
authored
feat: add GitHub Releases with changelog on version tags (#3)
- Add release job to docker workflow: verifies package.json version matches the tag, extracts changelog, creates GitHub Release - Add `latest` Docker tag on version tag pushes - Add CHANGELOG.md with Keep a Changelog format - Add CLAUDE.md documenting dev workflow and release process
1 parent 8a092c2 commit 1af5ffc

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

.github/workflows/docker.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ jobs:
4343
type=ref,event=branch
4444
type=semver,pattern={{version}}
4545
type=semver,pattern={{major}}.{{minor}}
46+
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
4647
type=sha
4748
4849
- name: Build and push
@@ -55,3 +56,46 @@ jobs:
5556
labels: ${{ steps.meta.outputs.labels }}
5657
cache-from: type=gha
5758
cache-to: type=gha,mode=max
59+
60+
release:
61+
if: startsWith(github.ref, 'refs/tags/v')
62+
needs: build
63+
runs-on: ubuntu-latest
64+
permissions:
65+
contents: write
66+
67+
steps:
68+
- uses: actions/checkout@v4
69+
70+
- name: Extract version from tag
71+
id: version
72+
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
73+
74+
- name: Verify package.json version matches tag
75+
run: |
76+
pkg_version=$(node -p "require('./package.json').version")
77+
tag_version="${{ steps.version.outputs.version }}"
78+
if [ "$pkg_version" != "$tag_version" ]; then
79+
echo "::error::package.json version ($pkg_version) does not match tag ($tag_version)"
80+
exit 1
81+
fi
82+
83+
- name: Extract changelog for this version
84+
id: changelog
85+
run: |
86+
version="${{ steps.version.outputs.version }}"
87+
# Extract the section between this version header and the next version header (or EOF)
88+
changelog=$(awk "/^## \[?${version//./\\.}\]?/{found=1; next} /^## \[?[0-9]/{if(found) exit} found{print}" CHANGELOG.md)
89+
if [ -z "$changelog" ]; then
90+
changelog="No changelog entry found for v${version}."
91+
fi
92+
# Write to file to avoid delimiter issues
93+
echo "$changelog" > /tmp/release-notes.md
94+
95+
- name: Create GitHub Release
96+
env:
97+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
98+
run: |
99+
gh release create "${{ github.ref_name }}" \
100+
--title "${{ github.ref_name }}" \
101+
--notes-file /tmp/release-notes.md

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## 0.1.0
9+
10+
### Added
11+
- LNURL-pay service with SSE-based wallet sessions (LUD-06)
12+
- Amountless Lightning receives via reverse swaps
13+
- Reusable sessions: wallet sends a token, server derives a deterministic sessionId via SHA-256
14+
- Session hijack prevention by construction (different tokens always produce different sessionIds)
15+
- Token-based authentication for invoice endpoints
16+
- Multi-arch Docker image (amd64 + arm64) published to GHCR
17+
- Input validation for token (hex, minimum length)
18+
- Comment passthrough to wallet via SSE events

CLAUDE.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# lnurl-server
2+
3+
LNURL-pay service for amountless Lightning receives via Arkade wallet reverse swaps.
4+
5+
## Development
6+
7+
```bash
8+
pnpm dev # start dev server with hot reload
9+
pnpm build # build with tsup
10+
pnpm test # run tests
11+
pnpm type-check # typecheck without emitting
12+
```
13+
14+
## Testing
15+
16+
Tests use vitest with real HTTP servers (no mocks). Each test starts a server on a random port.
17+
18+
## Releasing
19+
20+
Releases are triggered by pushing a semver git tag:
21+
22+
```bash
23+
# 1. Update version in package.json
24+
# 2. Update CHANGELOG.md with the new version's changes
25+
# 3. Commit: "release: v0.2.0"
26+
# 4. Tag and push:
27+
git tag v0.2.0
28+
git push origin main --tags
29+
```
30+
31+
This triggers the CI workflow which:
32+
- Builds and pushes Docker image to `ghcr.io/arklabshq/lnurl-server:{version}` + `latest`
33+
- Creates a GitHub Release with changelog content extracted from CHANGELOG.md
34+
- Verifies that `package.json` version matches the tag
35+
36+
## Changelog
37+
38+
Maintain `CHANGELOG.md` between version bumps. Add entries under an `## Unreleased` section as changes are merged. When cutting a release, rename `Unreleased` to the version number.
39+
40+
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/):
41+
- **Added** for new features
42+
- **Changed** for changes in existing functionality
43+
- **Fixed** for bug fixes
44+
- **Removed** for removed features
45+
46+
## Architecture
47+
48+
- `src/server.ts` — Express app with SSE session endpoints and LNURL-pay protocol
49+
- `src/session-manager.ts` — Session lifecycle, SSE streaming, invoice request/response flow
50+
- `src/types.ts` — Shared TypeScript types
51+
- `src/cli.ts` — CLI entrypoint reading config from env vars

0 commit comments

Comments
 (0)