Skip to content

ci: weekly SemVer releases with generated notes; freeze CHANGELOG.md at 1.7.4 - #800

Merged
jakob1379 merged 6 commits into
masterfrom
chore/weekly-github-changelog-release
Oct 31, 2026
Merged

jakob1379 merged 6 commits into
masterfrom
chore/weekly-github-changelog-release

Conversation

@jakob1379

@jakob1379 jakob1379 commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

The hand-edited CHANGELOG.md is replaced by a weekly GitHub Release. Every PR edited [Unreleased], so every PR after the first conflicted on it, and only Mads could cut a release.

every Monday 06:00 UTC (or Run workflow)              .github/workflows/release.yml
  skip unless repo == ai-job-search-dev/ai-job-search
  last = latest GitHub Release                         v1.7.3 today
  skip if master == last
  next = cz bump --get-next (commitizen via setup-uv)   or the manual override
           any `type!:` / BREAKING CHANGE: -> major
           any `feat`                       -> minor
           any `fix` / `refactor` / `perf`  -> patch
           only docs / chore / ci / ...     -> skip the week
  fail unless ci.yml passed on master HEAD
  fail if next exists or is not newer than last
  gh release create next --generate-notes              same format as pingdotgg/t3code
 .github/
+├── workflows/release.yml          # weekly tag + generated notes, no commit to master
 ├── PULL_REQUEST_TEMPLATE.md       # + "PR title is the release note and sets the version"
+.cz.toml                           # commitizen: conventional commits, versions from v* tags
 tests/
+├── test_release_workflow.py       # fork guard, job-scoped write access, SHA-pinned actions
 ├── test_changelog_structure.py    # [Unreleased] structure checks -> content pin (upstream only)
 CHANGELOG.md                       # [Unreleased] -> [1.7.4], intro points at Releases, frozen
 CONTRIBUTING.md / README.md / SETUP.md   # releases are weekly checkpoints that passed CI

The CHANGELOG's [Unreleased] entries become its last section, [1.7.4], in this PR instead of a separate hand-cut release. The heading has no date because the tag doesn't exist yet.

Evidence

  • Before: stale PRs that add a changelog entry mid-section would merge cleanly into a frozen section. Nothing chose the version.
    After: commitizen 4.19.3 replayed on our own tags:

    cz bump --get-next   (run at each next release commit)
    v1.6.0 -> 1.7.0   (Mads: 1.7.0)
    v1.7.0 -> 1.8.0   (Mads: 1.7.1, feat shipped as patch)
    v1.7.1 -> 1.8.0   (Mads: 1.7.2, 7 feats)
    v1.7.2 -> 1.8.0   (Mads: 1.7.3)
    v1.7.3 -> 1.7.4   (master today: 64 commits, 53 fix, 0 feat)
    
  • Tests: tests/test_release_workflow.py (3) and tests/test_changelog_structure.py (1) pass, and the guard skips with GITHUB_REPOSITORY=someone/fork.

    • Full suite: 879 tests, 3 failures in test_check_framework_version. The same 3 fail on master without this change in this environment (environmental).
    • lint_skills, check_framework_version and security_guards are OK.
  • Review: approved by Mads. converge-review ran with 4 independent seats, then a scoped re-review by 2 fresh seats.

    • Both re-review seats verdicted all 10 accepted findings addressed, except one deferred by design (below), and found no new breakage.
    • Fixes from the review:
      • write permission moved to the job;
      • the manual override rejects existing or older versions;
      • tests pin the fork guard and the SHA-pinned checkout;
      • the hash guard skips on forks;
      • a missing tag gives a clean error instead of a traceback;
      • the date written ahead of the release was dropped.

Merge Danger

Door: two-way for the code; one-way for every release it publishes.

A published tag can be deleted, but forks may already have fetched it. Reverting this PR restores the old process apart from the frozen hash and the [1.7.4] heading.

Blast Radius: releases

  • Right after merging, run the workflow manually with version = 1.7.4. The frozen [1.7.4] section and its compare link assume that tag. A feat or ! merged before the first Monday run would otherwise make it v1.8.0.
  • Stale PRs that still edit CHANGELOG.md: master's ruleset has strict up-to-date checks off (strict_required_status_checks_policy: false), so a pre-freeze PR can merge on its old green CI. Master CI then fails the hash guard, and the release refuses to run until the edit is reverted. Turn on "require branches to be up to date", or re-run CI on those PRs before merging. To resolve the conflict: git checkout origin/master -- CHANGELOG.md.
  • PR titles now decide the version. A feature titled fix: ships as a patch, and a docs:/chore:/ci: or untyped title doesn't trigger a release on its own.
    • The repo's squash title setting is COMMIT_OR_PR_TITLE (confirmed via the API), so a single-commit PR's version comes from its commit subject while the notes show the PR title. Set it to Pull request title (Settings → General → Pull Requests) so the bump and the notes use the same text.
    • Merge commits are also enabled: a merge-committed PR's own commits count towards the bump.
  • Untested on GitHub itself: the workflow never ran (no actionlint, no live gh). A tag ruleset that blocks GITHUB_TOKEN would make the first run fail loudly.

Every Monday at 06:00 UTC the workflow tags master and publishes a GitHub
Release whose notes list the merged PR titles. tools/next_version.py picks the
version from the commits since the last release: type!: or a BREAKING CHANGE
footer is major, feat is minor, anything else is patch. A manual run can
override it. Weeks without commits are skipped, a master commit whose CI did
not pass is never released, and forks never run it.
PR titles are now the release notes and their type sets the version, so
CONTRIBUTING and the PR template say so. README and SETUP describe releases
as weekly checkpoints that passed CI instead of pointing at CHANGELOG.md.
Rolls [Unreleased] into [1.7.4] and rewrites the intro to point at GitHub
Releases. The structure test becomes a content pin: stale PRs carry entries
that git would merge cleanly into the frozen section, so any edit now fails
CI with a pointer to the PR title.
Write access moves to the job; the override rejects existing or older
versions; next_version.py reports a missing tag instead of a traceback and
drops the unused rev argument; tests pin the fork guard and SHA-pinned
checkout. The frozen changelog drops the date written ahead of the release,
describes its guard accurately, and the guard skips on forks.
@jakob1379
jakob1379 marked this pull request as draft October 31, 2026 10:51
… of an in-repo script

A week of only docs, chore or ci commits now ships nothing on its own, matching commitizen's conventional-commit bump rules; fix, refactor and perf bump patch.
@jakob1379
jakob1379 marked this pull request as ready for review October 31, 2026 11:19
@jakob1379
jakob1379 merged commit 7f01d75 into master Oct 31, 2026
19 checks passed
@jakob1379
jakob1379 deleted the chore/weekly-github-changelog-release branch October 31, 2026 13:28
MadsLorentzen added a commit to ai-tvang/ai-job-search that referenced this pull request Nov 2, 2026
…ase notes come from the PR title)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to mvanhorn/ai-job-search that referenced this pull request Nov 9, 2026
…h-dev#800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit that referenced this pull request Nov 9, 2026
* fix(salary): split combined name-and-city workbook columns

The IDA demonstration workbook heads its company column "Firmanavn og by"
and stores "Ørsted A/S, Fredericia" in that one cell. After the header is
detected, convert_salary_excel copied the whole cell into company with
city "". salary_lookup --city only reads entry["city"], so the documented
lookup for Ørsted in Fredericia missed.

When the company header also names a city and there is no city column,
split the cell on the last ", ". A Company-only header still keeps commas
in the name.

* fix(salary): split a combined name-and-city cell on the last comma

Real IDA cells have no space after the separating comma
("Ørsted A/S,Fredericia"), and some company names contain ", "
themselves ("Rambøll Danmark A/S, Odense,Odense C"). Splitting on the
last ", " missed almost every real row, so --city still dropped out.

split_combined_company_city now splits on the last "," and strips both
parts. Test fixtures use the real unspaced cell shape, and a new unit
test covers a company name that contains a comma. The docstrings,
CHANGELOG entry, tools/README_SALARY_TOOL.md and the README salary
section describe the new split.

* docs(changelog): move the combined-city entry under Unreleased

The merge of master brought in the 1.7.3 release section, which left
this PR's Fixed entry under an already released version. Move it to
the Unreleased Fixed list.

* chore: drop the CHANGELOG hunk, the file is frozen since #800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Mads Lorentzen <madslorentzen17@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 9, 2026
…h-dev#800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 9, 2026
…h-dev#800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit that referenced this pull request Nov 9, 2026
* fix(fetch-page): decode standard zlib-wrapped HTTP deflate

* docs(changelog): reference deflate fix PR 711

* chore: drop the CHANGELOG hunk, the file is frozen since #800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Mads Lorentzen <madslorentzen17@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit that referenced this pull request Nov 9, 2026
* fix(add-portal): keep generated tests offline in CI

* docs(changelog): reference portal test fix PR 714

* chore: drop the CHANGELOG hunk, the file is frozen since #800

Release notes are generated from PR titles now.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Mads Lorentzen <madslorentzen17@gmail.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Mgobeaalcoba pushed a commit to Mgobeaalcoba/ai-job-search that referenced this pull request Nov 9, 2026
- scope the never-a-veto test to the Employment type paragraph instead of
  matching the phrase anywhere in rank.md
- count portal `detail` output as a source next to the posting text
- bracket the optional ` · <employment type>` so a null type leaves no
  dangling separator
- drop the CHANGELOG.md hunk: the file is frozen since ai-job-search-dev#800 and release notes
  come from the PR title

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mv8AZjCnuGt98qsM9zuCFZ
MadsLorentzen pushed a commit that referenced this pull request Nov 10, 2026
* feat(scrape,rank): record and surface a posting's employment type

Nullable employment_type (full_time|part_time|contract|freelance) in the
seen_jobs.json entry, read from posting text at Step 3; /rank shows it on
the shortlist line and flags a mismatch with a stated profile preference
(never a veto). No pay normalisation, no new profile field.

* fix(scrape,rank): address review on employment type

- scope the never-a-veto test to the Employment type paragraph instead of
  matching the phrase anywhere in rank.md
- count portal `detail` output as a source next to the posting text
- bracket the optional ` · <employment type>` so a null type leaves no
  dangling separator
- drop the CHANGELOG.md hunk: the file is frozen since #800 and release notes
  come from the PR title

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mv8AZjCnuGt98qsM9zuCFZ

---------

Co-authored-by: Claude <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…G hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…HANGELOG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…OG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…LOG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…OG hunk

Resolves the security_guards.py conflict by adding the two hook names to master's
moved FORBIDDEN_SCRIPTS block and docstring item 3. CHANGELOG.md is frozen at
1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…NGELOG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…OG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MadsLorentzen added a commit to rudycelekli/ai-job-search that referenced this pull request Nov 10, 2026
…HANGELOG hunk

CHANGELOG.md is frozen at 1.7.4 since ai-job-search-dev#800; release notes are generated from the PR title.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants