Skip to content

chore(main): release 0.4.0 #3

chore(main): release 0.4.0

chore(main): release 0.4.0 #3

Workflow file for this run

name: Release
on:
pull_request:
branches: [main]
types: [closed]
workflow_dispatch:
inputs:
ref:
description: Git ref containing the released package version
required: true
default: main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.merge_commit_sha || inputs.ref }}
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
jobs:
release:
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'release-please--'))
runs-on: ubuntu-latest
timeout-minutes: 30
env:
VITE_CLERK_OAUTH_CLIENT_ID: ${{ vars.VITE_CLERK_OAUTH_CLIENT_ID }}
VITE_CLERK_OAUTH_ISSUER: ${{ vars.VITE_CLERK_OAUTH_ISSUER }}
VITE_WEB_APP_URL: ${{ vars.VITE_WEB_APP_URL }}
GH_TOKEN: ${{ github.token }}
steps:
- name: Checkout released source
uses: actions/checkout@v4
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || github.event.pull_request.merge_commit_sha }}
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Validate release configuration
id: version
run: |
for name in \
VITE_CLERK_OAUTH_CLIENT_ID \
VITE_CLERK_OAUTH_ISSUER \
VITE_WEB_APP_URL
do
if [ -z "${!name}" ]; then
echo "Required release variable is missing: $name" >&2
exit 1
fi
done
package_version="$(node -p "require('./package.json').version")"
manifest_version="$(node -p "require('./.release-please-manifest.json')['.']")"
if [ "$package_version" != "$manifest_version" ]; then
echo "package.json version ${package_version} does not match Release Please version ${manifest_version}." >&2
exit 1
fi
echo "VERSION=${package_version}" >> "$GITHUB_ENV"
echo "TAG=v${package_version}" >> "$GITHUB_ENV"
echo "RELEASE_SHA=$(git rev-parse HEAD)" >> "$GITHUB_ENV"
echo "version=${package_version}" >> "$GITHUB_OUTPUT"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Verify release source
run: |
pnpm lint
pnpm test
- name: Build release packages
run: pnpm package
- name: Verify release packages
run: |
for package in \
"artifacts/memos-web-clipper-chromium-v${VERSION}.zip" \
"artifacts/memos-web-clipper-chrome-v${VERSION}.zip" \
"artifacts/memos-web-clipper-edge-v${VERSION}.zip" \
"artifacts/memos-web-clipper-firefox-v${VERSION}.zip"
do
unzip -tq "$package"
done
cmp \
"artifacts/memos-web-clipper-chrome-v${VERSION}.zip" \
"artifacts/memos-web-clipper-edge-v${VERSION}.zip"
verify_stage="$(mktemp -d)"
trap 'rm -rf "$verify_stage"' EXIT
unzip -p "artifacts/memos-web-clipper-chromium-v${VERSION}.zip" manifest.json > "$verify_stage/chromium.json"
unzip -p "artifacts/memos-web-clipper-chrome-v${VERSION}.zip" manifest.json > "$verify_stage/chrome.json"
unzip -p "artifacts/memos-web-clipper-edge-v${VERSION}.zip" manifest.json > "$verify_stage/edge.json"
unzip -p "artifacts/memos-web-clipper-firefox-v${VERSION}.zip" manifest.json > "$verify_stage/firefox.json"
node --input-type=module - "$verify_stage" "$VERSION" <<'NODE'
import { readFileSync } from "node:fs";
import { join } from "node:path";
const [stage, version] = process.argv.slice(2);
const readManifest = (name) => JSON.parse(readFileSync(join(stage, `${name}.json`), "utf8"));
const chromium = readManifest("chromium");
const chrome = readManifest("chrome");
const edge = readManifest("edge");
const firefox = readManifest("firefox");
if (chromium.version !== version || !chromium.key || chromium.update_url) {
throw new Error("The manual Chromium package has the wrong version, identity key, or update URL.");
}
for (const [name, manifest] of [["Chrome", chrome], ["Edge", edge]]) {
if (manifest.version !== version || manifest.key || manifest.update_url) {
throw new Error(`${name} store package has the wrong version or store-owned identity fields.`);
}
}
if (
firefox.version !== version ||
firefox.key ||
firefox.update_url ||
firefox.browser_specific_settings?.gecko?.id !== "web-clipper@usememos.com" ||
!firefox.background?.scripts?.length ||
firefox.background?.service_worker
) {
throw new Error("The Firefox store package has invalid release metadata.");
}
NODE
- name: Generate checksums and release notes
run: |
(
cd artifacts
sha256sum \
"memos-web-clipper-chromium-v${VERSION}.zip" \
"memos-web-clipper-chrome-v${VERSION}.zip" \
"memos-web-clipper-edge-v${VERSION}.zip" \
"memos-web-clipper-firefox-v${VERSION}.zip" \
> SHA256SUMS
)
awk '
/^## \[/ {
if (found) exit
found = 1
}
found { print }
' CHANGELOG.md > release-notes.md
if [ ! -s release-notes.md ]; then
echo "Release ${VERSION}" > release-notes.md
fi
- name: Publish immutable release with complete assets
run: |
assets=(
"artifacts/memos-web-clipper-chromium-v${VERSION}.zip"
"artifacts/memos-web-clipper-chrome-v${VERSION}.zip"
"artifacts/memos-web-clipper-edge-v${VERSION}.zip"
"artifacts/memos-web-clipper-firefox-v${VERSION}.zip"
"artifacts/SHA256SUMS"
)
release_state="$(gh release view "$TAG" --json isDraft --jq '.isDraft' 2>/dev/null || true)"
if [ "$release_state" = "false" ]; then
published_sha="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${TAG}" --jq '.sha')"
if [ "$published_sha" != "$RELEASE_SHA" ]; then
echo "Published release $TAG points to $published_sha instead of $RELEASE_SHA." >&2
exit 1
fi
if ! diff -u \
<(printf '%s\n' "${assets[@]##*/}" | sort) \
<(gh release view "$TAG" --json assets --jq '.assets[].name' | sort)
then
echo "Published release $TAG does not contain the expected immutable assets." >&2
exit 1
fi
echo "Release $TAG is already published with the expected commit and assets."
exit 0
fi
if [ "$release_state" = "true" ]; then
gh release edit "$TAG" --title "$TAG" --notes-file release-notes.md
gh release upload "$TAG" "${assets[@]}" --clobber
else
gh release create "$TAG" \
--draft \
--target "$RELEASE_SHA" \
--title "$TAG" \
--notes-file release-notes.md
gh release upload "$TAG" "${assets[@]}"
fi
gh release edit "$TAG" --draft=false --latest
- name: Mark release pull request complete
if: github.event_name == 'pull_request'
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
labels="$(gh pr view "$PR_NUMBER" --json labels --jq '.labels[].name')"
edit_args=()
if printf '%s\n' "$labels" | grep -Fxq "autorelease: pending"; then
edit_args+=(--remove-label "autorelease: pending")
fi
if ! printf '%s\n' "$labels" | grep -Fxq "autorelease: tagged"; then
edit_args+=(--add-label "autorelease: tagged")
fi
if [ "${#edit_args[@]}" -gt 0 ]; then
gh pr edit "$PR_NUMBER" "${edit_args[@]}"
fi