Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
5e3c574
chore(ci):add automated dated release workflow
Andes-indica Aug 18, 2026
282c579
updated docs
Andes-indica Aug 18, 2026
941706e
chore(ci): fix release workflow f-string and update docs
Andes-indica Aug 18, 2026
10892c7
ci: add workflow_dispatch to auto-release for manual testing
Andes-indica Aug 18, 2026
2b95956
ci: fix release step GITHUB_TOKEN and use
Andes-indica Aug 18, 2026
97095c0
ci: pin actions/checkout to full commit SHA
Andes-indica Aug 18, 2026
1f4024b
ci: auto-release - migrate notes to Bun TS, fix lint/format; adjust w…
Andes-indica Aug 19, 2026
877f28c
ci(workflows): pin oven-sh/setup-bun v2 to commit SHA in auto-release…
Andes-indica Aug 19, 2026
a1a0719
ci:resolved since-declaration causing the test error
Andes-indica Aug 20, 2026
337fb92
ci:resolved tag format error
Andes-indica Aug 20, 2026
b8f6fc3
ci:fix release retry boundary and orphan tag handling
Andes-indica Aug 21, 2026
fa29954
fix release retry and orphan tag recovery
Andes-indica Aug 21, 2026
7ecc729
Merge branch 'Noveum:main' into ci/auto-release-workflow
Andes-indica Aug 23, 2026
7585b19
ci:fix automated release workflow contract
Andes-indica Aug 24, 2026
2517e9f
Merge branch 'Noveum:main' into ci/auto-release-workflow
Andes-indica Aug 24, 2026
9cb3df4
fix release workflow orphan recovery
Andes-indica Aug 24, 2026
a3021d3
fix automated release workflow wiring
Andes-indica Aug 25, 2026
6d9ca76
docs: align automated release guidance
imshashank Aug 25, 2026
1da4666
fix(ci): recover prior dated release tags
imshashank Aug 25, 2026
c4c6d60
fix(ci): recover historical dated releases
imshashank Aug 25, 2026
1e0fa1e
fix(ci): avoid overlapping recovery notes
imshashank Aug 25, 2026
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
145 changes: 145 additions & 0 deletions .github/workflows/auto-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Automated Releases

on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:
concurrency:
group: automated-release
cancel-in-progress: true
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

permissions:
contents: write
pull-requests: read

jobs:
tag-and-release:
name: Create dated tag and release notes
runs-on: ubuntu-latest
steps:
- name: Checkout
Comment thread
Andes-indica marked this conversation as resolved.
Outdated
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262
with:
fetch-depth: 0
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Determine last tag and since
id: since
run: |
set -euo pipefail
# Try to find the latest tag on origin
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
git fetch --tags origin
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || true)
if [ -n "$LAST_TAG" ]; then
SINCE_DATE=$(git log -1 --format=%aI "$LAST_TAG")
echo "Found last tag: $LAST_TAG (since $SINCE_DATE)"
else
# Fallback to 7 days ago
SINCE_DATE=$(date -u -d '7 days ago' --iso-8601=seconds)
echo "No tag found, using fallback since: $SINCE_DATE"
fi
echo "last_tag=$LAST_TAG" >> "$GITHUB_OUTPUT"
echo "since_date=$SINCE_DATE" >> "$GITHUB_OUTPUT"
Comment thread
Andes-indica marked this conversation as resolved.
Outdated

- name: Build release notes (Python)
id: build_notes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Comment thread
greptile-apps[bot] marked this conversation as resolved.
run: |
python3 - <<'PY'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
import os, sys, json, urllib.request, datetime
repo = os.environ['GITHUB_REPOSITORY']
since = os.environ.get('INPUT_SINCE') or os.environ.get('since_date') or os.environ.get('GITHUB_SINCE')
if not since:
since = (datetime.datetime.utcnow() - datetime.timedelta(days=7)).isoformat() + 'Z'
owner, repo_name = repo.split('/')
token = os.environ.get('GITHUB_TOKEN')
hdr = {'User-Agent': 'orbit-release-bot', 'Accept': 'application/vnd.github+json'}
if token:
hdr['Authorization'] = f'token {token}'
prs = []
page = 1
while True:
url = f'https://api.github.com/repos/{owner}/{repo_name}/pulls?state=closed&per_page=100&page={page}'
req = urllib.request.Request(url, headers=hdr)
with urllib.request.urlopen(req) as resp:
data = json.load(resp)
if not data:
break
prs.extend(data)
if len(data) < 100:
break
page += 1

since_dt = datetime.datetime.fromisoformat(since.replace('Z','+00:00'))
merged = [p for p in prs if p.get('merged_at')]
merged = [p for p in merged if datetime.datetime.fromisoformat(p['merged_at'].replace('Z','+00:00')) >= since_dt]

areas = {}
breaking = []
for p in merged:
labels = [l['name'] for l in p.get('labels',[])]
if 'breaking change' in labels:
breaking.append(p)
continue
area = next((l for l in labels if l.startswith('area:')), 'Other')
areas.setdefault(area, []).append(p)

body = f"Automated release for {os.environ.get('GITHUB_SHA','')}\\n"
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated
if breaking:
body += '## Breaking changes\n'
for pr in breaking:
body += f"- {pr['title']} (#{pr['number']} {pr['html_url']})\n"
if pr.get('body'):
body += '\n ' + '\n '.join(pr['body'].splitlines()[:6]) + '\n'
body += '\n'

for area, prs_list in areas.items():
title = area.replace('area:', 'Area: ')
body += f"## {title}\n"
for pr in prs_list:
body += f"- {pr['title']} (#{pr['number']} {pr['html_url']})\n"
body += '\n'

if not breaking and not areas:
body += 'No merged pull requests found since the last tag.\n'

with open('RELEASE_NOTES.md','w') as f:
f.write(body)
print('WROTE RELEASE_NOTES.md')
# write output using the environment file instead of deprecated set-output
# the step runner will append this to $GITHUB_OUTPUT
PY
echo "notes_path=RELEASE_NOTES.md" >> "$GITHUB_OUTPUT"
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated

- name: Create dated tag
Comment thread
Andes-indica marked this conversation as resolved.
Outdated
id: create_tag
run: |
set -euo pipefail
BASE_TAG=$(date -u +%Y.%m.%d)
TAG="$BASE_TAG"
COUNT=0
while git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; do
COUNT=$((COUNT+1))
TAG="$BASE_TAG-$COUNT"
done
echo "Tag will be: $TAG"
git tag -a "$TAG" -m "Automated release $TAG" $GITHUB_SHA
git push origin "$TAG"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"

- name: Create GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
TAG=${{ steps.create_tag.outputs.tag }}
NOTES=$(cat RELEASE_NOTES.md || echo "No release notes available")
data=$(jq -n --arg tag "$TAG" --arg name "$TAG" --arg body "$NOTES" '{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:false}')
curl -sS -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github+json" https://api.github.com/repos/${GITHUB_REPOSITORY}/releases -d "$data"
Comment thread
Andes-indica marked this conversation as resolved.
Outdated
7 changes: 4 additions & 3 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ enforced.
## Releases

Orbit ships continuously from `main`. There are no long lived release branches
and no backporting, so self-hosted deployments should track `main` or a recent
tag.
and no backporting. To make deployments traceable we publish automated dated
tags and GitHub releases (weekly and on merges to `main`), so self-hosted
deployments can track `main` or a recent dated tag.

Anything requiring action from someone self-hosting is labelled
[`breaking change`](https://github.com/Noveum/orbit/labels/breaking%20change)
and called out in the release notes.
and called out prominently in the generated release notes.
7 changes: 4 additions & 3 deletions docs/self-hosting.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,11 +261,12 @@ bun run build
Always complete the database release before the code that depends on it goes live.
The production Vercel build refuses to deploy when the configured database cannot
be verified or is missing a required schema object. Additional legacy tables and
indexes are reported and preserved. Orbit ships continuously from `main` and there
is no backporting, so track `main` or a recent tag.
indexes are reported and preserved. Orbit ships continuously from `main`. We
also publish automated dated tags and GitHub releases (weekly and on merges to
`main`) so you can track `main` or a recent dated tag for deployed versions.

Watch the [releases](https://github.com/Noveum/orbit/releases) for anything
labelled `breaking change`.
labelled `breaking change` and follow the upgrade notes in the associated release.
Comment thread
Andes-indica marked this conversation as resolved.

### Backups

Expand Down
Loading