name: Release on: push: tags: ['v*'] jobs: # ────────────────────────────────────────────── # Job 1: Build & Push Docker Image (GHCR) # ────────────────────────────────────────────── docker: name: Docker Build & Push runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Docker metadata id: meta uses: docker/metadata-action@v5 with: # github.repository (= dwgx/WindsurfAPI) lowercases to "windsurfapi" # without the hyphen the package.json npm name uses. Hardcode the # kebab form so the image name stays "windsurf-api". images: ghcr.io/${{ github.repository_owner }}/windsurf-api tags: | # Only tag as latest for stable releases (no pre-release suffix like -rc, -alpha, -beta) type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }} # v2.0.6 -> 2.0.6 type=semver,pattern={{version}} # v2.0.6 -> 2.0 type=semver,pattern={{major}}.{{minor}} - name: Build and push uses: docker/build-push-action@v6 with: context: . platforms: linux/amd64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Summary run: | echo "## 🐳 Docker Image Published" >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" echo "**Tags:**" >> "$GITHUB_STEP_SUMMARY" echo '${{ steps.meta.outputs.tags }}' | tr ',' '\n' | sed 's/^/- `/' | sed 's/$/`/' >> "$GITHUB_STEP_SUMMARY" echo "" >> "$GITHUB_STEP_SUMMARY" echo "**Platform:** \`linux/amd64\`" >> "$GITHUB_STEP_SUMMARY" # ────────────────────────────────────────────── # Job 2: Create GitHub Release with source code # ────────────────────────────────────────────── release: name: GitHub Release runs-on: ubuntu-latest permissions: contents: write steps: - name: Checkout uses: actions/checkout@v4 - name: Get version from tag id: version run: echo "VERSION=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - name: Check for release notes id: notes run: | # New layout (docs/releases/) preferred; fall back to repo root # so historical tags still find their notes if anyone re-cuts an # old release. NEW_PATH="docs/releases/RELEASE_NOTES_${{ steps.version.outputs.VERSION }}.md" OLD_PATH="RELEASE_NOTES_${{ steps.version.outputs.VERSION }}.md" if [[ -f "$NEW_PATH" ]]; then echo "file=$NEW_PATH" >> "$GITHUB_OUTPUT" echo "found=true" >> "$GITHUB_OUTPUT" elif [[ -f "$OLD_PATH" ]]; then echo "file=$OLD_PATH" >> "$GITHUB_OUTPUT" echo "found=true" >> "$GITHUB_OUTPUT" else echo "found=false" >> "$GITHUB_OUTPUT" fi - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: name: v${{ steps.version.outputs.VERSION }} body_path: ${{ steps.notes.outputs.found == 'true' && steps.notes.outputs.file || '' }} generate_release_notes: ${{ steps.notes.outputs.found != 'true' }} draft: false prerelease: ${{ contains(github.ref_name, '-') }}