| @@ -0,0 +1,124 @@ |
| | # Keeps one pull open that releases the client, as release-please and |
| | # changesets' bot do: each day, when main has change files, it runs `knope |
| | # release` on main's tip and force-pushes the commit to `release/next`, |
| | # opening a pull titled `Release <version>`, or bringing the open one up |
| | # to date. Queueing that pull is the release: once it lands, release.yml |
| | # publishes the version and tags it. Nothing is queued here, so when to |
| | # release stays the owner's call. |
| | # |
| | # The version is worked out here and given to knope with |
| | # --override-version: a change file's `minor` or `major` bumps 0.x's minor, |
| | # where knope would bump the patch, and a `patch` the patch; from 1.0 on, |
| | # each bumps its own part. A pull already holding main's change files, and |
| | # still merging with main, is left alone, so its checks run again only |
| | # when what it releases changes. The open pull is found by its title, |
| | # `Release x.y.z` by the owner, so one cut by hand is taken over, its head |
| | # pointed at release/next. |
| | # |
| | # Ask for it at once with `knotless run rerun <repo> --ref refs/heads/main |
| | # --workflow release-pull`. Asked for on any other branch, it makes the |
| | # release commit there and prints the pull's body, pushing nothing. |
| | # |
| | # RELEASE_PASSWORD is release.yml's app password of the owner's, granted |
| | # to main alone. |
| | |
| | # Its secrets are on ci.knotless.dev alone, the runner that runs no one |
| | # else's code (deploy/runner-host/README.md, The trusted runner). |
| | runners: [ci.knotless.dev] |
| | on: |
| | schedule: |
| | - cron: '0 6 * * *' |
| | asked: {refs: [refs/heads/*]} |
| | image: node:24.22.1 |
| | secrets: [RELEASE_PASSWORD] |
| | env: |
| | REPO: knotless://chadtmiller.com/knotless |
| | OWNER: chadtmiller.com |
| | BRANCH: release/next |
| | KNOTLESS_APPVIEW: https://knotless.dev |
| | KNOPE_VERSION: 0.23.2 |
| | KNOPE_SHA256: c64f6281e012fc8e046ebd6f30be76c583e88b9ad55b00c7b1809b030db92eee |
| | steps: |
| | - name: changes |
| | run: | |
| | set -- .changeset/*.md |
| | if [ ! -e "$1" ]; then |
| | echo "no change files at $KNOTLESS_RUN_REF: nothing to release" |
| | touch ~/.done |
| | fi |
| | - name: tools |
| | run: | |
| | [ ! -e ~/.done ] || exit 0 |
| | cd /tmp |
| | curl -fsSLO "https://github.com/knope-dev/knope/releases/download/knope/v$KNOPE_VERSION/knope-x86_64-unknown-linux-musl.tgz" |
| | echo "$KNOPE_SHA256 knope-x86_64-unknown-linux-musl.tgz" | sha256sum -c - |
| | tar -xzf knope-x86_64-unknown-linux-musl.tgz |
| | install knope-x86_64-unknown-linux-musl/knope /usr/local/bin/ |
| | curl -fsSL https://knotless.dev/install.sh | KNOTLESS_INSTALL_DIR=/usr/local/bin sh |
| | - name: release commit |
| | run: | |
| | [ ! -e ~/.done ] || exit 0 |
| | set -- .changeset/*.md |
| | count=$# |
| | bumps=$(sed -n 's/^default: *//p' "$@") |
| | current=$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1) |
| | IFS=. read -r major minor patch <<EOF |
| | $current |
| | EOF |
| | if echo "$bumps" | grep -qx major && [ "$major" != 0 ]; then |
| | version=$((major + 1)).0.0 |
| | elif echo "$bumps" | grep -qxE 'major|minor'; then |
| | version=$major.$((minor + 1)).0 |
| | else |
| | version=$major.$minor.$((patch + 1)) |
| | fi |
| | echo "$version" > ~/.version |
| | knope release --override-version "$version" |
| | git -c user.name=knotless -c user.email=knotless@knotless.invalid commit -aqm "Release $version" |
| | at=$(echo "$KNOTLESS_RUN_SHA" | cut -c1-12) |
| | notes=$(awk -v v="$version" '/^## / { on = ($2 == v); next } on' CHANGELOG.md) |
| | cat > ~/.body <<EOF |
| | Releases knotless $version, from the $count change files on main: its changelog is below. Queue this pull to release it; once it lands, release.yml publishes the version and tags it. release-pull.yml keeps it up to date as change files land. |
| | |
| | <details> |
| | <summary>release-pull.yml</summary> |
| | |
| | ## What changes |
| | |
| | knotless $version, as \`knope release --override-version $version\` makes it from main at $at: the workspace version from $current to $version in Cargo.toml and the crates' Cargo.lock entries, the version's CHANGELOG.md section, and the change files removed. |
| | |
| | $notes |
| | |
| | ## Why |
| | |
| | Users get the client side of main's changes only from a release. A 0.x minor change bumps the minor here, where knope alone would bump the patch. |
| | |
| | ## How it was checked |
| | |
| | The build is left to CI. \`client.minimum\` is left as it is: raise it by hand if a release in between harms repositories. |
| | |
| | </details> |
| | EOF |
| | cat ~/.body |
| | - name: pull |
| | on: {refs: [refs/heads/main]} |
| | run: | |
| | [ ! -e ~/.done ] || exit 0 |
| | version=$(cat ~/.version) |
| | export KNOTLESS_IDENTIFIER="$OWNER" KNOTLESS_PASSWORD="$RELEASE_PASSWORD" |
| | pull=$(knotless pull list "$REPO" -q "is:pull state:open author:$OWNER Release" | |
| | awk -F '\t' '$4 ~ /^Release [0-9]+\.[0-9]+\.[0-9]+$/ { print $3; exit }') |
| | if [ -n "$pull" ] && git fetch -q "$REPO" "refs/heads/$BRANCH" && |
| | [ "$(git rev-parse "FETCH_HEAD^:.changeset")" = "$(git rev-parse "$KNOTLESS_RUN_SHA:.changeset")" ] && |
| | git merge-tree --write-tree "$KNOTLESS_RUN_SHA" FETCH_HEAD > /dev/null; then |
| | echo "$pull releases main's change files already and merges with main: nothing to push" |
| | exit 0 |
| | fi |
| | git push -q --force "$REPO" "HEAD:refs/heads/$BRANCH" |
| | if [ -z "$pull" ]; then |
| | knotless pull create "$REPO" main "$REPO" "$BRANCH" "Release $version" -m - < ~/.body |
| | else |
| | knotless pull retarget "$REPO" "$pull" --head "$BRANCH" |
| | knotless pull edit "$REPO" "$pull" --title "Release $version" -m - < ~/.body |
| | echo "updated $pull" |
| | fi |