diff --git a/.github/workflows/ci-deploy.yml b/.github/workflows/ci-deploy.yml new file mode 100644 index 0000000..5999af7 --- /dev/null +++ b/.github/workflows/ci-deploy.yml @@ -0,0 +1,132 @@ +name: CI + Deploy (prebuilt) + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +# Minimal permissions for posting PR comments and (future) deployments API +permissions: + contents: read + issues: write + pull-requests: write + deployments: write + +env: + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + VERCEL_ORG: ${{ secrets.VERCEL_ORG_ID }} + +jobs: + build_and_test: + runs-on: ubuntu-latest + steps: + # Check out repository + - uses: actions/checkout@v4 + + # Install Node and enable npm cache + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + # Install deps (prefer CI flow if lockfile exists) + - name: Install + run: npm ci || npm install + + # Lint if a "lint" script exists + - name: Lint + run: npm run -s | grep -qE '(^| )lint( |:)' && npm run lint || echo "No lint script" + + # Unit tests if a "test" script exists + - name: Unit tests + run: npm run -s | grep -qE '(^| )test( |:)' && npm test --ci --passWithNoTests=false || echo "No test script" + + # E2E tests if an "e2e" script exists + - name: E2E tests (optional) + run: npm run -s | grep -qE '(^| )e2e( |:)' && npm run e2e || echo "No e2e script" + + # Project build (your app’s own build step) + - name: App build + run: npm run build + + # Short success note in the PR checks summary + - name: Build summary + run: echo "Build & tests passed ✅" >> "$GITHUB_STEP_SUMMARY" + + deploy: + needs: build_and_test + if: ${{ success() }} + runs-on: ubuntu-latest + steps: + # Check out repository for deploy context + - uses: actions/checkout@v4 + + # Install Node for vercel CLI + - uses: actions/setup-node@v4 + with: + node-version: 18 + cache: 'npm' + + # Install Vercel CLI (latest) + - name: Install Vercel CLI + run: npm i -g vercel@latest + + # Decide Vercel environment: preview for PRs, production for main + - name: Decide target + id: tgt + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + echo "target=preview" >> $GITHUB_OUTPUT + else + echo "target=production" >> $GITHUB_OUTPUT + fi + + # Pull project settings and envs for the chosen environment + - name: Pull Vercel project settings + run: | + vercel pull --yes \ + --environment "${{ steps.tgt.outputs.target }}" \ + --token "${{ env.VERCEL_TOKEN }}" \ + --scope "${{ env.VERCEL_ORG }}" + + # Build a prebuilt artifact into .vercel/output + - name: Vercel prebuild + run: | + vercel build \ + --token "${{ env.VERCEL_TOKEN }}" \ + --scope "${{ env.VERCEL_ORG }}" + + # Deploy prebuilt artifact (no build on Vercel) + - name: Deploy (prebuilt) + id: deploy + env: + VC_TOKEN: ${{ env.VERCEL_TOKEN }} + VC_TEAM: ${{ env.VERCEL_ORG }} + TARGET: ${{ steps.tgt.outputs.target }} + run: | + set -e + ARGS=(deploy --yes --token "$VC_TOKEN" --scope "$VC_TEAM" --prebuilt) + [ "$TARGET" = "production" ] && ARGS+=(--prod) || true + URL="$(vercel "${ARGS[@]}")" + echo "url=$URL" >> "$GITHUB_OUTPUT" + echo "Deployed: $URL" + + # Put target and URL into the PR checks summary for quick access + - name: Summary + run: | + echo "### Deployment" >> "$GITHUB_STEP_SUMMARY" + echo "- Target: **${{ steps.tgt.outputs.target }}**" >> "$GITHUB_STEP_SUMMARY" + echo "- URL: ${{ steps.deploy.outputs.url }}" >> "$GITHUB_STEP_SUMMARY" + + # Comment the preview link on PRs so reviewers always see the latest link + - name: Post Preview URL to PR + if: ${{ github.event_name == 'pull_request' && steps.deploy.outputs.url != '' }} + uses: actions/github-script@v7 + with: + script: | + await github.rest.issues.createComment({ + ...context.repo, + issue_number: context.payload.pull_request.number, + body: `✅ Preview ready: ${{ steps.deploy.outputs.url }}` + }) \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 90b67d9..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: CI - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node.js - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: npm - - - name: Install dependencies - run: | - if [ -f package-lock.json ]; then - npm ci - else - npm install - fi - - - name: Validate BUILD_RESULT - env: - BUILD_RESULT: ${{ secrets.BUILD_RESULT }} - run: | - if [ -z "${BUILD_RESULT}" ]; then - echo "BUILD_RESULT is empty." - exit 1 - else - echo "BUILD_RESULT is set." - fi - - - name: Run build - env: - BUILD_RESULT: ${{ secrets.BUILD_RESULT }} - run: npm run build diff --git a/.github/workflows/fetch-vercel-logs.yml b/.github/workflows/fetch-vercel-logs.yml deleted file mode 100644 index aee8977..0000000 --- a/.github/workflows/fetch-vercel-logs.yml +++ /dev/null @@ -1,144 +0,0 @@ -name: Fetch Vercel Logs - -on: - # This enables the "Run workflow" button in GitHub Actions UI - workflow_dispatch: - inputs: - pr: - description: 'Pull Request number (optional)' - required: false - sha: - description: 'Commit SHA (optional, overrides PR if set)' - required: false - -permissions: - contents: read - pull-requests: write # required to add a comment in PRs - -jobs: - fetch: - runs-on: ubuntu-latest - env: - # Secrets stored in GitHub → Settings → Secrets and variables → Actions - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - VERCEL_PROJECT: ${{ secrets.VERCEL_PROJECT_ID }} - VERCEL_ORG: ${{ secrets.VERCEL_ORG_ID }} - - steps: - - uses: actions/checkout@v4 - - # Step 1: Resolve PR number and Commit SHA - - name: Resolve PR number and SHA - id: ctx - shell: bash - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - PR_INPUT="${{ github.event.inputs.pr }}" - SHA_INPUT="${{ github.event.inputs.sha }}" - - # If SHA provided manually, use it - if [ -n "$SHA_INPUT" ]; then - echo "sha=$SHA_INPUT" >> $GITHUB_OUTPUT - else - # If PR number provided, fetch its HEAD SHA - if [ -n "$PR_INPUT" ]; then - SHA=$(gh pr view "$PR_INPUT" --json headRefOid --jq .headRefOid) - echo "sha=$SHA" >> $GITHUB_OUTPUT - echo "pr=$PR_INPUT" >> $GITHUB_OUTPUT - else - # Try to find PR automatically by current commit - PR=$(gh pr list --search "${{ github.sha }}" --json number --jq '.[0].number' || true) - if [ -n "$PR" ] && [ "$PR" != "null" ]; then - SHA=$(gh pr view "$PR" --json headRefOid --jq .headRefOid) - echo "pr=$PR" >> $GITHUB_OUTPUT - echo "sha=$SHA" >> $GITHUB_OUTPUT - else - # Fallback: just use current commit SHA - echo "sha=${{ github.sha }}" >> $GITHUB_OUTPUT - fi - fi - fi - - # Step 2: Find latest Vercel deployment for this PR/commit - - name: Find Vercel deployment - id: dep - shell: bash - run: | - set -e - test -n "$VERCEL_TOKEN" || { echo "VERCEL_TOKEN is empty"; exit 1; } - test -n "$VERCEL_PROJECT" || { echo "VERCEL_PROJECT_ID is empty"; exit 1; } - test -n "$VERCEL_ORG" || { echo "VERCEL_ORG_ID is empty"; exit 1; } - - # Get list of latest preview deployments for the project - curl -sS -H "Authorization: Bearer $VERCEL_TOKEN" \ - "https://api.vercel.com/v6/deployments?projectId=$VERCEL_PROJECT&target=preview&limit=50" \ - > deployments.json - - # Prefer to match by PR number - DEP_ID=$(jq -r --arg PR "${{ steps.ctx.outputs.pr }}" '.deployments[] - | select(.meta.githubPrId == $PR) | .uid' deployments.json | head -n1) - - # If not found, try to match by commit SHA - if [ -z "$DEP_ID" ] || [ "$DEP_ID" = "null" ]; then - DEP_ID=$(jq -r --arg SHA "${{ steps.ctx.outputs.sha }}" '.deployments[] - | select(.meta.githubCommitSha == $SHA) | .uid' deployments.json | head -n1) - fi - - # If still not found, fail - if [ -z "$DEP_ID" ] || [ "$DEP_ID" = "null" ]; then - echo "No deployment found for this PR/SHA"; exit 1; - fi - - echo "id=$DEP_ID" >> $GITHUB_OUTPUT - - # Step 3: Fetch deployment logs (events) and convert to plain text - - name: Fetch logs (events → text) - shell: bash - run: | - curl -sS -H "Authorization: Bearer $VERCEL_TOKEN" \ - "https://api.vercel.com/v2/deployments/${{ steps.dep.outputs.id }}/events?orgId=$VERCEL_ORG" \ - > vercel-events.json - - # Extract only text log lines from events - jq -r '.events[] | .payload.text // empty' vercel-events.json > vercel-build.log || true - - # Prepare a short tail for PR comment (last 120 lines) - tail -n 120 vercel-build.log > vercel-build-tail.txt || true - - # Step 4: Upload full log file as artifact - - name: Upload full log - uses: actions/upload-artifact@v4 - with: - name: vercel-build.log - path: vercel-build.log - if-no-files-found: ignore - - # Step 5: Post log tail as a PR comment (only if PR number is known) - - name: Comment tail to PR - if: ${{ steps.ctx.outputs.pr != '' }} - uses: actions/github-script@v7 - with: - script: | - const fs = require('fs'); - const pr = Number('${{ steps.ctx.outputs.pr }}'); - const dep = '${{ steps.dep.outputs.id }}'; - let tail = '(no log lines)'; - try { tail = fs.readFileSync('vercel-build-tail.txt','utf8'); } catch {} - - const body = [ - `❌ Vercel deployment **${dep}** failed (PR #${pr})`, - '', - 'Last 120 lines:', - '```', - tail || '(empty)', - '```', - '📎 Full log attached as artifact (vercel-build.log).' - ].join('\n'); - - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: pr, - body - }) diff --git a/index.js b/index.js index 12104bd..dfea677 100644 --- a/index.js +++ b/index.js @@ -5,4 +5,4 @@ require("dotenv").config(); process.exit(0); } -throw new Error("Build failed"); +//throw new Error("Build failed"); diff --git a/public/index.html b/public/index.html index 9c9eb81..7db3af1 100644 --- a/public/index.html +++ b/public/index.html @@ -6,5 +6,6 @@

Hello from build-test

+

2.0 v