Skip to content

Commit 6352093

Browse files
feat: enhance release workflow with cherry-pick version sync to main (#53)
* chore(release): bump versions to 2.11.0 * feat: enhance release workflow with cherry-pick version sync to main * feat: add check to skip cherry-pick if version bump is already on default branch * feat: add checks to handle empty cherry-pick scenarios for version bumps
1 parent 9e1a930 commit 6352093

10 files changed

Lines changed: 274 additions & 21 deletions

File tree

.github/workflows/publish-release.yml

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ jobs:
3535
publish:
3636
runs-on: ubuntu-latest
3737
environment: release
38+
outputs:
39+
version: ${{ steps.version.outputs.version }}
40+
is_prerelease: ${{ steps.version.outputs.is_prerelease }}
41+
branch: ${{ steps.context.outputs.branch }}
3842
env:
3943
NX_DAEMON: "false"
4044

@@ -433,3 +437,172 @@ jobs:
433437
echo "| Pre-release | ${{ steps.version.outputs.is_prerelease }} |" >> "$GITHUB_STEP_SUMMARY"
434438
echo "| Branch | \`${{ steps.context.outputs.branch }}\` |" >> "$GITHUB_STEP_SUMMARY"
435439
echo "| Packages | All libs/* |" >> "$GITHUB_STEP_SUMMARY"
440+
441+
cherry-pick-version-to-main:
442+
needs: publish
443+
if: >
444+
inputs.dry_run != true &&
445+
needs.publish.outputs.is_prerelease == 'false'
446+
runs-on: ubuntu-latest
447+
permissions:
448+
contents: write
449+
pull-requests: write
450+
issues: write
451+
steps:
452+
- name: Checkout
453+
uses: actions/checkout@v4
454+
with:
455+
fetch-depth: 0
456+
token: ${{ secrets.GITHUB_TOKEN }}
457+
458+
- name: Check if latest semver
459+
id: check
460+
run: |
461+
set -euo pipefail
462+
VERSION="${{ needs.publish.outputs.version }}"
463+
464+
git fetch --tags
465+
466+
# Get all stable version tags, sort by semver, pick highest
467+
LATEST=$(git tag --list 'v*' \
468+
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
469+
| sort -V \
470+
| tail -1 \
471+
| sed 's/^v//')
472+
473+
echo "Released version: $VERSION"
474+
echo "Latest stable tag: $LATEST"
475+
476+
if [ "$VERSION" = "$LATEST" ]; then
477+
echo "is_latest=true" >> "$GITHUB_OUTPUT"
478+
echo "This is the latest version — will cherry-pick to main"
479+
else
480+
echo "is_latest=false" >> "$GITHUB_OUTPUT"
481+
echo "Skipping: v$VERSION is not the latest (v$LATEST is newer)"
482+
fi
483+
484+
- name: Configure git
485+
if: steps.check.outputs.is_latest == 'true'
486+
run: |
487+
git config user.name "github-actions[bot]"
488+
git config user.email "github-actions[bot]@users.noreply.github.com"
489+
490+
- name: Cherry-pick version bump to main
491+
if: steps.check.outputs.is_latest == 'true'
492+
env:
493+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
494+
run: |
495+
set -euo pipefail
496+
497+
VERSION="${{ needs.publish.outputs.version }}"
498+
RELEASE_BRANCH="${{ needs.publish.outputs.branch }}"
499+
DEFAULT_BRANCH="${{ github.event.repository.default_branch }}"
500+
501+
# Find the version bump commit on the release branch
502+
VERSION_COMMIT=$(git log "origin/$RELEASE_BRANCH" \
503+
--grep="chore(release): v${VERSION}" \
504+
--format="%H" -1)
505+
506+
if [ -z "$VERSION_COMMIT" ]; then
507+
echo "::warning::Could not find version bump commit for v${VERSION}"
508+
exit 0
509+
fi
510+
511+
echo "Found version bump commit: $VERSION_COMMIT"
512+
513+
git fetch origin "$DEFAULT_BRANCH"
514+
515+
# Skip if the version bump is already on the default branch
516+
if git merge-base --is-ancestor "$VERSION_COMMIT" "origin/$DEFAULT_BRANCH"; then
517+
echo "Version bump commit $VERSION_COMMIT is already on $DEFAULT_BRANCH — skipping cherry-pick"
518+
exit 0
519+
fi
520+
521+
# Prepare cherry-pick branch
522+
CHERRY_BRANCH="cherry-pick/v${VERSION}-version-to-main"
523+
524+
git checkout "$DEFAULT_BRANCH"
525+
git pull origin "$DEFAULT_BRANCH"
526+
527+
# Clean up existing remote branch if any
528+
git push origin --delete "$CHERRY_BRANCH" 2>/dev/null || true
529+
git checkout -b "$CHERRY_BRANCH"
530+
531+
# Attempt cherry-pick
532+
if git cherry-pick "$VERSION_COMMIT" --no-commit; then
533+
# Check if cherry-pick produced any changes (may be empty if already applied via a different commit)
534+
if [ -z "$(git diff --cached --name-only)" ]; then
535+
echo "Cherry-pick produced no changes — version bump already applied on $DEFAULT_BRANCH"
536+
git reset HEAD 2>/dev/null || true
537+
exit 0
538+
fi
539+
540+
git commit -m "$(cat <<EOF
541+
chore: sync version to $VERSION
542+
543+
Cherry-picked from $RELEASE_BRANCH (release v$VERSION)
544+
Original commit: $VERSION_COMMIT
545+
EOF
546+
)"
547+
548+
git push origin "$CHERRY_BRANCH"
549+
550+
gh pr create \
551+
--base "$DEFAULT_BRANCH" \
552+
--head "$CHERRY_BRANCH" \
553+
--title "chore: sync version to v${VERSION}" \
554+
--label "cherry-pick" \
555+
--label "auto-cherry-pick" \
556+
--body "$(cat <<EOF
557+
## Version sync to main
558+
559+
Updates all \`@enclave-vm/*\` package versions to \`${VERSION}\` on \`${DEFAULT_BRANCH}\`.
560+
561+
This cherry-pick was automatically created because \`v${VERSION}\` is the **latest stable release**.
562+
563+
**Source:** \`${RELEASE_BRANCH}\` release v${VERSION}
564+
565+
---
566+
_Auto-generated by the publish-release workflow._
567+
EOF
568+
)"
569+
570+
echo "Cherry-pick PR created successfully"
571+
else
572+
# Check if failure is due to empty cherry-pick (already applied) vs actual conflicts
573+
if [ -z "$(git status --porcelain)" ]; then
574+
echo "Cherry-pick is empty — version bump already applied on $DEFAULT_BRANCH"
575+
git cherry-pick --abort 2>/dev/null || true
576+
exit 0
577+
fi
578+
579+
git cherry-pick --abort || true
580+
echo "::warning::Cherry-pick had conflicts. Creating issue for manual resolution."
581+
582+
gh issue create \
583+
--title "Manual version sync needed: v${VERSION} to main" \
584+
--label "cherry-pick" \
585+
--label "conflict" \
586+
--label "needs-attention" \
587+
--body "$(cat <<EOF
588+
## Manual Version Sync Required
589+
590+
Auto cherry-pick of version bump to \`v${VERSION}\` failed due to conflicts.
591+
592+
### Manual Steps
593+
594+
\`\`\`bash
595+
git checkout $DEFAULT_BRANCH && git pull
596+
git checkout -b cherry-pick/v${VERSION}-version-to-main
597+
git cherry-pick $VERSION_COMMIT
598+
# Resolve conflicts
599+
git add . && git cherry-pick --continue
600+
git push origin cherry-pick/v${VERSION}-version-to-main
601+
gh pr create --base $DEFAULT_BRANCH --title "chore: sync version to v${VERSION}"
602+
\`\`\`
603+
604+
---
605+
_Auto-generated by the publish-release workflow._
606+
EOF
607+
)"
608+
fi

libs/ast/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/ast",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "A production-ready AST security guard for JavaScript - validate, protect, and enforce code safety with extensible rules",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave/tree/main/libs/ast-guard",

libs/broker/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/broker",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Tool broker and session management for the EnclaveJS streaming runtime",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -35,9 +35,9 @@
3535
}
3636
},
3737
"dependencies": {
38-
"@enclave-vm/types": "2.10.0",
39-
"@enclave-vm/stream": "2.10.0",
40-
"@enclave-vm/core": "2.10.0",
38+
"@enclave-vm/types": "2.11.0",
39+
"@enclave-vm/stream": "2.11.0",
40+
"@enclave-vm/core": "2.11.0",
4141
"minimatch": "^10.1.1",
4242
"zod": "^4.3.6"
4343
}

libs/client/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/client",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Browser and Node.js client SDK for the EnclaveJS streaming runtime",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -34,7 +34,7 @@
3434
}
3535
},
3636
"dependencies": {
37-
"@enclave-vm/types": "2.10.0",
38-
"@enclave-vm/stream": "2.10.0"
37+
"@enclave-vm/types": "2.11.0",
38+
"@enclave-vm/stream": "2.11.0"
3939
}
4040
}

libs/core/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/core",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Sandbox runtime for secure JavaScript code execution",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -39,8 +39,8 @@
3939
},
4040
"dependencies": {
4141
"@babel/standalone": "^7.29.0",
42-
"@enclave-vm/types": "2.10.0",
43-
"@enclave-vm/ast": "2.10.0",
42+
"@enclave-vm/types": "2.11.0",
43+
"@enclave-vm/ast": "2.11.0",
4444
"acorn": "8.15.0",
4545
"acorn-walk": "8.3.4",
4646
"astring": "1.9.0",

libs/react/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/react",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "React hooks and components for the EnclaveJS streaming runtime",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -34,7 +34,7 @@
3434
}
3535
},
3636
"dependencies": {
37-
"@enclave-vm/client": "2.10.0"
37+
"@enclave-vm/client": "2.11.0"
3838
},
3939
"peerDependencies": {
4040
"react": ">=18.0.0"

libs/runtime/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/runtime",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Standalone runtime worker for EnclaveJS - deployable execution environment",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -37,9 +37,9 @@
3737
"enclave-runtime": "./dist/cli.js"
3838
},
3939
"dependencies": {
40-
"@enclave-vm/types": "2.10.0",
41-
"@enclave-vm/stream": "2.10.0",
42-
"@enclave-vm/core": "2.10.0"
40+
"@enclave-vm/types": "2.11.0",
41+
"@enclave-vm/stream": "2.11.0",
42+
"@enclave-vm/core": "2.11.0"
4343
},
4444
"devDependencies": {
4545
"ws": "^8.19.0"

libs/stream/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/stream",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Streaming protocol implementation for EnclaveJS runtime (NDJSON, encryption, reconnection)",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",
@@ -35,6 +35,6 @@
3535
}
3636
},
3737
"dependencies": {
38-
"@enclave-vm/types": "2.10.0"
38+
"@enclave-vm/types": "2.11.0"
3939
}
4040
}

libs/types/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@enclave-vm/types",
3-
"version": "2.10.0",
3+
"version": "2.11.0",
44
"description": "Type definitions and Zod schemas for the EnclaveJS streaming runtime protocol",
55
"author": "AgentFront <info@agentfront.dev>",
66
"homepage": "https://github.com/agentfront/enclave",

0 commit comments

Comments
 (0)