From ad1cbba89fb0a9c35cd6bfbcda360776e54014e6 Mon Sep 17 00:00:00 2001 From: David Antoon Date: Thu, 11 Dec 2025 04:54:22 +0200 Subject: [PATCH 1/2] feat: implement internal dependency synchronization and changelog generation --- .github/workflows/create-release-branch.yml | 59 +++++++++++++++++++++ .github/workflows/publish-on-next-close.yml | 33 ++++++++++++ libs/enclave-vm/package.json | 4 +- 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows/create-release-branch.yml index ccb3797..6cde3bb 100644 --- a/.github/workflows/create-release-branch.yml +++ b/.github/workflows/create-release-branch.yml @@ -252,6 +252,14 @@ jobs: let maxVersion = '0.0.0'; const bumpedProjects = []; + const internalVersions = {}; + + // Helper to increment patch version + function bumpPatch(version) { + const parts = version.split('.'); + parts[2] = String(parseInt(parts[2], 10) + 1); + return parts.join('.'); + } // Helper to generate changelog entry function generateChangelogEntry(version, changelog) { @@ -291,6 +299,7 @@ jobs: fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); console.error('Updated ' + proj.name + ' to ' + proj.newVersion + ' (' + proj.bump + '): ' + proj.reason); bumpedProjects.push(proj.name); + internalVersions[proj.name] = proj.newVersion; // Track max version if (proj.newVersion.localeCompare(maxVersion, undefined, { numeric: true, sensitivity: 'base' }) > 0) { @@ -320,6 +329,56 @@ jobs: } } + // Second pass: Sync internal dependencies across ALL publishable packages + // If a package depends on a bumped package, update the dep version and patch-bump the dependent + const { execSync } = require('child_process'); + let allLibs = []; + try { + const allPublishable = execSync('npx nx show projects -p tag:scope:publishable --type lib --json', { encoding: 'utf8' }); + allLibs = JSON.parse(allPublishable); + } catch (e) { + console.error('Warning: Could not get publishable libs for dependency sync'); + } + + for (const libName of allLibs) { + const pkgPath = 'libs/' + libName + '/package.json'; + if (!fs.existsSync(pkgPath)) continue; + + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); + let modified = false; + let needsBump = false; + + // Check if any dependency was bumped + if (pkg.dependencies) { + for (const [dep, version] of Object.entries(pkg.dependencies)) { + if (internalVersions[dep] && version !== internalVersions[dep]) { + pkg.dependencies[dep] = internalVersions[dep]; + modified = true; + needsBump = true; + console.error('Updated ' + libName + ' dep ' + dep + ' to ' + internalVersions[dep]); + } + } + } + + // If this package wasn't already bumped but has updated deps, patch bump it + if (needsBump && !internalVersions[libName]) { + const newVersion = bumpPatch(pkg.version); + pkg.version = newVersion; + internalVersions[libName] = newVersion; + bumpedProjects.push(libName); + console.error('Patch bumped ' + libName + ' to ' + newVersion + ' (dependency update)'); + + // Update max version + if (newVersion.localeCompare(maxVersion, undefined, { numeric: true, sensitivity: 'base' }) > 0) { + maxVersion = newVersion; + } + } + + if (modified) { + fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n'); + } + } + // Update global changelog if (output.globalChangelog && bumpedProjects.length > 0) { const globalPath = 'CHANGELOG.md'; diff --git a/.github/workflows/publish-on-next-close.yml b/.github/workflows/publish-on-next-close.yml index 7ac0e04..3f05159 100644 --- a/.github/workflows/publish-on-next-close.yml +++ b/.github/workflows/publish-on-next-close.yml @@ -63,6 +63,9 @@ jobs: - name: Install dependencies run: yarn install --frozen-lockfile + - name: Set Nx SHAs + uses: nrwl/nx-set-shas@v4 + - name: Find affected publishable libs id: to_publish shell: bash @@ -223,11 +226,41 @@ jobs: yarn nx run "$project:publish" done + - name: Generate release body + id: release_body + shell: bash + run: | + set -euo pipefail + + PROJECTS="${{ steps.to_publish.outputs.projects }}" + VERSION="${{ steps.version.outputs.version }}" + + if [ -n "$PROJECTS" ]; then + # Build release body with published packages info + BODY="## Published Packages\n\n" + + IFS=',' read -ra LIBS <<< "$PROJECTS" + for lib in "${LIBS[@]}"; do + if [ -f "libs/$lib/package.json" ]; then + LIB_VERSION=$(node -e "console.log(require('./libs/$lib/package.json').version)") + BODY+="- **${lib}** v${LIB_VERSION} - [npm](https://www.npmjs.com/package/${lib}/v/${LIB_VERSION})\n" + fi + done + + BODY+="\n---\n\n" + else + BODY="*No packages published in this release.*\n\n---\n\n" + fi + + # Save body to file for multiline support + echo -e "$BODY" > /tmp/release_body.md + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: tag_name: v${{ steps.version.outputs.version }} name: v${{ steps.version.outputs.version }} + body_path: /tmp/release_body.md generate_release_notes: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/libs/enclave-vm/package.json b/libs/enclave-vm/package.json index ea7b4d6..0b1d8ff 100644 --- a/libs/enclave-vm/package.json +++ b/libs/enclave-vm/package.json @@ -1,6 +1,6 @@ { "name": "enclave-vm", - "version": "1.0.0", + "version": "1.0.1", "description": "Sandbox runtime for secure JavaScript code execution", "author": "AgentFront ", "homepage": "https://github.com/agentfront/enclave", @@ -36,7 +36,7 @@ } }, "dependencies": { - "ast-guard": "1.0.0", + "ast-guard": "1.1.0", "acorn": "8.15.0", "acorn-walk": "8.3.4", "astring": "1.9.0", From b27c62664f47a9f6871176e9ac9f44adb7fbfac4 Mon Sep 17 00:00:00 2001 From: David Antoon Date: Thu, 11 Dec 2025 05:13:05 +0200 Subject: [PATCH 2/2] feat: validate semantic versioning and enhance internal dependency checks --- .github/workflows/create-release-branch.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows/create-release-branch.yml index 6cde3bb..3950d5a 100644 --- a/.github/workflows/create-release-branch.yml +++ b/.github/workflows/create-release-branch.yml @@ -257,10 +257,18 @@ jobs: // Helper to increment patch version function bumpPatch(version) { const parts = version.split('.'); + if (parts.length < 3 || isNaN(parseInt(parts[2], 10))) { + throw new Error('Invalid semantic version: ' + version); + } parts[2] = String(parseInt(parts[2], 10) + 1); return parts.join('.'); } + // Helper to check if version is exact (no range specifier) + function isExactVersion(version) { + return /^\d+\.\d+\.\d+$/.test(version); + } + // Helper to generate changelog entry function generateChangelogEntry(version, changelog) { const categories = [ @@ -348,10 +356,11 @@ jobs: let modified = false; let needsBump = false; - // Check if any dependency was bumped + // Check if any internal dependency was bumped + // Only update exact-pinned versions (internal deps), skip range specifiers (external deps) if (pkg.dependencies) { for (const [dep, version] of Object.entries(pkg.dependencies)) { - if (internalVersions[dep] && version !== internalVersions[dep]) { + if (internalVersions[dep] && isExactVersion(version) && version !== internalVersions[dep]) { pkg.dependencies[dep] = internalVersions[dep]; modified = true; needsBump = true;