ci: Bump codecov/codecov-action from 4.6.0 to 5.5.2 (#25) #31
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
| name: Release | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| bump: | ||
| description: 'Version bump type' | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - patch | ||
| - minor | ||
| - major | ||
| env: | ||
| GO_VERSION: '1.26.1' | ||
| concurrency: | ||
| group: release | ||
| cancel-in-progress: false | ||
| jobs: | ||
| preflight: | ||
| name: Preflight Checks | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 30 | ||
| defaults: | ||
| run: | ||
| working-directory: cli | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | ||
| with: | ||
| go-version: '${{ env.GO_VERSION }}' | ||
| cache: true | ||
| cache-dependency-path: cli/go.sum | ||
| - name: Cache Go tools | ||
| uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4 | ||
| with: | ||
| path: ~/go/bin | ||
| key: go-tools-${{ runner.os }}-${{ hashFiles('cli/go.sum') }} | ||
| - name: Install golangci-lint | ||
| run: go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest | ||
| - name: Install staticcheck | ||
| run: go install honnef.co/go/tools/cmd/staticcheck@latest | ||
| - name: Install gosec | ||
| run: go install github.com/securego/gosec/v2/cmd/gosec@latest | ||
| - name: Install govulncheck | ||
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | ||
| - name: Install azd | ||
| run: curl -fsSL https://aka.ms/install-azd.sh | bash | ||
| - name: Install azd extensions | ||
| run: | | ||
| azd extension source add azd --location https://aka.ms/azd/extensions/registry --type url 2>/dev/null || true | ||
| azd extension install microsoft.azd.extensions --source azd | ||
| - name: Format check | ||
| run: | | ||
| if [ -n "$(gofmt -l ./src/)" ]; then | ||
| echo "Go files need formatting:" | ||
| gofmt -l ./src/ | ||
| exit 1 | ||
| fi | ||
| - name: Lint | ||
| run: golangci-lint run --timeout=5m ./src/... | ||
| - name: Security scan | ||
| run: gosec -quiet -exclude=G204,G304 ./src/... | ||
| - name: Vulnerability check | ||
| run: govulncheck ./src/... | ||
| test: | ||
| name: Test | ||
| runs-on: ${{ matrix.os }} | ||
| timeout-minutes: 30 | ||
| defaults: | ||
| run: | ||
| working-directory: cli | ||
| strategy: | ||
| matrix: | ||
| os: [ubuntu-latest, windows-latest, macos-latest] | ||
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | ||
| with: | ||
| go-version: '${{ env.GO_VERSION }}' | ||
| cache: true | ||
| cache-dependency-path: cli/go.sum | ||
| - name: Run tests | ||
| shell: bash | ||
| run: | | ||
| mkdir -p ../coverage | ||
| if [ "${{ matrix.os }}" = "macos-latest" ]; then | ||
| go test -short -v -coverprofile=../coverage/coverage.out ./src/... | ||
| else | ||
| go test -short -v -race -coverprofile=../coverage/coverage.out ./src/... | ||
| fi | ||
| - name: Upload coverage to Codecov | ||
| if: github.repository == 'jongio/azd-rest' | ||
| uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 | ||
| with: | ||
| file: coverage/coverage.out | ||
| flags: unittests | ||
| name: codecov-${{ matrix.os }}-go-${{ env.GO_VERSION }} | ||
| token: ${{ secrets.CODECOV_TOKEN }} | ||
| fail_ci_if_error: false | ||
| verbose: true | ||
| - name: Set up Go | ||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | ||
| with: | ||
| go-version: '${{ env.GO_VERSION }}' | ||
| cache: true | ||
| cache-dependency-path: cli/go.sum | ||
| - name: Build for multiple platforms | ||
| run: | | ||
| GOOS=windows GOARCH=amd64 go build -o bin/windows-amd64/rest.exe ./src/cmd/rest | ||
| GOOS=windows GOARCH=arm64 go build -o bin/windows-arm64/rest.exe ./src/cmd/rest | ||
| GOOS=linux GOARCH=amd64 go build -o bin/linux-amd64/rest ./src/cmd/rest | ||
| GOOS=darwin GOARCH=amd64 go build -o bin/darwin-amd64/rest ./src/cmd/rest | ||
| GOOS=darwin GOARCH=arm64 go build -o bin/darwin-arm64/rest ./src/cmd/rest | ||
| - name: Upload artifacts | ||
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 | ||
| with: | ||
| name: binaries | ||
| path: cli/bin/ | ||
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| needs: [preflight, test, build] | ||
| timeout-minutes: 60 | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| id-token: write # Required for cosign OIDC signing | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - name: Set up Go | ||
| uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 | ||
| with: | ||
| go-version: '${{ env.GO_VERSION }}' | ||
| cache: true | ||
| cache-dependency-path: cli/go.sum | ||
| - name: Calculate next version | ||
| id: version | ||
| run: | | ||
| CURRENT=$(grep '^version:' cli/extension.yaml | awk '{print $2}') | ||
| IFS='.' read -r major minor patch <<< "$CURRENT" | ||
| case "${{ inputs.bump }}" in | ||
| major) | ||
| major=$((major + 1)) | ||
| minor=0 | ||
| patch=0 | ||
| ;; | ||
| minor) | ||
| minor=$((minor + 1)) | ||
| patch=0 | ||
| ;; | ||
| patch) | ||
| patch=$((patch + 1)) | ||
| ;; | ||
| esac | ||
| NEXT="$major.$minor.$patch" | ||
| echo "current=$CURRENT" >> $GITHUB_OUTPUT | ||
| echo "next=$NEXT" >> $GITHUB_OUTPUT | ||
| echo "Bumping from $CURRENT to $NEXT" | ||
| - name: Update version files and create PR | ||
| id: version_pr | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| BRANCH="release/v${VERSION}" | ||
| git push origin --delete "$BRANCH" 2>/dev/null || true | ||
| git branch -D "$BRANCH" 2>/dev/null || true | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git checkout -b "$BRANCH" | ||
| sed -i "s/^version: .*/version: $VERSION/" cli/extension.yaml | ||
| PREV="${{ steps.version.outputs.current }}" | ||
| if git rev-parse "v${PREV}" >/dev/null 2>&1; then | ||
| COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges v${PREV}..HEAD) | ||
| else | ||
| LAST_VERSION_COMMIT=$(git log --grep="^chore: bump version to" --format="%H" -n 1) | ||
| if [ -n "$LAST_VERSION_COMMIT" ]; then | ||
| COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges ${LAST_VERSION_COMMIT}..HEAD) | ||
| else | ||
| COMMITS=$(git log --pretty=format:"- %s (%h)" --no-merges) | ||
| fi | ||
| fi | ||
| DATE=$(date +%Y-%m-%d) | ||
| { | ||
| echo "## [$VERSION] - $DATE" | ||
| echo "" | ||
| echo "$COMMITS" | ||
| echo "" | ||
| cat CHANGELOG.md | ||
| } > CHANGELOG.new.md | ||
| mv CHANGELOG.new.md CHANGELOG.md | ||
| git add cli/extension.yaml CHANGELOG.md | ||
| git commit -m "chore: bump version to $VERSION" | ||
| git push origin "$BRANCH" | ||
| PR_URL=$(gh pr create \ | ||
| --title "chore: Release v${VERSION}" \ | ||
| --body "Automated version bump to ${VERSION} for release." \ | ||
| --base main \ | ||
| --head "$BRANCH") | ||
| echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT | ||
| echo "branch=$BRANCH" >> $GITHUB_OUTPUT | ||
| PR_NUMBER=$(echo "$PR_URL" | grep -oP '\d+$') | ||
| echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT | ||
| - name: Enable auto-merge and wait for merge | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| PR_NUMBER="${{ steps.version_pr.outputs.pr_number }}" | ||
| echo "Waiting for CI checks to be queued..." | ||
| sleep 10 | ||
| MAX_RETRIES=3 | ||
| RETRY=0 | ||
| while [ $RETRY -lt $MAX_RETRIES ]; do | ||
| if gh pr merge "$PR_NUMBER" --auto --squash 2>&1; then | ||
| echo "Auto-merge enabled successfully!" | ||
| break | ||
| else | ||
| RETRY=$((RETRY + 1)) | ||
| if [ $RETRY -lt $MAX_RETRIES ]; then | ||
| echo "Retrying in 10 seconds... (attempt $RETRY/$MAX_RETRIES)" | ||
| sleep 10 | ||
| else | ||
| echo "Failed to enable auto-merge after $MAX_RETRIES attempts" | ||
| exit 1 | ||
| fi | ||
| fi | ||
| done | ||
| echo "Waiting for PR to be merged..." | ||
| TIMEOUT=600 | ||
| ELAPSED=0 | ||
| INTERVAL=15 | ||
| while [ $ELAPSED -lt $TIMEOUT ]; do | ||
| PR_DATA=$(gh pr view "$PR_NUMBER" --json state,mergeable,statusCheckRollup) | ||
| STATE=$(echo "$PR_DATA" | jq -r '.state') | ||
| MERGEABLE=$(echo "$PR_DATA" | jq -r '.mergeable') | ||
| echo "PR state: $STATE, Mergeable: $MERGEABLE" | ||
| if [ "$STATE" = "MERGED" ]; then | ||
| echo "PR merged successfully!" | ||
| break | ||
| fi | ||
| PENDING_CHECKS=$(echo "$PR_DATA" | jq '[.statusCheckRollup[] | select(.status == "IN_PROGRESS" or .status == "QUEUED" or .status == "PENDING")] | length') | ||
| TOTAL_CHECKS=$(echo "$PR_DATA" | jq '.statusCheckRollup | length') | ||
| echo "Checks: $((TOTAL_CHECKS - PENDING_CHECKS))/$TOTAL_CHECKS complete" | ||
| if [ "$PENDING_CHECKS" -eq 0 ] && [ "$TOTAL_CHECKS" -gt 0 ]; then | ||
| FAILED_CHECKS=$(echo "$PR_DATA" | jq -r '.statusCheckRollup[] | select(.conclusion == "FAILURE" or .conclusion == "CANCELLED") | .name') | ||
| if [ -n "$FAILED_CHECKS" ]; then | ||
| echo "ERROR: Some checks failed:" | ||
| echo "$FAILED_CHECKS" | ||
| exit 1 | ||
| fi | ||
| fi | ||
| sleep $INTERVAL | ||
| ELAPSED=$((ELAPSED + INTERVAL)) | ||
| done | ||
| if [ "$STATE" != "MERGED" ]; then | ||
| echo "ERROR: PR did not merge within timeout" | ||
| exit 1 | ||
| fi | ||
| - name: Checkout main and create tag | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| git checkout main | ||
| git pull origin main | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| # Delete existing tag if present (from a previous failed run) | ||
| git tag -d "v${VERSION}" 2>/dev/null || true | ||
| git push origin --delete "v${VERSION}" 2>/dev/null || true | ||
| git tag -a "v${VERSION}" -m "Release version ${VERSION}" | ||
| git push origin "v${VERSION}" | ||
| - name: Install azd | ||
| run: curl -fsSL https://aka.ms/install-azd.sh | bash | ||
| - name: Install azd extensions | ||
| run: | | ||
| azd extension source add azd --location https://aka.ms/azd/extensions/registry --type url 2>/dev/null || true | ||
| azd extension install microsoft.azd.extensions --source azd | ||
| - name: Build binaries | ||
| working-directory: cli | ||
| run: | | ||
| export EXTENSION_ID="jongio.azd.rest" | ||
| export EXTENSION_VERSION="${{ steps.version.outputs.next }}" | ||
| azd x build --all | ||
| - name: Package | ||
| working-directory: cli | ||
| run: azd x pack | ||
| - name: Extract release notes | ||
| id: release_notes | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| awk ' | ||
| BEGIN { in_section = 0 } | ||
| /^## \['"$VERSION"'\]/ { in_section = 1; next } | ||
| /^## \[/ { in_section = 0 } | ||
| in_section && NF > 0 { print } | ||
| ' CHANGELOG.md > /tmp/release-notes.md | ||
| echo "Release notes for v$VERSION:" | ||
| cat /tmp/release-notes.md | ||
| - name: Release | ||
| working-directory: cli | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| TAG_NAME="azd-ext-jongio-azd-rest_${VERSION}" | ||
| # Delete existing release if present (from a previous failed run) | ||
| gh release delete "$TAG_NAME" --yes 2>/dev/null || true | ||
| azd x release \ | ||
| --repo "${{ github.repository }}" \ | ||
| --version "$VERSION" \ | ||
| --notes-file /tmp/release-notes.md \ | ||
| --confirm | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Install cosign | ||
| uses: sigstore/cosign-installer@3454372be43e8ddeec39df0f73bb47954da3a1f1 # v3 | ||
| - name: Install syft | ||
| uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0 | ||
| - name: Sign release artifacts with cosign | ||
| working-directory: cli | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| TAG_NAME="azd-ext-jongio-azd-rest_${VERSION}" | ||
| echo "Signing release artifacts for ${TAG_NAME}..." | ||
| # Download release assets | ||
| gh release download "${TAG_NAME}" --dir /tmp/release-assets --repo "${{ github.repository }}" || true | ||
| # Sign each artifact | ||
| if [ -d /tmp/release-assets ]; then | ||
| for file in /tmp/release-assets/*; do | ||
| if [ -f "$file" ]; then | ||
| echo "Signing $(basename $file)..." | ||
| cosign sign-blob --yes "$file" --output-signature "${file}.sig" --output-certificate "${file}.pem" | ||
| fi | ||
| done | ||
| # Upload signatures and certificates to the release | ||
| gh release upload "${TAG_NAME}" /tmp/release-assets/*.sig /tmp/release-assets/*.pem --repo "${{ github.repository }}" || true | ||
| echo "✅ All artifacts signed with cosign (keyless/OIDC)" | ||
| fi | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Generate SBOM | ||
| working-directory: cli | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.next }}" | ||
| TAG_NAME="azd-ext-jongio-azd-rest_${VERSION}" | ||
| echo "Generating SBOM for ${TAG_NAME}..." | ||
| # Generate SBOM for the Go module | ||
| syft . -o spdx-json=/tmp/sbom-spdx.json -o cyclonedx-json=/tmp/sbom-cyclonedx.json | ||
| # Upload SBOM to the release | ||
| gh release upload "${TAG_NAME}" /tmp/sbom-spdx.json /tmp/sbom-cyclonedx.json --repo "${{ github.repository }}" || true | ||
| echo "✅ SBOM generated and uploaded (SPDX + CycloneDX)" | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Update registry | ||
| working-directory: cli | ||
| run: | | ||
| azd x publish \ | ||
| --registry ../registry.json \ | ||
| --version "${{ steps.version.outputs.next }}" \ | ||
| --repo "${{ github.repository }}" | ||
| cd .. | ||
| git config user.name "github-actions[bot]" | ||
| git config user.email "github-actions[bot]@users.noreply.github.com" | ||
| git add registry.json | ||
| if ! git diff --cached --quiet; then | ||
| git commit -m "chore: update registry for v${{ steps.version.outputs.next }}" | ||
| git push | ||
| fi | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||