diff --git a/.github/RELEASING.md b/.github/RELEASING.md index f3fa783b..da8e1b5e 100644 --- a/.github/RELEASING.md +++ b/.github/RELEASING.md @@ -42,8 +42,9 @@ it cannot be deleted, so direct pushes are fine too. `main` moves only by promotion: a pull request `dev → main`, which also builds every platform's engines, needs a green `CI`, and only an admin can merge. Every version released is a tag on -`main`. main only squash-merges, so after every push to main the `sync-dev` job in `release.yml` -merges main back into dev; a hotfix that conflicts with dev pushes nothing and opens an issue with +`main`. A promotion is merged with a merge commit, never squashed, so main shares dev's history and +"dev is N commits ahead" counts only unreleased work. Merge work into dev with squash. After every +push to main the `sync-dev` job in `release.yml` merges main back into dev; a hotfix that conflicts with dev pushes nothing and opens an issue with the commands to resolve it by hand. ## Nightly diff --git a/.github/scripts/protect-main.sh b/.github/scripts/protect-main.sh index 6a7fa16e..ec73a7bd 100755 --- a/.github/scripts/protect-main.sh +++ b/.github/scripts/protect-main.sh @@ -14,7 +14,8 @@ # - the `CI` check must pass, evaluated against an up-to-date branch # - only the repository ADMIN role may merge into main (ruleset main-merge-admins): # anyone can open a pull request, an admin merges it, their own included -# - linear history: squash or rebase, no merge bubbles +# - a promotion lands as a merge commit, never a squash: main then shares dev's history, so +# "dev is N commits ahead" counts only what is not on main yet # - a release tag (v*) can be created but never moved or deleted: npm will not # republish a version, so a tag that moved would name a tree nobody installed # @@ -41,7 +42,6 @@ payload="$(cat <<'JSON' "rules": [ { "type": "deletion" }, { "type": "non_fast_forward" }, - { "type": "required_linear_history" }, { "type": "pull_request", "parameters": { @@ -51,7 +51,7 @@ payload="$(cat <<'JSON' "require_last_push_approval": false, "require_extra_approval_for_unattributed_changes": false, "required_review_thread_resolution": true, - "allowed_merge_methods": ["squash", "rebase"] + "allowed_merge_methods": ["merge"] } }, { @@ -156,12 +156,13 @@ apply_ruleset main-merge-admins "$merge_payload" apply_ruleset protect-dev "$dev_payload" apply_ruleset protect-release-tags "$tag_payload" -# Merge-method hygiene lives on the repository, not the ruleset: squash-only, and +# Merge-method hygiene lives on the repository: squash for work into dev, merge commits allowed so that +# protect-main can require them for a promotion (a repository setting cannot differ per branch), and # delete the branch once it has landed so the branch list stops accumulating the # stale aliases this repo has collected before. gh api -X PATCH "repos/$REPO" \ -F allow_squash_merge=true \ - -F allow_merge_commit=false \ + -F allow_merge_commit=true \ -F allow_rebase_merge=false \ -F delete_branch_on_merge=true \ -F allow_auto_merge=true >/dev/null diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3da821a5..0a1799b7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -85,10 +85,9 @@ jobs: echo "::notice::drafted $tag — review it under Releases and publish it to ship to npm" # ── keep dev on top of main ───────────────────────────────────────────────── - # main only takes squash merges, so a promotion from dev lands on main as a NEW - # commit that dev does not have; without this, the next dev→main pull request - # shows the old work again. Merging main back into dev records that it is - # already there. A promotion merges cleanly (same content both sides); a hotfix + # A promotion from dev lands on main as a merge commit that dev does not have + # yet, and a hotfix straight to main is a commit dev lacks too; merging main + # back into dev records that they are already there. A promotion merges cleanly (same content both sides); a hotfix # that went straight to main and touches lines dev has since changed does not, # and then nothing is pushed: an issue says how to resolve it by hand. sync-dev: