diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 1105a8919a4..a2c3d67a8ed 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -1,6 +1,119 @@
# Maintainer Hints
-## Creating a New Release
+## Background
+
+`agoric-sdk` is a monorepo containing multiple components which are currently not released at the same time. Roughly there are 2 main categories of code:
+- Code running on chain inside a worker managed by swingset, with orthogonal persistence. This code has to be upgraded through a "vat upgrade" mechanism driven by explicit inputs to swingset: a bundle + publish + core-eval (which can be combined as a core-proposal).
+- Everything else, including chain software a.k.a. the swingset host (golang/cosmos, cosmic-swingset and related kernel packages) as well as tools and repo testing infrastructure (agoric-cli, deploy-script-support, .github, etc.). This code is simply executed whenever a new version of `agoric-sdk` is checked out, without any further steps beyond the action that caused the new version of `agoric-sdk` to be used.
+
+We would like to have similar behavior regardless of whether a chain launched from a release upgrades a predecessor or starts clean. Since we are currently not in a position where we can upgrade all vats, our release must not include behavioral changes to code running in any vat that it is not explicitly upgrading. The easiest way to accomplish that is by avoiding any changes to code included in vats, however this is not always feasible.
+
+We maintain `release-*` branches which represent a fork of the `master` dev branch at a given point:
+- `release-pismo` is the previous/archived release branch used before the "bulldozer" upgrade which threw away all JavaScript state.
+- `release-mainnet1B` is our current release branch. Despite its name, it has lived beyond the "mainnet-1" phase of the agoric-3 chain.
+
+Release branches should only ever be updated when publishing a new release.
+
+Releases are tagged commits from the above release branches, with a corresponding entry in https://github.com/Agoric/agoric-sdk/releases .
+
+To ease the maintenance process, we want to avoid any commit original to the release branch that has no direct equivalent on the `master` branch, except when needed to generate or test a specific release. To satisfy that, we usually directly cherry-pick commits and PRs from the `master` branch. We do not expect to merge the release branches back into `master`.
+
+To clearly delineate separate releases from each other on the release branch, we now use "dev release" branches to compile all changes going into a release before merging that branch into the release branch when the release is cut. It also allows us to re-scope a release if needed without having to revert commits on the release branch.
+
+## Preparing for a Release
+
+### Assign Release Parameters
+
+The Release Owner and other appropriate stakeholders must agree on:
+
+- _**base branch**_: This should be `release-mainnet1B`, but might need to vary for a patch release.
+
+- _**release label**_: This is used for the git tags, and is currently expected to follow a
+ sequential pattern (example: `agoric-upgrade-8`).
+ The mainnet release label is preceded by release candidates numbered from zero
+ (example: `agoric-upgrade-8-rc0`), and shares its commit with the final release candidate.
+
+- _**release short label**_: This is used for release artifacts, and is currently expected to be a
+ simplified substring of _**release label**_ including the number (examples: `upgrade-8`,
+ `upgrade-8-rc0`).
+
+- _**upgrade name**_: This is used to coordinate with the cosmos-sdk UpgradeKeeper.
+ The name used to upgrade mainnet is currently expected to match the _**release label**_, but
+ other networks should use distinct names that indicate their testing-oriented purpose
+ (examples: `agorictest-upgrade-8`, `agorictest-upgrade-8-2`).
+
+### Create the "dev release" branch
+
+- [ ] When a new release is planned, create a new branch from branch `release-mainnet1B` with a name like `dev-$releaseShortLabel` (example: `dev-upgrade-8`). This can be done from the command line or the [GitHub Branches UI](https://github.com/Agoric/agoric-sdk/branches).
+- [ ] Initialize the new branch for the planned upgrade:
+ - [ ] In **golang/cosmos/app/app.go**, update the `upgradeName` constants and the associated upgrade handler function name to correspond with the [_**upgrade name**_](#assign-release-parameters).
+ Remove from the function any logic specific to the previous upgrade (e.g., core proposals).
+ - [ ] Ensure that **a3p-integration/package.json** has an object-valued `agoricSyntheticChain` property with `fromTag` set to the [agoric-3-proposals Docker images](https://github.com/Agoric/agoric-3-proposals/pkgs/container/agoric-3-proposals) tag associated with the previous release
+ (example: `use-upgrade-7`).
+ - [ ] Ensure that **a3p-integration/proposals** contains a single subdirectory with the following characteristics
+ - named like "$prefix:[_**release short label**_](#assign-release-parameters)" per [agoric-3-proposals: Naming](https://github.com/Agoric/agoric-3-proposals#naming) (conventionally using "a" for the unreleased $prefix, e.g. `a:upgrade-8`)
+ - containing a **package.json** having an object-valued `agoricProposal` property with `sdkImageTag` set to "unreleased" and `planName` set to the [_**upgrade name**_](#assign-release-parameters)
+ - containing other files appropriate for the upgrade per [agoric-3-proposals: Files](https://github.com/Agoric/agoric-3-proposals#files)
+
+ For example, see the [upgrade-14 PR](https://github.com/Agoric/agoric-sdk/pull/8755).
+
+### Populate the "dev release" branch
+
+For each set of changes to include:
+- [ ] Create a work branch from the "dev release" branch.
+- [ ] Cherry-pick approved changes from `master` onto this work branch.
+ - Avoid any cherry-pick that has side-effects on code you do not wish to be upgraded. For example, a change impacting deployed vat code that is not meant to be part of the upgrade (comment/types only changes may be acceptable, but will still result in new bundles, so should be avoided if possible). Chain software code is usually safe to upgrade as long as integration with code running inside vats doesn't change. For example, the host side of any bridge and the set of swingset syscalls must remain backwards compatible.
+ - For integrating a single PR (best suited to vat code changes which often require manual adaptation):
+ - [ ] Cherry-pick the commits of the `master` PR onto the work branch with minimal/mechanical conflict resolutions.
+ It's acceptable to author the changes on the "dev release" based work branch and then rebase them to a master PR, as long as the PRs lands at "about the same time" (`master` PR **MUST** be merged before a release is cut).
+ - [ ] As needed, author any extra commits required for compatibility on the "dev release" work branch.
+ - [ ] Create a PR with the "dev release" branch as target.
+ - [ ] Reviewer must check that changes are narrowly focused, and do not affect unrelated components.
+ - For vat code PRs, changes to other packages tests, tools, or scripts may be acceptable.
+ - Compare the resulting code of the changed component with its code on master, and highlight any unexpected differences.
+ - For integrating a set of PRs (best suited to PRs that do not affect vat code and can be cherry-picked somewhat cleanly):
+ - [ ] Optional: Ensure [git rerere](https://git-scm.com/book/en/v2/Git-Tools-Rerere) ("reuse recorded resolution") is locally enabled:
+ ```sh
+ git config rerere.enabled true
+ ```
+ - [ ] Author a `rebase-todo` by selecting relevant changes from the `master` branch rebase log (see below).
+ - For a convenient starting point, use `scripts/gen-rebase-todo.sh $since` to get a todo list reflecting all merge-inclusive changes from $since to the current HEAD (but note that on a fresh clone, branch names will be generated from commit titles rather than corresponding with those of the primary fork).
+ - Comment out any commit that should be excluded from a multi-commit PR.
+ - If a small change from an unrelated PR is needed (rider commits), either:
+ - Outside of a label/merge section, `pick` the commit, and indicate with a comment on the previous line the origin PR of the picked commit.
+ - Take the larger section of the rebase log related to the PR containing the commit, remove unneeded commits, and use `merge -c` (lower case instead of upper case `c`) to reword the merge commit's message indicating it's a merge of a partial pull request.
+ - [ ] Initiate an interactive rebase, and use the authored `rebase-todo`
+ ```sh
+ git rebase -i HEAD
+ ```
+ And replace the `noop` content with the authored `rebase-todo`.
+ - If encountering a commit with conflicts that have a straightforward resolution (such as 3-way combine with strategy "theirs" or "ours"), prefix with an explanatory `##` comment in the `rebase-todo`.
+ - If encountering a commit with conflicts that do not have a straightforward resolution, check if picking any prior commit would help resolve the conflicts.
+ - Abort the rebase, update the authored `rebase-todo`, and restart the interactive rebase.
+ - Avoid authoring manual changes unless absolutely necessary. If authoring changes, keep them as separate commits and indicate them as such on the authored rebase todo (insert either a `pick` instruction with the id of the commit you just authored or an `exec` instruction that makes the modifications and ends with `git commit -m $message`, in either case prefixing with an explanatory `##` comment).
+ - For `exec`, make portable in-place edits with either `ed` or `alias sed-i="sed -i $(sed --help 2>&1 | sed 2q | grep -qe '-i ' && echo "''")"`, e.g. `printf 'H\n/\( *\)foo/ s##\\1// prettier-ignore\\\n\nw\n' | ed -s packages/path/to/file'` or `sed-i -E "$(printf 's#( *)foo#\\1// prettier-ignore\\\n')" packages/path/to/file`.
+ - If a commit is empty, skip it and comment it out in the rebase todo.
+ - [ ] Verify that tests pass. In particular:
+ - Linting locally can catch incompatibilities in the cherry-pick, often requiring some changes to be reverted or more commits from `master` to be included. In those cases, update the authored `rebase-todo`, and redo the interactive rebase as necessary.
+ - Linting errors should not happen, unless a conflict resolution introduced formatting issues. In those cases, redo the interactive rebase and make sure to format the file before marking the conflict as resolved. Do not put formatting changes in unrelated commits.
+ - [ ] Create a PR with the "dev release" branch as target.
+ - [ ] In the description of the PR, include the authored `rebase-todo` used to construct the branch.
+ - Reviewer must check that changes accomplish the goal, and do not affect unrelated components:
+ - [ ] Verify that the `rebase-todo` is constructed from the `master` history in merge order, and note any deviations.
+ - [ ] Verify that all PRs necessary to accomplish the goal were selected.
+ - [ ] Verify that the description explains the presence of any extra commits not obviously necessary to accomplish the goal.
+ - [ ] If the goal is to catch up a specific component, compare the resulting code with the master code, and highlight any behavioral differences, or non-behavioral differences that may make future rebase work more complicated.
+ - [ ] Verify that unrelated components are not affected by picked changes. In particular, a chain software upgrade or tooling changes should not affect vat code. Changes to other components tests, tools, or scripts may be acceptable.
+ - In both cases:
+ - [ ] Apply the `force:integration` GitHub label to the PR.
+ - [ ] Merge the PR using the GitHub UI, using the "merge" strategy once all tests have passed.
+ - Use of auto-merge or the merge queue is not currently supported for a "dev release" branch.
+ - Integration tests are required on a "dev release" branch, and are triggered by adding the `force:integration` GitHub label to the PR.
+ - If the PR branch is no longer up to date with the "dev release" branch, do not use GitHub UI to update the branch. Instead rebase it locally with the `--rebase-merges` option (or re-apply the authored `rebase-todo`), and force push.
+ - The "squash" merge strategy is acceptable if the PR is straight pick of a single commit / squashed `master` PR, and no extra commits were required.
+ - As usual, never use the "rebase" GitHub merge strategy.
+
+## Creating a Release
These are the steps for a Release Manager to create and publish a
new release of the Agoric SDK. This combines the process of
@@ -9,75 +122,61 @@ publication of the SDK and its individual packages.
### Prerequisites
-#### Build Environment
+#### Prepare the Build Environment
Follow the instructions at the [getting started
guide](https://docs.agoric.com/guides/getting-started/) to install
the correct versions of `node`, `yarn`, and `git`. Also install the
latest version of the [Go development tools](https://go.dev/doc/install).
-#### NPM Account
+#### Authenticate your NPM Account
Sign up for an [NPM account](https://www.npmjs.com/signup) with
some form of 2FA. Then request that an administrator add your NPM
user ID to the `@agoric` organization and the `agoric` package.
-### Preparation
+### Describe the Release
-Together with the Release Owner and other appropriate stakeholders,
-ensure there is consensus on the following parameters for the
-release:
+The Release Owner and other appropriate stakeholders must agree on:
-- Base branch: which branch will the release be based on? The base
-branch will need to be stable and may be frozen at various times,
-so it is a good practice to have the base branch be a branch off
-of `master`. The base branch might also be used for followon patch
-releases before the next major release.
+- _**development history oriented description**_: a short description
+of the major changes in the release from the perspective of source code changes
+and tracked issues addressed.
-- Release labels: we currently label our releases with both a
-human-meaningful label such as `pismoA` and a sequential upgrade
-label like `agoric-upgrade-8`. In the future, semantic versioning
-might replace either or both label styles.
-
-- Development history oriented release descrition: a short description
-of the major changes in the release from the point of view of
-understanding the source code and tracked issues addressed by the
-release.
-
-- Validator oriented release description: a short description of the
+- _**validator oriented release description**_: a short description of the
release from the perspective of a validator to understand why the
release should be installed and important operational changes.
-### Generating the Release
+### Generate the Release
-Until we reach the next section "Publish the release", the release
-process can be aborted.
+Until we reach the next section ["Publish the release"](#publish-the-release),
+the release process can be aborted.
-- [ ] Check the development history oriented release description
-into the top-level CHANGELOG.md on the base branch.
+**Note: If there is an error or problem following the steps below, after debugging, please restart from this step to ensure there's no accidental contamination.**
-- [ ] Review the [next release](
-https://github.com/Agoric/agoric-sdk/labels/next%20release
-) label for additional tasks particular to this release.
+- [ ] Add the [_**development history oriented description**_](#describe-the-release)
+ to the top-level CHANGELOG.md on the [_**base branch**_](#assign-release-parameters).
+
+- [ ] Review the [next release](https://github.com/Agoric/agoric-sdk/labels/next%20release)
+ GitHub label for additional tasks particular to this release.
- [ ] Create a fresh, clean clone of the repository.
-This avoids accidental contamination from untracked or ignored
-changes in one's usual development repository.
+ This avoids accidental contamination from untracked or ignored
+ changes in one's usual development repository.
+ ```sh
+ # Fresh checkout under ~/release or any other preferred directory without agoric-sdk
+ mkdir ~/release
+ cd ~/release
+ git clone https://github.com/Agoric/agoric-sdk.git
+ cd agoric-sdk
+ ```
-#### Note: If there is an error or problem following the steps below, after debugging, please restart from this step to ensure there's no accidental contamination.
+- [ ] `git switch` to the ["dev release" branch](#create-the-dev-release-branch).
-```sh
-# Fresh checkout under ~/release or any other preferred directory without agoric-sdk
-cd ~/release
-git clone https://github.com/Agoric/agoric-sdk.git
-cd agoric-sdk
-```
+- [ ] Create a timestamped release branch for hosting the commit to be tagged as the release.
-- [ ] Check out the appropriate base branch as outlined in "Preparation" above.
-
-- [ ] Create a release branch tagged with a timestamp. The specific commit tagged as the release will live
-in this branch. The release tags will be human-meaningful, the release branch need not be.
+ Unlike release tag names, the release branch name does not need to be human-meaningful.
```sh
# Create a release branch.
now=`date -u +%Y%m%dT%H%M%S`
@@ -90,12 +189,11 @@ in this branch. The release tags will be human-meaningful, the release branch ne
yarn install --force
```
-- [ ] Generate new SDK version and per-package CHANGELOG.md files
+- [ ] Generate new SDK version and per-package CHANGELOG.md files.
- Use `--conventional-prerelease` instead of `--conventional-graduate` if you just want to generate a dev release.
+ To generate a `$VERSION-$PRE.$N` dev release that will not be accidentally selected by downstream package.json files, replace `--conventional-graduate` below with `--conventional-prerelease --preid "$PRE"` (example: `--conventional-prerelease --preid u14`).
These instructions will:
-
- modify the `package.json` (to bump the version) of every package
which saw changes since the previous release, or whose dependencies
change because of other packages being bumped (in practice this
@@ -107,7 +205,7 @@ in this branch. The release tags will be human-meaningful, the release branch ne
- create a `$package@$version` git tag for every package that changed,
including a special `@agoric/sdk@$n` "SDK version" tag that (among other
things) CI will use for tagging a Docker image;
- - create a special `v$version` tag derived from the `@agoric/cosmos@$version`
+ - create a special `v$version` git tag derived from the `@agoric/cosmos@$version`
tag for
[Go's opinionated reference scheme](https://go.dev/ref/mod#version-queries)
as used in e.g. `go get github.com/Agoric/agoric-sdk@$version`.
@@ -126,23 +224,21 @@ in this branch. The release tags will be human-meaningful, the release branch ne
scripts/have-news HEAD^ > have-news.md
```
-- [ ] Create the release PR.
-
- The above should have pushed state to GitHub to let you create a
- new PR to merge the release branch back to the main branch. The PR
- name should follow the convention of previous releases, which is
- currently `chore(release): publish _release_label_`. Paste
- `have-news.md` as the description of the PR. Follow the example
- of previous releases for any other details of the PR.
+- [ ] Create the release PR:
+ - Source branch: the [timestamped release branch](#user-content-release-branch)
+ - Target branch: the [_**base branch**_](#assign-release-parameters)
+ - Title: "chore(release): publish [_**release short label**_](#assign-release-parameters)"
+ - Description: the contents of `have-news.md` from the previous step
+ - Labels
+ - `force:integration`
- (Note that the `have-news.md` file might be too large for a Git commit
- message if you've gone too long without making a release.)
+ Follow the example of previous releases for any other details of the PR.
- Creating this PR will also kick off the CI tests.
+ Creating this PR will initiate the CI tests.
- [ ] Build the NPM-installed SDK packages.
- While the above CI tests run, build the SDK:
+ While the previous step's CI tests run, build the SDK:
```sh
# Build all package generated files.
yarn install --force
@@ -155,7 +251,7 @@ in this branch. The release tags will be human-meaningful, the release branch ne
These steps cannot be undone, so be sure that you are ready to proceed.
In particular, be sure that you have waited for the release PR's CI tests
-to pass.
+to pass and for reviewer approval.
- [ ] Publish to NPM
```sh
@@ -165,20 +261,22 @@ to pass.
```
- [ ] Merge the release PR into the base branch.
+
**DO NOT REBASE OR SQUASH OR YOU WILL LOSE REFERENCES TO YOUR TAGS.**
- You may use the "Merge" button directly instead of automerge.
-- [ ] DO NOT change your local git environment to the base branch - keep
+ You may use the GitHub "Merge" button directly instead of automerge.
+
+- [ ] **DO NOT** change your local git environment to the base branch - keep
it on the release branch for the following steps.
-- [ ] Publish the released package tags
+- [ ] Publish the released package tags
```sh
# Publish the released package tags.
./scripts/get-released-tags git push origin
```
- This will push all the tags created in the "Generate new SDK version" step
- above.
+ This will push all the tags created in the above
+ ["Generate new SDK version" step](#user-content-generate-sdk-version).
- [ ] (Optional) Publish an NPM distribution tag
@@ -205,18 +303,18 @@ to pass.
- [ ] Push release labels as tags
- Perform the following for each \ that we will use to label this release.
-
+ Perform the following for each [_**release label**_](#assign-release-parameters):
```sh
- git tag
- git push origin
+ git tag
+ git push origin
```
-- [ ] Confirm that a Docker image for SDK version $SDKVER has been published to the
+- [ ] Confirm that a Docker image for SDK version [$SDKVER](#user-content-generate-sdk-version)
+ has been published to the
[agoric-sdk Container registry](https://github.com/Agoric/agoric-sdk/pkgs/container/agoric-sdk).
Note that this is triggered by pushing the `@agoric/sdk@$n` tag in the
- "Publish the released package tags" step and may take a while.
+ ["Publish the released package tags" step](#user-content-publish-tags) and may take a while.
You can observe workflow initiation and progress at
[Build release Docker Images](https://github.com/Agoric/agoric-sdk/actions/workflows/docker.yml).
@@ -224,17 +322,18 @@ to pass.
Follow the [GitHub
instructions](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
- ) and use previous releases as a template. This uses the
- validator-oriented release description.
+ ) and use previous releases as a template. The release description should include the
+ [_**validator oriented release description**_](#describe-the-release).
### Cleanup
-- [ ] Review recent changes in the base branch for anything that
- should be merged into its ancestors, all the way up to master. This
- should include the changes to CHANGELOG.md.
+- [ ] Remove the repository clone you created for this release, so you don't accidentally reuse it.
-- [ ] Remove the repository clone you created for this release,
- so you don't accidentally reuse it.
+- [ ] Open an [agoric-3-proposals](https://github.com/Agoric/agoric-3-proposals) PR to represent
+ the mainnet proposal corresponding with the upgrade.
+ Include in the proposal files tests copied from this release's **a3p-integration/proposals**,
+ with the proposal directory's **package.json** `agoricProposal` updated to include `releaseNotes`
+ and `upgradeInfo` matching the mainnet proposal.
## More subtlety
diff --git a/scripts/gen-rebase-todo.sh b/scripts/gen-rebase-todo.sh
new file mode 100755
index 00000000000..a13842a5a1c
--- /dev/null
+++ b/scripts/gen-rebase-todo.sh
@@ -0,0 +1,198 @@
+#! /bin/bash
+set -ueo pipefail
+declare -r USAGE="Usage: $0
+
+Capture merge-inclusive history of the current branch since
+and output it as a todo list that will recreate it on another branch
+when used to overwrite the \"noop\" contents of \`git rebase -i HEAD\`.
+
+This is useful for cherry-picking onto a release branch.
+"
+usage() {
+ [ -n "$1" ] && printf '%s\n' "$1"
+ printf '%s' "$USAGE"
+ exit 64
+}
+case "${1-}" in
+ --help) usage ;;
+ -*) usage 1>&2 "Error: unknown option \"$1\"" ;;
+ '') usage 1>&2 "Error: missing commit" ;;
+esac
+
+since="$1"
+
+# Get an an initial todo list from `git rebase -i` by using a fake
+# editor that echoes the file to standard output and then trucates it to
+# ensure that no rebase actually happens.
+# Filter the resulting standard error to remove expected "hint" and
+# "nothing to do" lines, and send the todo list through a transformation
+# pipeline.
+{
+ fake_editor='cat &1 1>&3 \
+ | sed -E '/^hint:|^error: nothing to do$/d'
+} 3>&1 1>&2 \
+ | {
+ # Remove any final block of instruction comments (by appending
+ # blanks/comments to hold space and flushing that before other lines,
+ # minus the line feed before the first appended content).
+ sed -nE '/^$|^#/ { H; d; }; H; s/.*//; x; s/^[[:cntrl:]]//; p;'
+ } \
+ | {
+ # Restructure branch-specific blocks:
+ # * Move an isolated initial `label` into the first block (and
+ # remove a following no-op `reset`).
+ # * When a block starts with `reset` + `merge`, move them into
+ # the previous block.
+ # * Add blank lines at the beginning and end
+ # (for later block detection).
+ awk '
+ BEGIN {
+ printf "\n";
+ }
+ NR == 1 && match($0, /^label /) {
+ firstBlockPrefix = $0 "\n";
+ label = substr($0, RLENGTH + 1, length($0) - RLENGTH);
+ noopReset = "reset " label;
+ next;
+ }
+ firstBlockPrefix != "" && $0 == noopReset {
+ next;
+ }
+ /^$|^# .*[Bb]ranch .*/ {
+ blockHeader = blockHeader $0 "\n";
+ next;
+ }
+ blockHeader != "" {
+ if (cmdBuf == "" && match($0, /^reset /)) {
+ cmdBuf = $0 "\n";
+ next;
+ } else if (cmdBuf != "" && match($0, /^merge /)) {
+ printf "%s%s", cmdBuf, $0 "\n";
+ cmdBuf = "";
+ next;
+ }
+ }
+ {
+ printf "%s%s%s%s", blockHeader, firstBlockPrefix, cmdBuf, $0 "\n"
+ blockHeader = "";
+ firstBlockPrefix = "";
+ cmdBuf = "";
+ }
+ END {
+ printf "%s%s%s\n", blockHeader, firstBlockPrefix, cmdBuf;
+ }
+ '
+ } \
+ | {
+ # Rename each label that receives `merge` in a block to
+ # "base-$branchName", and prefix each source of such merges with a
+ # PR reference to "pr-####--...".
+ awk '
+ function addLabel(label) {
+ if (++labels[label] == 1) return;
+ print "duplicate label: " label > "/dev/stderr";
+ exit 1;
+ }
+ function ere_escape(s) {
+ gsub(/[^a-zA-Z0-9_-]/, "[&]", s);
+ gsub(/[[][\\][]]/, "\\\\", s);
+ gsub(/[[]\^[]]/, "\\^", s);
+ return s;
+ }
+ $0 == "" && branch != "" && pr != "" {
+ re = "\n# [Bb]ranch " ere_escape(branch) "\n";
+ if (match(buf, re)) {
+ commentTail = substr(buf, RSTART + 3, RLENGTH - 4);
+ buf = sprintf("%s\n# %s\n%s",
+ substr(buf, 1, RSTART - 1),
+ sprintf("PR #%s %s", pr, commentTail),
+ substr(buf, RSTART + RLENGTH, length(buf) - RSTART - RLENGTH + 1));
+ }
+ newLabel = sprintf("pr-%s--%s", pr, branch);
+ addLabel(newLabel);
+ renames[++renameCount] = branch SUBSEP newLabel;
+ }
+ match($0, /^$|^# .*[Bb]ranch /) {
+ branch = substr($0, RLENGTH + 1, length($0) - RLENGTH);
+ pr = "";
+ }
+ branch != "" && match($0, /^merge /) && match(prev, /^reset /) {
+ onto = substr(prev, RLENGTH + 1, length($0) - RLENGTH);
+ sub(/[[:space:]].*/, "", onto);
+ newOnto = "base-" branch;
+ addLabel(newOnto);
+ renames[++renameCount] = onto SUBSEP newOnto;
+
+ if (!match($0, /(gh-|#)[0-9]+/)) {
+ pr = "";
+ } else {
+ pr = substr($0, RSTART, RLENGTH);
+ sub(/^[^0-9]*/, "", pr);
+ }
+ }
+ /^label / {
+ addLabel(substr($0, RLENGTH + 1, length($0) - RLENGTH));
+ }
+ {
+ buf = buf $0 "\n";
+ prev = $0;
+ }
+ END {
+ # For "last-wins" semantics, apply renames in reverse order.
+ for (i = renameCount; split(renames[i], pair, SUBSEP); i--) {
+ len1 = length(pair[1]);
+ j = split("label reset merge", rebaseCmds, " ");
+ for (; cmd = rebaseCmds[j]; j--) {
+ newBuf = "";
+ # "reset" and "merge" are followed by a label,
+ # but "merge" usually has an intervening "-C/-c" and commit id.
+ seekLine = sprintf("\n%s ", cmd);
+ if (cmd != "merge") seekLine = seekLine pair[1];
+ while (k = index(buf, seekLine)) {
+ # Consume everything before the match.
+ newBuf = newBuf substr(buf, 1, k - 1);
+ buf = substr(buf, k, length(buf) - (k - 1));
+
+ # Expand the match as needed.
+ len = length(seekLine);
+ if (cmd == "merge") {
+ match(buf, /^\nmerge( -[Cc] [^ \n]*)? [^ \n]*/);
+ if (RLENGTH) len = RLENGTH;
+ }
+
+ # Define the replacement (or lack thereof if the match
+ # does not actually reference the renamed label).
+ r = substr(buf, 1, len);
+ if (len > len1 \
+ && substr(buf, len - len1, len1 + 1) == " " pair[1] \
+ && match(substr(buf, len + 1, 1), /[ \n]/)) {
+
+ r = substr(buf, 1, len - len1) pair[2];
+ }
+
+ # Apply the replacement and consume the match.
+ newBuf = newBuf r;
+ buf = substr(buf, len + 1, length(buf) - len);
+ }
+ buf = newBuf buf;
+ }
+ }
+ printf "%s", buf;
+ }
+ '
+ } \
+ | {
+ # Remove leading and trailing blank lines.
+ awk '
+ $0 != "" {
+ active = 1;
+ for (; blanks > 0; blanks--) print "";
+ print;
+ }
+ $0 == "" && active {
+ blanks++;
+ }
+ '
+ }
diff --git a/scripts/get-released-tags b/scripts/get-released-tags
index 32a2caa4f08..2a0374ea45d 100755
--- a/scripts/get-released-tags
+++ b/scripts/get-released-tags
@@ -1,10 +1,11 @@
#! /bin/sh
-# Invokes `echo` or a specified other command with a list of "...@" and
-# "v" tags that include the HEAD commit, specifically handling
-# "@agoric/sdk@" tags into a dedicated invocation for CI convenience.
# Usage: $0 [ [...]]
-cmd=${1+"$@"}
-cmd=${cmd:-echo}
+# Invokes `echo` or a specified other command with a list of "...@" and
+# "v" tags associated with the HEAD commit, specifically handling
+# "@agoric/sdk@" tags in a dedicated invocation for CI convenience.
+# Fails if either expected tag category is empty.
+cmd=${1:-echo}
+[ $# -gt 0 ] && shift
sdkTags=
otherTags=
for tag in $(git tag -l --contains HEAD | grep -E '(@|^v)[0-9.]+(-[^.]*\.[0-9.]+)?$'); do
@@ -14,5 +15,13 @@ for tag in $(git tag -l --contains HEAD | grep -E '(@|^v)[0-9.]+(-[^.]*\.[0-9.]+
esac
done
+errors=
+[ -z "$sdkTags" ] && errors="$(printf '%s%s\n' "$errors" 'No @agoric/sdk tags!')"
+[ -z "$otherTags" ] && errors="$(printf '%s%s\n' "$errors" 'No non-@agoric/sdk tags!')"
+if [ -n "$errors" ]; then
+ echo 1>&2 "$errors"
+ exit 1
+fi
+
# Push the SDK tag separately so that it can trigger CI.
-$cmd $otherTags && $cmd $sdkTags
+"$cmd" "$@" $otherTags && "$cmd" "$@" $sdkTags