[codex] stabilize openrouter defaults and app identity (#197) #83
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # CD Release - Version bump + GitHub release creation | |
| # Trigger: main push (skips version bump commits) | |
| # Parallel: runs alongside ci-tests on main | |
| name: cd-release | |
| on: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| concurrency: | |
| group: cd-release-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| release: | |
| runs-on: blacksmith-2vcpu-ubuntu-2404 | |
| # Skip if commit message contains [skip-release] or is a version bump commit | |
| if: | | |
| !contains(github.event.head_commit.message, '[skip-release]') && | |
| !contains(github.event.head_commit.message, 'chore: bump version') | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| fetch-depth: 0 | |
| - name: Skip bump merges | |
| id: skip_release | |
| run: | | |
| MSG=$(git log -1 --pretty=%B) | |
| if echo "$MSG" | grep -q "chore: bump version"; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping release for bump commit." | |
| exit 0 | |
| fi | |
| if echo "$MSG" | grep -q "chore/bump-version"; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping release for bump merge." | |
| exit 0 | |
| fi | |
| PARENTS=$(git show -s --pretty=%P HEAD) | |
| PARENT_COUNT=$(echo "$PARENTS" | wc -w | tr -d ' ') | |
| if [ "$PARENT_COUNT" -gt 1 ]; then | |
| MERGED_HEAD=$(echo "$PARENTS" | awk '{print $2}') | |
| MERGED_MSG=$(git show -s --pretty=%B "$MERGED_HEAD") | |
| if echo "$MERGED_MSG" | grep -q "chore: bump version"; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping release for bump merge." | |
| exit 0 | |
| fi | |
| fi | |
| # Skip releases when changes are limited to non-runtime paths (docs, OpenCode, CI, or the npm plugin package). | |
| # This prevents bumping the app version when only publishing/iterating on the OpenCode plugin. | |
| BEFORE_SHA="${{ github.event.before }}" | |
| AFTER_SHA="${{ github.sha }}" | |
| CHANGED_FILES="$(git diff --name-only "${BEFORE_SHA}..${AFTER_SHA}" || true)" | |
| if [ -n "$CHANGED_FILES" ]; then | |
| ONLY_IGNORED="true" | |
| while IFS= read -r file; do | |
| [ -z "$file" ] && continue | |
| case "$file" in | |
| README.md|AGENTS.md|bun.lock) ;; | |
| docs/*|.codex/*) ;; | |
| packages/opencode-excalidraw/*) ;; | |
| .github/workflows/*) ;; | |
| *) | |
| ONLY_IGNORED="false" | |
| break | |
| ;; | |
| esac | |
| done <<< "$CHANGED_FILES" | |
| if [ "$ONLY_IGNORED" = "true" ]; then | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| echo "Skipping release: only non-runtime paths changed." | |
| exit 0 | |
| fi | |
| fi | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| if: steps.skip_release.outputs.skip != 'true' | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: bun install | |
| - name: Configure Git | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --global user.name "github-actions[bot]" | |
| - name: Get current version | |
| id: current_version | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: echo "version=$(bun -e "console.log(require('./package.json').version)")" >> $GITHUB_OUTPUT | |
| - name: Create bump branch | |
| id: bump_branch | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| BRANCH="chore/bump-version-${{ github.run_id }}-${{ github.run_attempt }}" | |
| git checkout -b "$BRANCH" | |
| echo "branch=$BRANCH" >> $GITHUB_OUTPUT | |
| - name: Bump version | |
| id: bump_version | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| CUR_VERSION="${{ steps.current_version.outputs.version }}" | |
| CUR_VERSION="${CUR_VERSION%%-*}" | |
| IFS='.' read -r CUR_MAJOR CUR_MINOR _ <<< "$CUR_VERSION" | |
| for _ in {1..10}; do | |
| npm version patch --no-git-tag-version | |
| NEW_VERSION=$(bun -e "console.log(require('./package.json').version)") | |
| NEW_VERSION_BASE="${NEW_VERSION%%-*}" | |
| IFS='.' read -r NEW_MAJOR NEW_MINOR _ <<< "$NEW_VERSION_BASE" | |
| if [ "$CUR_MAJOR" != "$NEW_MAJOR" ] || [ "$CUR_MINOR" != "$NEW_MINOR" ]; then | |
| echo "Refusing to bump major/minor; patch-only enforced." | |
| exit 1 | |
| fi | |
| TAG="v$NEW_VERSION" | |
| if git rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then | |
| echo "Tag $TAG already exists; bumping again." | |
| continue | |
| fi | |
| echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT | |
| echo "Bumped version from ${{ steps.current_version.outputs.version }} to $NEW_VERSION" | |
| exit 0 | |
| done | |
| echo "Failed to find unused patch version after 10 bumps." | |
| exit 1 | |
| - name: Commit version bump | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| git add package.json | |
| git commit -m "chore: bump version to ${{ steps.bump_version.outputs.new_version }} [skip-release] [skip ci]" | |
| git push --set-upstream origin "${{ steps.bump_branch.outputs.branch }}" | |
| - name: Create PR | |
| id: bump_pr | |
| if: steps.skip_release.outputs.skip != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| PR_URL=$(gh pr create \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --base main \ | |
| --head "${{ steps.bump_branch.outputs.branch }}" \ | |
| --title "chore: bump version to ${{ steps.bump_version.outputs.new_version }}" \ | |
| --body "Automated patch version bump.") | |
| echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT | |
| - name: Enable auto-merge | |
| if: steps.skip_release.outputs.skip != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| PR_URL="${{ steps.bump_pr.outputs.pr_url }}" | |
| set +e | |
| MERGE_OUTPUT=$( | |
| gh pr merge "$PR_URL" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --squash \ | |
| --auto 2>&1 | |
| ) | |
| MERGE_STATUS=$? | |
| set -e | |
| if [ "$MERGE_STATUS" -eq 0 ]; then | |
| echo "$MERGE_OUTPUT" | |
| exit 0 | |
| fi | |
| if printf '%s' "$MERGE_OUTPUT" | grep -q "in clean status"; then | |
| echo "Auto-merge not applicable, merging immediately." | |
| gh pr merge "$PR_URL" \ | |
| --repo "$GITHUB_REPOSITORY" \ | |
| --squash \ | |
| --delete-branch | |
| exit 0 | |
| fi | |
| echo "$MERGE_OUTPUT" | |
| exit "$MERGE_STATUS" | |
| - name: Wait for PR merge | |
| if: steps.skip_release.outputs.skip != 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| PR_URL="${{ steps.bump_pr.outputs.pr_url }}" | |
| for _ in {1..30}; do | |
| MERGED_AT=$(gh pr view "$PR_URL" --repo "$GITHUB_REPOSITORY" --json mergedAt -q .mergedAt) | |
| if [ -n "$MERGED_AT" ] && [ "$MERGED_AT" != "null" ]; then | |
| echo "PR merged at $MERGED_AT" | |
| git fetch origin main | |
| git checkout main | |
| git reset --hard origin/main | |
| exit 0 | |
| fi | |
| sleep 5 | |
| done | |
| echo "PR did not merge in time." | |
| exit 1 | |
| - name: Generate release notes | |
| id: release_notes | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| # Get the latest tag (if any) | |
| LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| # Generate release notes | |
| if [ -z "$LATEST_TAG" ]; then | |
| NOTES="## Initial Release" | |
| echo "Initial release - no previous tags found" | |
| else | |
| echo "Generating notes from $LATEST_TAG to HEAD" | |
| # Get commit messages since last tag, excluding version bump commits | |
| COMMITS=$(git log $LATEST_TAG..HEAD --pretty=format:"- %s" --no-merges | grep -v "chore: bump version" | grep -v "\[skip-release\]") | |
| if [ -z "$COMMITS" ]; then | |
| NOTES="## Release v${{ steps.bump_version.outputs.new_version }}" | |
| else | |
| printf -v NOTES "## Release v${{ steps.bump_version.outputs.new_version }}\n\n### Changes\n%s" "$COMMITS" | |
| fi | |
| fi | |
| # Save to file for multiline support | |
| echo "$NOTES" > release_notes.md | |
| echo "Release notes generated" | |
| - name: Create GitHub Release | |
| if: steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| gh release create v${{ steps.bump_version.outputs.new_version }} \ | |
| --title "Release v${{ steps.bump_version.outputs.new_version }}" \ | |
| --notes-file release_notes.md \ | |
| --target main | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Clean up | |
| if: always() && steps.skip_release.outputs.skip != 'true' | |
| run: | | |
| rm -f release_notes.md |