diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..fe9232ffd1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,126 @@ +name: Publish (Forge 7) + +on: + push: + branches: + - main + +jobs: + check-release-criteria: + name: Check Release Criteria + runs-on: ubuntu-latest + outputs: + should_release: ${{ steps.check.outputs.should_release }} + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + fetch-depth: 2 + + - name: Check release criteria + id: check + run: | + set -e + + # Get commit message title and body + COMMIT_TITLE=$(git log -1 --pretty=%s) + COMMIT_BODY=$(git log -1 --pretty=%b) + + echo "Commit title: $COMMIT_TITLE" + echo "Commit body: $COMMIT_BODY" + + # Check 1: Commit title matches "chore: bump version to ..." + if ! echo "$COMMIT_TITLE" | grep -qE '^chore: bump version to .+$'; then + echo "Commit title does not match 'chore: bump version to ...'" + echo "should_release=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "✓ Commit title matches pattern" + + # Check 2: Commit body contains "" + if ! echo "$COMMIT_BODY" | grep -qF ''; then + echo "Commit body does not contain ''" + echo "should_release=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "✓ Commit body contains trigger" + + # Check 3: Only package.json or lerna.json files were changed + CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD) + echo "Changed files:" + echo "$CHANGED_FILES" + + for file in $CHANGED_FILES; do + if [[ ! "$file" =~ ^(.*/)?package\.json$ ]] && [[ ! "$file" =~ ^(.*/)?lerna\.json$ ]]; then + echo "File '$file' is not a package.json or lerna.json" + echo "should_release=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + done + echo "✓ Only package.json and lerna.json files changed" + + # Check 4: Only "version" field was changed in each file + for file in $CHANGED_FILES; do + # Get the old and new versions of the file + OLD_CONTENT=$(git show HEAD~1:"$file" 2>/dev/null || echo '{}') + NEW_CONTENT=$(git show HEAD:"$file") + + # Remove the "version" field from both and compare + OLD_WITHOUT_VERSION=$(echo "$OLD_CONTENT" | jq 'del(.version)') + NEW_WITHOUT_VERSION=$(echo "$NEW_CONTENT" | jq 'del(.version)') + + if [ "$OLD_WITHOUT_VERSION" != "$NEW_WITHOUT_VERSION" ]; then + echo "File '$file' has changes other than the version field" + echo "Diff (excluding version):" + diff <(echo "$OLD_WITHOUT_VERSION" | jq -S .) <(echo "$NEW_WITHOUT_VERSION" | jq -S .) || true + echo "should_release=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + done + echo "✓ Only version fields were changed" + + echo "All criteria met - proceeding with release" + echo "should_release=true" >> "$GITHUB_OUTPUT" + + publish: + name: Publish Release + runs-on: ubuntu-latest + needs: check-release-criteria + if: needs.check-release-criteria.outputs.should_release == 'true' + environment: npm-trusted-publisher + permissions: + contents: write + id-token: write + steps: + - name: Checkout + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + + - name: Install Node.js + uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.0.1 + with: + node-version-file: '.nvmrc' + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: yarn install --immutable + + - name: Build + run: yarn build + + - name: Publish + run: lerna publish from-package --force-publish --no-changelog --exact --yes + + - name: Get version from lerna.json + id: version + run: | + VERSION=$(jq -r '.version' lerna.json) + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Get GitHub app token + id: secret-service + uses: electron/secret-service-action@3476425e8b30555aac15b1b7096938e254b0e155 # v1.0.0 + + - name: Create GitHub release + env: + GH_TOKEN: ${{ fromJSON(steps.secret-service.outputs.secrets).GITHUB_TOKEN }} + run: gh release create "v${{ steps.version.outputs.version }}" --target ${{ github.sha }} --generate-notes --prerelease diff --git a/package.json b/package.json index 3741e2ec25..88892fd78c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "build": "tsc -b packages && ts-node tools/test-dist", "build:watch": "tsc -b packages --watch", "docs": "yarn build && typedoc", - "lerna:publish": "lerna publish --force-publish --conventional-commits --no-changelog --exact", + "lerna:version": "./tools/version.sh", "lint:js": "prettier --check . --experimental-cli && eslint . --cache", "lint:markdown": "electron-markdownlint \"**/*.md\"", "lint:markdown-js": "electron-lint-markdown-standard --root . --ignore-path .markdownlintignore --semi \"**/*.md\"", diff --git a/tools/version.sh b/tools/version.sh new file mode 100755 index 0000000000..fb8f28a2b0 --- /dev/null +++ b/tools/version.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +set -e + +if [ -n "$(git status --porcelain)" ]; then + echo "Error: Working directory is not clean. Please commit or stash your changes before running lerna:version." + exit 1 +fi + +echo "Running lerna version..." +lerna version \ + --force-publish \ + --no-changelog \ + --conventional-commits \ + --exact \ + --no-git-tag-version \ + --no-push + +# Releaser may decline to apply version changes. Exit early in that case. +if [ -z "$(git status --porcelain)" ]; then + echo "No version changes were made. Exiting." + exit 0 +fi + +BRANCH_NAME="v7/$(date +'%y%m%d-%I-%M')" +echo "Creating branch: $BRANCH_NAME" +git checkout -b "$BRANCH_NAME" + +echo "Committing changes..." +git commit -a -m 'chore: version bump' -m '' + +echo "Version bump complete! Branch $BRANCH_NAME created and changes committed." \ No newline at end of file