Skip to content
Merged
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
69 changes: 69 additions & 0 deletions .github/workflows/release-zed.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: Release Zed extension

# Merging a Zed release PR bumps this file; the run tags whatever version main carries that has no tag yet.
on:
push:
branches: [main]
paths: [crates/zed-extension/extension.toml]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: release-zed
cancel-in-progress: false

jobs:
tag:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Resolve tag
id: tag
working-directory: crates/zed-extension
run: |
crate_version=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].version')
extension_version=$(sed -n 's/^version = "\(.*\)"/\1/p' extension.toml)
[ "$crate_version" = "$extension_version" ] ||
{ echo "::error::Cargo.toml $crate_version != extension.toml $extension_version"; exit 1; }

tag="zed-v$crate_version"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
# ls-remote exits 2 when the tag is absent; any other failure must not pass for "absent".
status=0
git ls-remote --exit-code --tags origin "refs/tags/$tag" > /dev/null || status=$?
case $status in
0) echo "::notice::$tag already exists; nothing to release"; echo "due=false" >> "$GITHUB_OUTPUT" ;;
2) echo "due=true" >> "$GITHUB_OUTPUT" ;;
*) exit "$status" ;;
esac

# A version bump that did not come through `just bump-zed-version` stops here instead of tagging.
- name: Verify commit is a merged release PR
if: steps.tag.outputs.due == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.tag.outputs.tag }}
run: |
gh api "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/pulls" |
jq -e --arg tag "$TAG" 'any(.[];
.merged_at != null
and .head.repo.full_name == .base.repo.full_name
and .head.ref == "chore/release-zed-\($tag | ltrimstr("zed-v"))"
and .title == "chore(zed): release \($tag | ltrimstr("zed-"))")' > /dev/null ||
{ echo "::error::$GITHUB_SHA is not a merged chore/release-${TAG#zed-v} PR titled \"chore(zed): release ${TAG#zed-}\""; exit 1; }

- name: Create tag
if: steps.tag.outputs.due == 'true'
run: gh api "repos/$GITHUB_REPOSITORY/git/refs" -f ref="refs/tags/$TAG" -f sha="$GITHUB_SHA"
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.tag.outputs.tag }}
76 changes: 64 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,32 +1,69 @@
name: Release

# Merging a release PR bumps this file; the run releases whatever version main carries that has no tag yet.
on:
push:
tags: ["v*"]
branches: [main]
paths: [packages/css-var-kit/package.json]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: release
cancel-in-progress: false

env:
CARGO_TERM_COLOR: always

jobs:
# Every publish below trusts the tag, so a tag that is off main or ahead of the versions stops here.
verify:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
tag: ${{ steps.tag.outputs.tag }}
due: ${{ steps.tag.outputs.due }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false

- name: Verify tag is on main
- name: Resolve tag
id: tag
run: |
git fetch --quiet origin main
git merge-base --is-ancestor HEAD FETCH_HEAD ||
{ echo "::error::tag $GITHUB_REF_NAME is not reachable from main"; exit 1; }
tag="v$(node -p "require('./packages/css-var-kit/package.json').version")"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
# ls-remote exits 2 when the tag is absent; any other failure must not pass for "absent".
status=0
git ls-remote --exit-code --tags origin "refs/tags/$tag" > /dev/null || status=$?
case $status in
0) echo "::notice::$tag already exists; nothing to release"; echo "due=false" >> "$GITHUB_OUTPUT" ;;
2) echo "due=true" >> "$GITHUB_OUTPUT" ;;
*) exit "$status" ;;
esac

# A version bump that did not come through `just bump-version` stops here instead of releasing.
- name: Verify commit is a merged release PR
if: steps.tag.outputs.due == 'true'
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.tag.outputs.tag }}
run: |
gh api "repos/$GITHUB_REPOSITORY/commits/$GITHUB_SHA/pulls" |
jq -e --arg tag "$TAG" 'any(.[];
.merged_at != null
and .head.repo.full_name == .base.repo.full_name
and .head.ref == "chore/release-\($tag[1:])"
and .title == "chore: release \($tag)")' > /dev/null ||
{ echo "::error::$GITHUB_SHA is not a merged chore/release-${TAG#v} PR titled \"chore: release $TAG\""; exit 1; }

- name: Verify tag matches package versions
env:
TAG: ${{ steps.tag.outputs.tag }}
run: |
set -o pipefail
{
Expand All @@ -40,10 +77,11 @@ jobs:
'
cargo metadata --format-version 1 --no-deps |
jq -r '.packages[] | select(.name == "css-var-kit") | "Cargo.toml \(.version)"'
} | awk -v tag="${GITHUB_REF_NAME#v}" '$NF != tag { print "::error::" $0 " != " tag; failed = 1 } END { exit failed }'
} | awk -v tag="${TAG#v}" '$NF != tag { print "::error::" $0 " != " tag; failed = 1 } END { exit failed }'

build:
needs: verify
if: needs.verify.outputs.due == 'true'
strategy:
matrix:
include:
Expand Down Expand Up @@ -100,8 +138,21 @@ jobs:
name: ${{ matrix.npm-pkg }}
path: packages/${{ matrix.npm-pkg }}/${{ matrix.binary }}

# Tags are immutable, so tagging only after the builds pass keeps a broken build from burning its version.
tag:
needs: [verify, build]
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Create tag
run: gh api "repos/$GITHUB_REPOSITORY/git/refs" -f ref="refs/tags/$TAG" -f sha="$GITHUB_SHA"
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.verify.outputs.tag }}

publish:
needs: build
needs: tag
runs-on: ubuntu-latest
permissions:
contents: read
Expand Down Expand Up @@ -170,7 +221,7 @@ jobs:
fi

publish-vscode:
needs: build
needs: tag
runs-on: ubuntu-latest
strategy:
matrix:
Expand Down Expand Up @@ -235,7 +286,7 @@ jobs:
path: packages/vscode/*.vsix

github-release:
needs: [build, publish-vscode]
needs: [verify, publish-vscode]
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -261,6 +312,7 @@ jobs:
# The notes come from the PRs merged since the previous tag, grouped by `.github/release.yml`;
# edit them on the release page afterwards if needed.
- name: Create GitHub Release
run: gh release create "$GITHUB_REF_NAME" --verify-tag --generate-notes dist/*
run: gh release create "$TAG" --verify-tag --generate-notes dist/*
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.verify.outputs.tag }}
21 changes: 3 additions & 18 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ package-jsons := "packages/css-var-kit/package.json \

zed-pkg := "crates/zed-extension"

# Bumps the version on a release branch cut from the latest main and opens its PR; without `level`, bumpp prompts for it.
# Bumps the version on a release branch cut from the latest main and opens its PR; merging it releases.
# Without `level`, bumpp prompts for it.
bump-version level="": _latest-main
#!/usr/bin/env sh
set -eu
Expand All @@ -28,15 +29,7 @@ bump-version level="": _latest-main
git push -u origin HEAD
gh pr create --fill --label skip-changelog

# Tags the merged release on main; the pushed tag triggers the release workflow.
push-tag: _latest-main
#!/usr/bin/env sh
set -eu
tag="v$(node -p "require('./packages/css-var-kit/package.json').version")"
git tag "$tag"
git push origin "$tag"

# Bumps the Zed extension version on a release branch cut from the latest main and opens its PR.
# Bumps the Zed extension version on a release branch cut from the latest main and opens its PR; merging it tags the release.
bump-zed-version level: _latest-main
#!/usr/bin/env sh
set -eu
Expand All @@ -54,14 +47,6 @@ bump-zed-version level: _latest-main
git push -u origin HEAD
gh pr create --fill --label skip-changelog

# Tags the merged Zed extension release on main.
push-zed-tag: _latest-main
#!/usr/bin/env sh
set -eu
tag="zed-v$(cd {{zed-pkg}} && cargo metadata --format-version 1 --no-deps | jq -r '.packages[0].version')"
git tag "$tag"
git push origin "$tag"

[private]
_latest-main:
#!/usr/bin/env sh
Expand Down
Loading