name: Bump version and release on: workflow_dispatch: inputs: version_type: description: "Version bump type (patch, minor, major)" required: false default: "patch" prerelease: description: "Publish as prerelease? (leave empty for stable, or enter tag like 'next')" required: false default: "" jobs: preflight: runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout uses: actions/checkout@v6 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.0 - name: Setup Node uses: actions/setup-node@v6 with: node-version: "22" - name: Install dependencies env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bun install - name: Lint & Type Check run: bun run check - name: Build bundle run: bun run build - name: Update-chain preflight smoke run: bun run test:update-chain:manual publish: needs: preflight runs-on: ubuntu-latest environment: npm-publish permissions: contents: write id-token: write # Required for npm OIDC trusted publishing steps: - name: Checkout uses: actions/checkout@v6 with: token: ${{ secrets.GITHUB_TOKEN }} fetch-depth: 0 - name: Configure Git run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.0 - name: Setup Node (for npm OIDC publishing) uses: actions/setup-node@v6 with: node-version: "22" - name: Upgrade npm for OIDC support run: npm install -g npm@latest - name: Bump version id: version run: | VERSION_TYPE="${{ github.event.inputs.version_type || 'patch' }}" PRERELEASE_TAG="${{ github.event.inputs.prerelease }}" OLD_VERSION=$(jq -r '.version' package.json) # Check if old version is a prerelease (contains -) if [[ "$OLD_VERSION" == *-* ]]; then OLD_IS_PRERELEASE=true BASE_VERSION=$(echo "$OLD_VERSION" | sed 's/-.*//') else OLD_IS_PRERELEASE=false BASE_VERSION="$OLD_VERSION" fi # Split base version into parts IFS='.' read -ra VERSION_PARTS <<< "$BASE_VERSION" MAJOR=${VERSION_PARTS[0]} MINOR=${VERSION_PARTS[1]} PATCH=${VERSION_PARTS[2]} # Always bump based on version_type if [ "$VERSION_TYPE" = "major" ]; then MAJOR=$((MAJOR + 1)) MINOR=0 PATCH=0 elif [ "$VERSION_TYPE" = "minor" ]; then MINOR=$((MINOR + 1)) PATCH=0 else # patch - only bump if not coming from prerelease # (prerelease → stable with patch just drops the suffix) if [ "$OLD_IS_PRERELEASE" = "false" ]; then PATCH=$((PATCH + 1)) fi fi NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}" # Handle prerelease suffix if [ -n "$PRERELEASE_TAG" ]; then # Making a prerelease if [[ "$OLD_VERSION" == "${NEW_VERSION}-${PRERELEASE_TAG}."* ]]; then # Same base + same tag: increment prerelease number PRERELEASE_NUM=$(echo "$OLD_VERSION" | sed "s/${NEW_VERSION}-${PRERELEASE_TAG}\.\([0-9]*\)/\1/") PRERELEASE_NUM=$((PRERELEASE_NUM + 1)) else # Different base or different tag: start at 1 PRERELEASE_NUM=1 fi NEW_VERSION="${NEW_VERSION}-${PRERELEASE_TAG}.${PRERELEASE_NUM}" echo "npm_tag=$PRERELEASE_TAG" >> $GITHUB_OUTPUT echo "is_prerelease=true" >> $GITHUB_OUTPUT else # Making a stable release - NEW_VERSION is already just the base echo "npm_tag=latest" >> $GITHUB_OUTPUT echo "is_prerelease=false" >> $GITHUB_OUTPUT fi # Update package.json jq --arg version "$NEW_VERSION" '.version = $version' package.json > package.json.tmp mv package.json.tmp package.json # Keep package-lock versions in sync for npm publish consistency jq --arg version "$NEW_VERSION" '.version = $version | .packages[""].version = $version' package-lock.json > package-lock.json.tmp mv package-lock.json.tmp package-lock.json echo "old_version=$OLD_VERSION" >> $GITHUB_OUTPUT echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT echo "tag=v$NEW_VERSION" >> $GITHUB_OUTPUT - name: Commit and tag version bump (local only) run: | git add package.json package-lock.json git commit -m "chore: bump version to ${{ steps.version.outputs.new_version }} [skip ci]" git tag "${{ steps.version.outputs.tag }}" - name: Install dependencies env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: bun install - name: Lint & Type Check run: bun run check - name: Build bundle run: bun run build - name: Smoke test - help run: ./letta.js --help - name: Smoke test - version run: ./letta.js --version || echo "Version flag not implemented yet" - name: Integration smoke test (real API) env: LETTA_API_KEY: ${{ secrets.LETTA_API_KEY }} run: ./letta.js --prompt "ping" --tools "" --permission-mode plan - name: Publish to npm run: npm publish --access public --tag ${{ steps.version.outputs.npm_tag }} - name: Push commit and tag after publish run: | git push origin main git push origin "${{ steps.version.outputs.tag }}" - name: Create GitHub Release if: steps.version.outputs.is_prerelease == 'false' uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.version.outputs.tag }} name: Release ${{ steps.version.outputs.tag }} body: | Changes from ${{ steps.version.outputs.old_version }} to ${{ steps.version.outputs.new_version }} generate_release_notes: true files: letta.js fail_on_unmatched_files: true