Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 96 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,102 @@
# Changelog


## v1.1.1

[compare changes](https://github.com/Alex1990/tiny-oss/compare/v1.1.0...v1.1.1)

### 🚀 Enhancements

- Add Volcano Engine TOS provider entry ([d15d021](https://github.com/Alex1990/tiny-oss/commit/d15d021))

### 🩹 Fixes

- Include CHANGELOG.md in the release commit ([5646c15](https://github.com/Alex1990/tiny-oss/commit/5646c15))

### 📖 Documentation

- Document the release flow for future maintainers ([31c17cb](https://github.com/Alex1990/tiny-oss/commit/31c17cb))
- Replace supported providers list with a table of contents ([e4ab41f](https://github.com/Alex1990/tiny-oss/commit/e4ab41f))
- Adopt loop norms (AGENTS.md, docs/agents, skills) ([e3c4cd6](https://github.com/Alex1990/tiny-oss/commit/e3c4cd6))
- Translate scripts/loop/README.md to English ([477d138](https://github.com/Alex1990/tiny-oss/commit/477d138))
- Extend needs-info close window from 7 to 30 days ([151d561](https://github.com/Alex1990/tiny-oss/commit/151d561))
- **loop:** Flag an acceptance double-counting hazard (D32) ([807bf52](https://github.com/Alex1990/tiny-oss/commit/807bf52))
- **loop:** Record the live PR-resynchronisation skip (D26) ([fd43cda](https://github.com/Alex1990/tiny-oss/commit/fd43cda))
- **loop:** Note the unattributed-approval ruleset default ([65071c3](https://github.com/Alex1990/tiny-oss/commit/65071c3))
- **loop:** Approving a loop PR's runs one at a time is the better default ([9929d03](https://github.com/Alex1990/tiny-oss/commit/9929d03))
- Add conventional status badges to the READMEs ([35c7312](https://github.com/Alex1990/tiny-oss/commit/35c7312))

### 🏡 Chore

- Add local loop host for manual A0 trials ([da28a14](https://github.com/Alex1990/tiny-oss/commit/da28a14))
- Support claiming reopened GitHub issues (D9) ([f236b76](https://github.com/Alex1990/tiny-oss/commit/f236b76))
- **loop:** Add Actions + R2 host for stage A1 (report-only) ([ec85a18](https://github.com/Alex1990/tiny-oss/commit/ec85a18))
- **loop:** Repair workflow contexts that broke parsing ([da75c9c](https://github.com/Alex1990/tiny-oss/commit/da75c9c))
- **loop:** Keep credential failures out of the human inbox, log outcomes ([ede64a0](https://github.com/Alex1990/tiny-oss/commit/ede64a0))
- **loop:** Target the right gh subcommand, import PRs locally ([51661b9](https://github.com/Alex1990/tiny-oss/commit/51661b9))
- **loop:** Shrink R2 configuration to three secrets ([ddbeb9a](https://github.com/Alex1990/tiny-oss/commit/ddbeb9a))
- **loop:** Derive one R2 bucket per repository ([d71b6f6](https://github.com/Alex1990/tiny-oss/commit/d71b6f6))
- **loop:** Include the owner in the derived bucket name ([35d0fd3](https://github.com/Alex1990/tiny-oss/commit/35d0fd3))
- **loop:** Let workflow_dispatch check out its own ref ([64ead08](https://github.com/Alex1990/tiny-oss/commit/64ead08))
- **loop:** Correct the model id, validate it, add an infrastructure smoke ([d6d526a](https://github.com/Alex1990/tiny-oss/commit/d6d526a))
- **loop:** Render system-level runs correctly in SUMMARY ([faf6d09](https://github.com/Alex1990/tiny-oss/commit/faf6d09))
- **loop:** No pager, bounded timeouts, and a readable smoke ([2a7797e](https://github.com/Alex1990/tiny-oss/commit/2a7797e))
- **loop:** Give system-level runs their own outcome vocabulary ([1611f76](https://github.com/Alex1990/tiny-oss/commit/1611f76))
- **loop:** Record A1 acceptance progress with run evidence ([1ab3354](https://github.com/Alex1990/tiny-oss/commit/1ab3354))
- **loop:** Verify the task-scoped path on Actions ([f837d6d](https://github.com/Alex1990/tiny-oss/commit/f837d6d))
- **loop:** Check out the PR's code for same-repo PRs ([5451e88](https://github.com/Alex1990/tiny-oss/commit/5451e88))
- **loop:** Log every decision that produces no run ([de050ad](https://github.com/Alex1990/tiny-oss/commit/de050ad))
- **norms:** Add the commit-message convention ([9ab6fd1](https://github.com/Alex1990/tiny-oss/commit/9ab6fd1))
- **loop:** Translate the loop host to English ([3c9cfac](https://github.com/Alex1990/tiny-oss/commit/3c9cfac))
- **loop:** Fix a stale path in the cron comment ([f079d72](https://github.com/Alex1990/tiny-oss/commit/f079d72))
- **loop:** Wire the weekly retro schedule ([1df565f](https://github.com/Alex1990/tiny-oss/commit/1df565f))
- **loop:** Fix the dependabot CI failure, guard runs that lack secrets ([f11a55e](https://github.com/Alex1990/tiny-oss/commit/f11a55e))
- **loop:** Limit the D9 reopen check to terminal states ([723aacc](https://github.com/Alex1990/tiny-oss/commit/723aacc))
- **deps-dev:** Bump hono from 4.12.34 to 4.13.5 ([88d54e1](https://github.com/Alex1990/tiny-oss/commit/88d54e1))
- **loop:** Move tasks to terminal states on GitHub gate events ([2d104af](https://github.com/Alex1990/tiny-oss/commit/2d104af))
- **loop:** Terminalise the task of a non-loop PR when it closes ([05cbfb6](https://github.com/Alex1990/tiny-oss/commit/05cbfb6))
- **loop:** Correct the D33 note (dependabot PRs never reach triage) ([fcb23ff](https://github.com/Alex1990/tiny-oss/commit/fcb23ff))
- **loop:** Record what A1 structurally cannot validate ([025a82b](https://github.com/Alex1990/tiny-oss/commit/025a82b))
- **loop:** Let workflow_dispatch override the engine model ([4f72802](https://github.com/Alex1990/tiny-oss/commit/4f72802))
- **loop:** Do not push state when the pull never ran ([8e2282b](https://github.com/Alex1990/tiny-oss/commit/8e2282b))
- **loop:** Record the D34 verification run ([3019498](https://github.com/Alex1990/tiny-oss/commit/3019498))
- **loop:** Record the write-credential scope decision (does PR write include merge?) ([a6c46f0](https://github.com/Alex1990/tiny-oss/commit/a6c46f0))
- **loop:** Record L2c — the loop opens PRs and still cannot merge ([92fdfa2](https://github.com/Alex1990/tiny-oss/commit/92fdfa2))
- **loop:** Measure the GitHub credential instead of assuming it ([a86af17](https://github.com/Alex1990/tiny-oss/commit/a86af17))
- **loop:** Widen the credential probe to the dangerous scopes too ([f95274e](https://github.com/Alex1990/tiny-oss/commit/f95274e))
- **loop:** Keep a writable credential out of the agent's hands ([c17bfc1](https://github.com/Alex1990/tiny-oss/commit/c17bfc1))
- **loop:** Cross-check the credential probes against GitHub's own permissions ([18b49da](https://github.com/Alex1990/tiny-oss/commit/18b49da))
- **loop:** Replace the unsound permission probe with idempotent writes ([2af56f7](https://github.com/Alex1990/tiny-oss/commit/2af56f7))
- **loop:** Check the agent credential on signals that actually exist ([187d420](https://github.com/Alex1990/tiny-oss/commit/187d420))
- **loop:** Measure Contents with a real write, not the repo permissions object ([a11cc0a](https://github.com/Alex1990/tiny-oss/commit/a11cc0a))
- **loop:** Implement L2c — the host pushes the branch, the agent never can ([fc8072c](https://github.com/Alex1990/tiny-oss/commit/fc8072c))
- **loop:** Give the agent no write credential at all, not a narrower one ([67f799b](https://github.com/Alex1990/tiny-oss/commit/67f799b))
- **loop:** Make the branch ruleset the gate, not the GitHub credential ([13ecf41](https://github.com/Alex1990/tiny-oss/commit/13ecf41))
- **loop:** Tell a job token apart from a PAT in the boundary check ([fe0cd2c](https://github.com/Alex1990/tiny-oss/commit/fe0cd2c))
- **loop:** Let workflow_dispatch fall back to the write switch ([1e452a2](https://github.com/Alex1990/tiny-oss/commit/1e452a2))
- **loop:** Let a triaged task actually reach the implementing stage ([31aa850](https://github.com/Alex1990/tiny-oss/commit/31aa850))
- **loop:** Report every GitHub action a run took, not just the last two ([af4d600](https://github.com/Alex1990/tiny-oss/commit/af4d600))
- **ci:** Run Azure signer oracle in CI ([88982b2](https://github.com/Alex1990/tiny-oss/commit/88982b2))
- **norms:** Let the loop open host PRs, keep merging with the owner ([6a57a66](https://github.com/Alex1990/tiny-oss/commit/6a57a66))
- **loop:** Attribute loop commits to github-actions[bot] ([f7f6897](https://github.com/Alex1990/tiny-oss/commit/f7f6897))
- **norms:** Add Volcano Engine TOS to AGENTS.md entry list ([bb2c01b](https://github.com/Alex1990/tiny-oss/commit/bb2c01b))
- **tooling:** Make the oxlint config effective and clear its warnings ([a3384f7](https://github.com/Alex1990/tiny-oss/commit/a3384f7))
- **tooling:** Cut releases through a pull request, tag after the merge ([13d2c80](https://github.com/Alex1990/tiny-oss/commit/13d2c80))

### ✅ Tests

- Skip OSS integration cases when no credentials are configured ([8d149b9](https://github.com/Alex1990/tiny-oss/commit/8d149b9))

### 🤖 CI

- Add GitHub Actions workflow for lint and test ([dab2f55](https://github.com/Alex1990/tiny-oss/commit/dab2f55))
- Add coverage and post it as a PR comment ([8020b24](https://github.com/Alex1990/tiny-oss/commit/8020b24))

### ❤️ Contributors

- Alex Chao ([@Alex1990](https://github.com/Alex1990))
- Tiny-oss Loop ([@loop](https://github.com/loop))

## v1.1.0

[compare changes](https://github.com/Alex1990/tiny-oss/compare/v1.0.2...v1.1.0)
Expand Down
41 changes: 31 additions & 10 deletions bump.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,49 @@ import { defineConfig } from 'bumpp'
* 1. bumpp bumps the version in package.json (interactive semver prompt)
* 2. this `execute` hook regenerates CHANGELOG.md for the new version and
* stages it, so the changelog lands in the release commit
* 3. bumpp commits (`chore(release): <version>`, matching repo history),
* tags `v<version>` and pushes
* 3. bumpp commits (`chore(release): <version>`) on a `release/v<version>`
* branch, pushes that branch and opens a pull request
*
* `changelogen -r` must receive the exact new version: without it the heading
* would read `<oldTag>...<branch>` instead of `v<newVersion>`.
* The release commit travels as a pull request because the `Main branch`
* ruleset refuses every direct push to `main`, releases included: `422 Changes
* must be made through a pull request`. The owner's bypass (`pull_request`
* mode) covers merging a PR, not pushing one, so there is nothing to route
* around — see `docs/agents/release.md`.
*
* `pr.base` is pinned instead of detected: bumpp otherwise reads the base from
* `origin/HEAD`, which still says `master` in clones that predate the rename.
*
* bumpp creates no tag in this mode — it cannot know the merge commit, and a
* squash or rebase merge rewrites the release commit. The tag is made after the
* merge by `pnpm release:tag` (`scripts/release-tag.mjs`).
*
* The commit message and `--all` are passed on the command line in
* `package.json` rather than set here: bumpp's CLI defaults (`--commit`,
* `--all`) take precedence over the config file's object form, so a
* `commit: { message }` here would be silently replaced by the default
* `chore: release v<version>` — which is how v1.1.0 was committed.
*
* `all: true` matters: without it bumpp commits with `git commit <files>`
* (only the bumped files), which ignores other staged paths — a staged
* CHANGELOG.md would never land in the release commit. `git commit -a`
* commits the whole index.
* CHANGELOG.md would never land in the release commit.
*
* `changelogen -r` must receive the exact new version: without it the heading
* would read `<oldTag>...<branch>` instead of `v<newVersion>`.
*/
export default defineConfig({
all: true,
commit: {
message: 'chore(release): {version}',
pr: {
base: 'main',
branch: 'release/v{version}',
title: 'chore(release): {version}',
body: '{oldVersion} → {version}',
},
execute(operation) {
execSync(`changelogen --output CHANGELOG.md -r ${operation.state.newVersion}`, {
stdio: 'inherit',
})
// A brand-new CHANGELOG.md is untracked, and `git commit -a` skips
// untracked files, so stage it explicitly.
// A brand-new CHANGELOG.md is untracked, and `git commit -a` skips untracked
// files, so stage it explicitly.
execSync('git add CHANGELOG.md', { stdio: 'inherit' })
},
})
84 changes: 71 additions & 13 deletions docs/agents/release.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,87 @@
# Releasing

How to cut a release of tiny-oss. Tooling: `bumpp` drives the version bump / commit / tag / push; `changelogen` maintains `CHANGELOG.md`. Orchestration lives in `package.json` scripts and `bump.config.ts` — read `bump.config.ts` before changing anything here.
How to cut a release of tiny-oss. Tooling: `bumpp` drives the version bump,
the release branch and the pull request; `changelogen` maintains
`CHANGELOG.md`; `scripts/release-tag.mjs` (`pnpm release:tag`) tags the merged
release commit. Orchestration lives in `package.json` scripts and
`bump.config.ts` — read `bump.config.ts` before changing anything here.

A release is a change to `main` like any other, and `main` only moves through a
pull request: the `Main branch` ruleset refuses a direct push with `422 Changes
must be made through a pull request`, for every credential, the owner's
included. So the release commit travels as a PR too. What the owner's bypass
(`bypass_mode: pull_request`) buys is *merging* a PR without a second
reviewer — which is what makes a solo release possible — not pushing one.

## Loop preflight (recommended)

The loop runs stage=release before you cut a release: all gates green, a
version suggestion (feature → minor, fix/docs → patch, breaking → human),
and a preview changelog. Read its report comment, then follow the Flow below
yourself — `pnpm release` and `pnpm publish` stay human-only.
yourself — `pnpm release`, `pnpm release:tag` and `pnpm publish` stay
human-only.

## Flow

1. **Working tree must be clean.** `bump.config.ts` sets `all: true`, so the release commit runs `git commit -a` and sweeps up every tracked modification and staged file. Uncommitted work would land in the release commit.
1. **Start from a clean tree on an up-to-date `main`.** `bumpp --pr` refuses
otherwise (clean tree, on the base branch, not behind `origin/main`).
`bump.config.ts` sets `all: true`, so the release commit runs `git commit -a`
and sweeps up every tracked modification and staged file.
2. **Gates** (fast, no browser needed): `pnpm lint && pnpm check:types`.
3. `pnpm release` — interactive semver prompt. Pick per the commits since the last tag: new feature(s) → `minor`; fixes/docs/tests only → `patch`. This repo has had no breaking change yet, so no `major`. Non-interactive (agent/CI): `pnpm exec bumpp --release <patch|minor> --yes`.
4. That commits `chore(release): <version>` — including the regenerated `CHANGELOG.md` — tags `v<version>`, and pushes straight to `main`, carrying any unpushed commits already on the branch. Push is on by default; opt out with `--no-push`.
5. **`pnpm build && pnpm publish`** — manual, needs npm auth. `dist/` is gitignored but ships in the package (`files: ["dist", "UPGRADING.md"]`), so build locally right before publishing.
3. `pnpm release` — interactive semver prompt. Pick per the commits since the
last tag: new feature(s) → `minor`; fixes/docs/tests only → `patch`. This
repo has had no breaking change yet, so no `major`. Non-interactive
(agent/CI): `pnpm exec bumpp --release <patch|minor> --yes`.
bumpp then creates `release/v<version>`, commits
`chore(release): <version>` including the regenerated `CHANGELOG.md`, pushes
the branch, switches you back to `main` and opens the pull request with `gh`.
**No tag is created** — see step 5.
4. **Merge the release PR.** You authored it, so you cannot approve it; the
ruleset bypass is what lets you merge it anyway. Merging is the consent.
Squash and rebase both rewrite the release commit's SHA on `main` — which is
exactly why the tag is not made on the branch.
5. **`pnpm release:tag`** — on the updated `main`, tags `v<version>` at the
merge result and pushes the tag. It refuses a dirty tree, a branch other
than `main`, a `main` out of sync with `origin/main`, and an existing tag.
`--no-push` creates the tag locally only, for a rehearsal.
6. **`pnpm build && pnpm publish`** — manual, needs npm auth. `dist/` is
gitignored but ships in the package (`files: ["dist", "UPGRADING.md"]`), so
build locally right before publishing.

Preview the next changelog without touching anything: `pnpm changelog` (stdout only).
Preview the next changelog without touching anything: `pnpm changelogen`
(stdout only).

## Gotchas (verified against the installed tool versions)

- `bump.config.ts` MUST keep `all: true`. Without it bumpp commits with `git commit <files>` (only the bumped files), silently dropping the staged `CHANGELOG.md` from the release commit. That shipped once; it was fixed by amending the release commit and force-pushing.
- `changelogen` needs `-r <newVersion>` (injected by the config's `execute` hook from `operation.state.newVersion`), or the changelog heading reads `<oldTag>...<branch>` instead of `v<newVersion>`.
- A brand-new `CHANGELOG.md` is untracked, and `git commit -a` skips untracked files — the `execute` hook stages it explicitly. Do not pre-create `CHANGELOG.md`; the release commit creates it.
- Bare `changelogen` prints to stdout and writes nothing; only `--output` / `--bump` / `--release` touch disk.
- Re-tagging after a mistaken push: `git push --force-with-lease origin <tag>` fails with `stale info` for tags — use `git push --force origin <tag>`.
- Tags are `v<version>` since v1.0.0 (pre-1.0.0 `0.x.y` tags have no prefix). `bumpp`/`changelogen` defaults match the `v` prefix; commit messages historically read `chore(release): <version>` without the `v`.
- **Do not plan around a direct push to `main`.** The ruleset answers `422`
whatever the credential; a PR is the only way in. Tags are *not* covered —
there is no tag ruleset — so `git push origin v<version>` works.
- `pr.base: 'main'` MUST stay in `bump.config.ts`. Without it bumpp derives the
base from `origin/HEAD`, which still says `master` in a clone made before the
rename, and the precondition check then refuses to run on `main`.
- The commit message lives on the command line in `package.json`, not in
`bump.config.ts`: bumpp's CLI defaults (`--commit`, `--all`) win over the
config file's object form, so a `commit: { message }` there is silently
replaced by the default `chore: release v<version>` — that is how v1.1.0 was
committed, config and all. `-a` is passed for the same reason: `all: true` in
the config is the belt, the flag is the braces.
- `bump.config.ts` MUST keep `all: true`. Without it bumpp commits with
`git commit <files>` (only the bumped files), silently dropping the staged
`CHANGELOG.md` from the release commit. That shipped once; it was fixed by
amending the release commit and force-pushing.
- The tag is created after the merge, never on the release branch: bumpp's PR
mode creates no tag by design, since it cannot know the merge commit. Tags
are annotated (`git tag -a`) — v1.1.0 was cut by hand and is the one
lightweight tag in the history.
- `changelogen` needs `-r <newVersion>` (injected by the config's `execute` hook
from `operation.state.newVersion`), or the changelog heading reads
`<oldTag>...<branch>` instead of `v<newVersion>`.
- A brand-new `CHANGELOG.md` is untracked, and `git commit -a` skips untracked
files — the `execute` hook stages it explicitly. Do not pre-create
`CHANGELOG.md`; the release commit creates it.
- Bare `changelogen` prints to stdout and writes nothing; only `--output` /
`--bump` / `--release` touch disk.
- Re-tagging after a mistaken push: `git push --force-with-lease origin <tag>`
fails with `stale info` for tags — use `git push --force origin <tag>`.
- Tags are `v<version>` since v1.0.0 (pre-1.0.0 `0.x.y` tags have no prefix);
`bumpp`'s default and `scripts/release-tag.mjs` agree on the `v` prefix.
Loading
Loading