Skip to content

Commit 8fdecb7

Browse files
authored
Merge pull request #44 from upstat-io/dev
feat(ci): CalVer releases, fix duplicate CI/deploy runs
2 parents 2d34a8e + 3fa236c commit 8fdecb7

4 files changed

Lines changed: 75 additions & 136 deletions

File tree

.github/workflows/auto-release.yml

Lines changed: 38 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
11
name: Auto Release
22

3-
# Automatically bump version, tag, and trigger release on every merge to master.
4-
# During alpha, every PR merge gets its own release (alpha.N → alpha.N+1).
3+
# Automatically tag and release on every merge to master.
4+
# Uses CalVer: v2026.02.27.N-alpha (UTC date + daily build counter).
5+
# No commits to master — just tags the merge commit directly.
56

67
on:
78
push:
89
branches: [master]
910

11+
# Change to "beta" or remove for stable releases.
12+
env:
13+
PRERELEASE_SUFFIX: alpha
14+
1015
# Queue releases — don't cancel in-progress ones.
11-
# Each merge gets its own version bump, processed sequentially.
16+
# Each merge gets its own tag, processed sequentially.
1217
concurrency:
1318
group: auto-release
1419
cancel-in-progress: false
1520

1621
jobs:
1722
auto-release:
18-
name: Bump Version & Tag
23+
name: Tag & Release
1924
runs-on: ubuntu-latest
20-
timeout-minutes: 10
21-
22-
# Skip release commits to prevent infinite loop.
23-
# The version bump commit starts with "chore: release v".
24-
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
25+
timeout-minutes: 5
2526

2627
steps:
2728
- name: Checkout
@@ -31,58 +32,39 @@ jobs:
3132
fetch-depth: 0
3233
ref: master
3334

34-
- name: Configure git
35+
- name: Derive release tag
36+
id: tag
3537
run: |
36-
git config user.name "github-actions[bot]"
37-
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
38-
39-
- name: Install Rust
40-
uses: dtolnay/rust-toolchain@stable
38+
TODAY=$(date -u +"%Y.%m.%d")
39+
COUNT=1
40+
while git rev-parse "refs/tags/v${TODAY}.${COUNT}-${PRERELEASE_SUFFIX}" &>/dev/null; do
41+
COUNT=$((COUNT + 1))
42+
done
43+
TAG="v${TODAY}.${COUNT}-${PRERELEASE_SUFFIX}"
44+
echo "tag=$TAG" >> $GITHUB_OUTPUT
45+
echo "Release tag: $TAG"
4146
42-
- name: Determine version
43-
id: version
47+
- name: Push tag
4448
run: |
45-
CURRENT=$(grep -E '^version\s*=' Cargo.toml | head -1 | sed 's/.*=\s*"\([^"]*\)".*/\1/')
46-
echo "current=$CURRENT" >> $GITHUB_OUTPUT
47-
48-
if git rev-parse "refs/tags/v$CURRENT" &>/dev/null; then
49-
# Tag exists — auto-increment
50-
echo "Tag v$CURRENT already exists, auto-incrementing..."
51-
echo "bumped=true" >> $GITHUB_OUTPUT
52-
else
53-
# Tag doesn't exist — version was set manually in a PR, or first release
54-
echo "Tag v$CURRENT does not exist, using current version as-is"
55-
echo "bumped=false" >> $GITHUB_OUTPUT
56-
echo "new_version=$CURRENT" >> $GITHUB_OUTPUT
57-
fi
49+
git tag "${{ steps.tag.outputs.tag }}"
50+
git push origin "${{ steps.tag.outputs.tag }}"
5851
59-
- name: Bump version
60-
if: steps.version.outputs.bumped == 'true'
61-
run: ./scripts/release.sh --yes
62-
63-
- name: Read new version
64-
id: new_version
52+
- name: Create release with notes
53+
env:
54+
GH_TOKEN: ${{ secrets.ORILANG_RELEASE_TOKEN }}
6555
run: |
66-
VERSION=$(grep -E '^version\s*=' Cargo.toml | head -1 | sed 's/.*=\s*"\([^"]*\)".*/\1/')
67-
echo "version=$VERSION" >> $GITHUB_OUTPUT
68-
echo "New version: $VERSION"
56+
TAG="${{ steps.tag.outputs.tag }}"
6957
70-
- name: Regenerate lockfiles
71-
if: steps.version.outputs.bumped == 'true'
72-
run: |
73-
cargo generate-lockfile
74-
cargo generate-lockfile --manifest-path compiler/ori_llvm/Cargo.toml
75-
cargo generate-lockfile --manifest-path compiler/ori_rt/Cargo.toml
76-
cargo generate-lockfile --manifest-path tools/ori-lsp/Cargo.toml
77-
cargo generate-lockfile --manifest-path website/playground-wasm/Cargo.toml
58+
# Find previous tag for release notes range
59+
PREV_TAG=$(git tag --sort=-creatordate | grep '^v' | sed -n '2p')
7860
79-
- name: Commit version bump
80-
if: steps.version.outputs.bumped == 'true'
81-
run: |
82-
git add -A
83-
git commit -m "chore: release v${{ steps.new_version.outputs.version }}"
61+
NOTES_ARGS=""
62+
if [[ -n "$PREV_TAG" ]]; then
63+
NOTES_ARGS="--notes-start-tag $PREV_TAG"
64+
fi
8465
85-
- name: Tag and push
86-
run: |
87-
git tag "v${{ steps.new_version.outputs.version }}"
88-
git push origin master --tags
66+
gh release create "$TAG" \
67+
--title "Ori ${TAG#v}" \
68+
--generate-notes \
69+
$NOTES_ARGS \
70+
--prerelease

.github/workflows/ci.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919
# Fast checks - run first, fail fast
2020
version-check:
2121
name: Version Sync
22+
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
2223
runs-on: ubuntu-latest
2324
timeout-minutes: 5
2425
steps:
@@ -28,6 +29,7 @@ jobs:
2829

2930
format:
3031
name: Format
32+
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
3133
runs-on: ubuntu-latest
3234
timeout-minutes: 5
3335
steps:
@@ -40,6 +42,7 @@ jobs:
4042

4143
clippy:
4244
name: Clippy
45+
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
4346
runs-on: ubuntu-latest
4447
timeout-minutes: 15
4548
steps:
@@ -55,6 +58,7 @@ jobs:
5558
# Main test suite
5659
test:
5760
name: Test
61+
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
5862
runs-on: ubuntu-latest
5963
timeout-minutes: 30
6064
steps:
@@ -182,6 +186,7 @@ jobs:
182186
# TODO: Make this blocking once LLVM backend is stable
183187
llvm:
184188
name: LLVM Backend
189+
if: "!startsWith(github.event.head_commit.message, 'chore: release v')"
185190
runs-on: ubuntu-latest
186191
timeout-minutes: 60
187192
continue-on-error: true # Non-blocking during pre-alpha
@@ -246,7 +251,7 @@ jobs:
246251
name: CI Success
247252
needs: [version-check, format, clippy, test, cross-platform]
248253
runs-on: ubuntu-latest
249-
if: always()
254+
if: "always() && !startsWith(github.event.head_commit.message, 'chore: release v')"
250255
steps:
251256
- name: Check all jobs passed
252257
run: |

.github/workflows/deploy-website.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ on:
66
workflows: ["CI"]
77
types: [completed]
88
branches: [master]
9+
# Deploy directly on release commits (CI is skipped for these, but website needs version update)
10+
push:
11+
branches: [master]
912
workflow_dispatch:
1013

1114
permissions:
@@ -20,6 +23,13 @@ concurrency:
2023

2124
jobs:
2225
build:
26+
# push: only for release commits (CI is skipped, but website needs the version)
27+
# workflow_run: only when CI succeeded (not when skipped for release commits)
28+
# workflow_dispatch: always
29+
if: >-
30+
(github.event_name == 'push' && startsWith(github.event.head_commit.message, 'chore: release v')) ||
31+
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
32+
github.event_name == 'workflow_dispatch'
2333
runs-on: ubuntu-latest
2434
steps:
2535
- name: Checkout

.github/workflows/release.yml

Lines changed: 21 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -36,34 +36,6 @@ jobs:
3636
fi
3737
echo "Tag is on master branch - OK"
3838
39-
- name: Extract expected version from tag
40-
id: tag_version
41-
run: |
42-
# Remove 'v' prefix from tag
43-
TAG_VERSION="${GITHUB_REF_NAME#v}"
44-
echo "tag_version=$TAG_VERSION" >> $GITHUB_OUTPUT
45-
echo "Tag version: $TAG_VERSION"
46-
47-
- name: Extract Cargo.toml version
48-
id: cargo_version
49-
run: |
50-
CARGO_VERSION=$(grep -E '^version\s*=' Cargo.toml | head -1 | sed 's/.*=\s*"\([^"]*\)".*/\1/')
51-
echo "cargo_version=$CARGO_VERSION" >> $GITHUB_OUTPUT
52-
echo "Cargo.toml version: $CARGO_VERSION"
53-
54-
- name: Validate tag matches Cargo.toml
55-
run: |
56-
if [[ "${{ steps.tag_version.outputs.tag_version }}" != "${{ steps.cargo_version.outputs.cargo_version }}" ]]; then
57-
echo "ERROR: Tag version (${{ steps.tag_version.outputs.tag_version }}) does not match Cargo.toml version (${{ steps.cargo_version.outputs.cargo_version }})"
58-
echo ""
59-
echo "To fix:"
60-
echo " 1. Delete the tag: git tag -d ${{ github.ref_name }} && git push origin :refs/tags/${{ github.ref_name }}"
61-
echo " 2. Update versions: ./scripts/release.sh ${{ steps.tag_version.outputs.tag_version }}"
62-
echo " 3. Commit, tag, and push again"
63-
exit 1
64-
fi
65-
echo "Version validation passed!"
66-
6739
- name: Check version synchronization
6840
run: ./scripts/sync-version.sh --check
6941

@@ -90,8 +62,16 @@ jobs:
9062
with:
9163
fetch-depth: 0
9264

93-
- name: Derive build number
94-
run: ./scripts/bump-build.sh
65+
- name: Derive build number from tag
66+
run: |
67+
# Extract CalVer build number from tag: v2026.02.27.2-alpha → 2026.02.27.2
68+
BUILD=$(echo "${GITHUB_REF_NAME}" | grep -oE '[0-9]{4}\.[0-9]{2}\.[0-9]{2}\.[0-9]+')
69+
if [[ -n "$BUILD" ]]; then
70+
echo "$BUILD" > BUILD_NUMBER
71+
else
72+
./scripts/bump-build.sh # Fallback for semver tags
73+
fi
74+
echo "Build number: $(cat BUILD_NUMBER)"
9575
9676
- name: Set up Docker Buildx
9777
uses: docker/setup-buildx-action@v3
@@ -149,8 +129,16 @@ jobs:
149129
with:
150130
fetch-depth: 0
151131

152-
- name: Derive build number
153-
run: ./scripts/bump-build.sh
132+
- name: Derive build number from tag
133+
run: |
134+
# Extract CalVer build number from tag: v2026.02.27.2-alpha → 2026.02.27.2
135+
BUILD=$(echo "${GITHUB_REF_NAME}" | grep -oE '[0-9]{4}\.[0-9]{2}\.[0-9]{2}\.[0-9]+')
136+
if [[ -n "$BUILD" ]]; then
137+
echo "$BUILD" > BUILD_NUMBER
138+
else
139+
./scripts/bump-build.sh # Fallback for semver tags
140+
fi
141+
echo "Build number: $(cat BUILD_NUMBER)"
154142
155143
- name: Install LLVM
156144
run: |
@@ -302,58 +290,12 @@ jobs:
302290
echo "This is a stable release"
303291
fi
304292
305-
- name: Generate release body
306-
run: |
307-
VERSION="${GITHUB_REF_NAME#v}"
308-
if [[ "$VERSION" == *"alpha"* ]]; then
309-
cat << 'BODY' > release_body.md
310-
## ⚠️ Nightly Release
311-
312-
This is an **alpha/nightly** build intended for testing and development.
313-
It may contain bugs and breaking changes.
314-
315-
### Installation
316-
317-
**Quick install (Linux/macOS):**
318-
```bash
319-
curl -fsSL https://ori-lang.com/install.sh | sh
320-
```
321-
322-
**Manual download:** See assets below for your platform.
323-
324-
### What's New
325-
326-
See the auto-generated changelog below for details.
327-
328-
---
329-
BODY
330-
else
331-
cat << 'BODY' > release_body.md
332-
## Installation
333-
334-
**Quick install (Linux/macOS):**
335-
```bash
336-
curl -fsSL https://ori-lang.com/install.sh | sh
337-
```
338-
339-
**Manual download:** See assets below for your platform.
340-
341-
### What's New
342-
343-
See the auto-generated changelog below for details.
344-
345-
---
346-
BODY
347-
fi
348-
349-
- name: Create Release
293+
- name: Upload artifacts to release
350294
uses: softprops/action-gh-release@v2
351295
with:
352296
name: ${{ steps.release_type.outputs.name }}
353-
body_path: release_body.md
354297
files: |
355298
artifacts/*
356-
generate_release_notes: true
357299
prerelease: ${{ steps.release_type.outputs.prerelease }}
358300
make_latest: ${{ steps.release_type.outputs.prerelease != 'true' }}
359301
env:

0 commit comments

Comments
 (0)