ci: bump actions/download-artifact from 4.3.0 to 8.0.1 #177
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: PR Build | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: | |
| - completed | |
| # Removed branches filter - run for all branches to catch PR updates | |
| pull_request_target: | |
| branches: [ main ] | |
| types: [labeled, closed] | |
| push: | |
| branches: [ prbuild ] | |
| paths: | |
| - 'cli/**' | |
| - '.github/workflows/pr-build.yml' | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to build' | |
| required: false | |
| type: number | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| working-directory: cli | |
| env: | |
| GO_VERSION: '1.26.1' | |
| jobs: | |
| # Check if build should run | |
| check-permission: | |
| name: Check Build Permission | |
| runs-on: ubuntu-latest | |
| # Only run if: | |
| # 1. CI workflow succeeded, OR | |
| # Only run if: | |
| # 1. CI workflow succeeded, OR | |
| # 2. Manual trigger via workflow_dispatch, OR | |
| # 3. PR labeled with 'safe-to-build', OR | |
| # 4. Push to prbuild branch (for testing) | |
| if: | | |
| github.event_name == 'workflow_dispatch' || | |
| github.event_name == 'pull_request_target' || | |
| github.event_name == 'push' || | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') | |
| outputs: | |
| allowed: ${{ steps.check.outputs.allowed }} | |
| pr_number: ${{ steps.check.outputs.pr_number }} | |
| pr_sha: ${{ steps.check.outputs.pr_sha }} | |
| steps: | |
| - name: Check if build is allowed | |
| id: check | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 | |
| with: | |
| script: | | |
| let allowed = false; | |
| let prNumber = null; | |
| let prSha = null; | |
| // Workflow dispatch - always allowed | |
| if (context.eventName === 'workflow_dispatch') { | |
| allowed = true; | |
| prNumber = context.payload.inputs.pr_number; | |
| if (prNumber) { | |
| const pr = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| prSha = pr.data.head.sha; | |
| } | |
| core.setOutput('allowed', 'true'); | |
| core.setOutput('pr_number', prNumber || ''); | |
| core.setOutput('pr_sha', prSha || ''); | |
| return; | |
| } | |
| // push event (for testing on prbuild branch) | |
| if (context.eventName === 'push') { | |
| allowed = true; | |
| // Find PR for this branch | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| head: `${context.repo.owner}:${context.ref.replace('refs/heads/', '')}` | |
| }); | |
| if (prs.length > 0) { | |
| prNumber = prs[0].number; | |
| prSha = prs[0].head.sha; | |
| } | |
| core.setOutput('allowed', 'true'); | |
| core.setOutput('pr_number', prNumber || ''); | |
| core.setOutput('pr_sha', prSha || ''); | |
| return; | |
| } | |
| // workflow_run - triggered after CI passes | |
| if (context.eventName === 'workflow_run') { | |
| // Get the PR associated with the workflow run | |
| const { data: prs } = await github.rest.pulls.list({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: 'open', | |
| head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}` | |
| }); | |
| if (prs.length > 0) { | |
| const pr = prs[0]; | |
| const association = pr.author_association; | |
| // Check if trusted contributor | |
| const trustedAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR']; | |
| if (trustedAssociations.includes(association)) { | |
| allowed = true; | |
| prNumber = pr.number; | |
| prSha = pr.head.sha; | |
| } else { | |
| // For first-time contributors, check if they have the label | |
| const hasLabel = pr.labels.some(label => label.name === 'safe-to-build'); | |
| if (hasLabel) { | |
| allowed = true; | |
| prNumber = pr.number; | |
| prSha = pr.head.sha; | |
| } | |
| } | |
| } | |
| } | |
| // pull_request_target with 'safe-to-build' label | |
| if (context.eventName === 'pull_request_target') { | |
| const hasLabel = context.payload.pull_request.labels.some( | |
| label => label.name === 'safe-to-build' | |
| ); | |
| if (hasLabel) { | |
| allowed = true; | |
| prNumber = context.payload.pull_request.number; | |
| prSha = context.payload.pull_request.head.sha; | |
| } | |
| } | |
| core.setOutput('allowed', allowed ? 'true' : 'false'); | |
| core.setOutput('pr_number', prNumber || ''); | |
| core.setOutput('pr_sha', prSha || ''); | |
| if (!allowed) { | |
| core.notice('Build skipped - requires maintainer approval. Add "safe-to-build" label to proceed.'); | |
| } | |
| build-pr: | |
| name: Build PR Preview | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| needs: check-permission | |
| if: needs.check-permission.outputs.allowed == 'true' | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - name: Get PR details | |
| id: pr | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 | |
| with: | |
| script: | | |
| const prNumber = '${{ needs.check-permission.outputs.pr_number }}' || context.payload.pull_request.number; | |
| const pr = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| core.setOutput('number', prNumber); | |
| core.setOutput('sha', pr.data.head.sha); | |
| core.setOutput('ref', pr.data.head.ref); | |
| core.setOutput('title', pr.data.title); | |
| - name: Checkout code | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| ref: ${{ steps.pr.outputs.sha }} | |
| - 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 PR version | |
| id: version | |
| working-directory: cli | |
| run: | | |
| BASE_VERSION=$(grep '^version:' extension.yaml | awk '{print $2}') | |
| PR_NUMBER="${{ steps.pr.outputs.number }}" | |
| PR_VERSION="${BASE_VERSION}-pr${PR_NUMBER}" | |
| # Use the standard azd extension tag format so azd x publish generates correct URLs | |
| STANDARD_TAG="azd-ext-jongio-azd-exec_${PR_VERSION}" | |
| echo "version=$PR_VERSION" >> $GITHUB_OUTPUT | |
| echo "base_version=$BASE_VERSION" >> $GITHUB_OUTPUT | |
| echo "tag=$STANDARD_TAG" >> $GITHUB_OUTPUT | |
| echo "Building version: $PR_VERSION with tag: $STANDARD_TAG" | |
| - name: Install azd | |
| run: curl -fsSL https://aka.ms/install-azd.sh | bash | |
| - name: Install azd extensions | |
| run: | | |
| # Add the official azd extensions registry source | |
| 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: Update extension.yaml with PR version | |
| working-directory: cli | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| # Temporarily update version (won't commit) | |
| sed -i "s/^version: .*/version: ${VERSION}/" extension.yaml | |
| - name: Build binaries | |
| working-directory: cli | |
| run: | | |
| export EXTENSION_ID="jongio.azd.exec" | |
| export EXTENSION_VERSION="${{ steps.version.outputs.version }}" | |
| azd x build --all | |
| - name: Package | |
| working-directory: cli | |
| run: azd x pack | |
| - name: Create PR pre-release | |
| working-directory: cli | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| TAG="azd-ext-jongio-azd-exec_${VERSION}" | |
| PR_NUM="${{ steps.pr.outputs.number }}" | |
| # Delete existing release if it exists (idempotent for re-runs) | |
| gh release delete "$TAG" --repo "${{ github.repository }}" --yes 2>/dev/null || true | |
| # Create pre-release with all binaries (same pattern as release.yml but with --prerelease) | |
| gh release create "$TAG" \ | |
| --repo "${{ github.repository }}" \ | |
| --title "PR #${PR_NUM} Preview (v${VERSION})" \ | |
| --notes "PR #${PR_NUM} preview build. Test using the one-line installer from the PR comment." \ | |
| --prerelease \ | |
| ~/.azd/registry/jongio.azd.exec/${VERSION}/* | |
| - name: Update registry | |
| working-directory: cli | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| # Generate registry (saves to /tmp/pr-registry.json for the install scripts) | |
| echo '{"extensions":[]}' > /tmp/pr-registry.json | |
| azd x publish \ | |
| --registry /tmp/pr-registry.json \ | |
| --version "$VERSION" \ | |
| --repo "${{ github.repository }}" | |
| # Upload registry to the release so install scripts can download it | |
| TAG="azd-ext-jongio-azd-exec_${VERSION}" | |
| gh release upload "$TAG" --repo "${{ github.repository }}" /tmp/pr-registry.json --clobber | |
| - name: Generate installation instructions | |
| id: instructions | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| PR_NUM="${{ steps.pr.outputs.number }}" | |
| TAG="${{ steps.version.outputs.tag }}" | |
| REPO="${{ github.repository }}" | |
| COMMIT="${{ steps.pr.outputs.sha }}" | |
| SHORT_COMMIT=$(echo $COMMIT | cut -c1-7) | |
| # Use the branch where the scripts actually exist | |
| BRANCH="${{ github.ref_name }}" | |
| WEBSITE_URL="https://jongio.github.io/azd-exec/pr/$PR_NUM/" | |
| cat > ../instructions.md <<EOF | |
| ## 🚀 Test This PR | |
| A preview build (\`$VERSION\`) is ready for testing! | |
| ### 🌐 Website Preview | |
| **Live Preview:** [$WEBSITE_URL]($WEBSITE_URL) | |
| ### One-Line Install (Recommended) | |
| **PowerShell (Windows):** | |
| \`\`\`powershell | |
| iex "& { \$(irm https://raw.githubusercontent.com/$REPO/$BRANCH/cli/scripts/install-pr.ps1) } -PrNumber $PR_NUM -Version $VERSION" | |
| \`\`\` | |
| **Bash (macOS/Linux):** | |
| \`\`\`bash | |
| curl -fsSL https://raw.githubusercontent.com/$REPO/$BRANCH/cli/scripts/install-pr.sh | bash -s $PR_NUM $VERSION | |
| \`\`\` | |
| ### Uninstall | |
| When you're done testing: | |
| **PowerShell (Windows):** | |
| \`\`\`powershell | |
| iex "& { \$(irm https://raw.githubusercontent.com/$REPO/$BRANCH/cli/scripts/uninstall-pr.ps1) } -PrNumber $PR_NUM" | |
| \`\`\` | |
| **Bash (macOS/Linux):** | |
| \`\`\`bash | |
| curl -fsSL https://raw.githubusercontent.com/$REPO/$BRANCH/cli/scripts/uninstall-pr.sh | bash -s $PR_NUM | |
| \`\`\` | |
| --- | |
| **Build Info:** | |
| - **Version:** \`$VERSION\` | |
| - **Commit:** \`$SHORT_COMMIT\` | |
| - **Release:** [View pre-release](https://github.com/$REPO/releases/tag/$TAG) | |
| **What to Test:** | |
| Please review the PR description and test the changes described there. | |
| EOF | |
| - name: Comment on PR | |
| uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const instructions = fs.readFileSync('instructions.md', 'utf8'); | |
| const prNumber = '${{ steps.pr.outputs.number }}'; | |
| // Find existing comment | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| }); | |
| const botComment = comments.data.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('🚀 Test This PR') | |
| ); | |
| if (botComment) { | |
| // Update existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: instructions | |
| }); | |
| console.log('Updated existing comment'); | |
| } else { | |
| // Create new comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: prNumber, | |
| body: instructions | |
| }); | |
| console.log('Created new comment'); | |
| } | |
| # Cleanup job - removes registry releases when PR closes | |
| cleanup: | |
| name: Cleanup PR Registry | |
| runs-on: ubuntu-latest | |
| if: github.event.action == 'closed' && github.event_name == 'pull_request_target' | |
| permissions: | |
| contents: write | |
| defaults: | |
| run: | |
| working-directory: . | |
| steps: | |
| - name: Delete PR registry release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| PR_NUM=${{ github.event.pull_request.number }} | |
| # Find and delete releases matching this PR | |
| gh release list --repo ${{ github.repository }} --json tagName,name --limit 100 | \ | |
| jq -r ".[] | select(.tagName | contains(\"-pr${PR_NUM}\")) | .tagName" | \ | |
| while read tag; do | |
| echo "Deleting release: $tag" | |
| gh release delete "$tag" --repo ${{ github.repository }} --yes || true | |
| # Delete tag | |
| git push --delete origin "$tag" 2>/dev/null || true | |
| done |