fix: carry forward high court monthly metrics by active publication lineage (#307) #833
Workflow file for this run
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: CI | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - "phase-*" | |
| - "implement-*" | |
| pull_request: | |
| types: | |
| - opened | |
| - synchronize | |
| - reopened | |
| permissions: | |
| contents: read | |
| jobs: | |
| secret-scan: | |
| runs-on: ubuntu-latest | |
| env: | |
| GITLEAKS_VERSION: 8.30.1 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| with: | |
| fetch-depth: 0 | |
| - name: Install gitleaks CLI | |
| run: | | |
| curl -fsSL \ | |
| "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \ | |
| -o "$RUNNER_TEMP/gitleaks.tar.gz" | |
| tar -xzf "$RUNNER_TEMP/gitleaks.tar.gz" -C "$RUNNER_TEMP" | |
| chmod +x "$RUNNER_TEMP/gitleaks" | |
| - name: Scan for committed secrets | |
| run: | | |
| "$RUNNER_TEMP/gitleaks" git . \ | |
| --config .gitleaks.toml \ | |
| --no-banner \ | |
| --redact | |
| verify: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Set up Node.js | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Install Rollup Linux binary | |
| run: npm install --no-save @rollup/rollup-linux-x64-gnu | |
| - name: Install Playwright Chromium | |
| run: npx playwright install --with-deps chromium | |
| - name: Typecheck | |
| run: npm run typecheck | |
| - name: Unit and integration tests | |
| run: npm test | |
| - name: Start local persistent stack | |
| run: npm run docker:up | |
| - name: Persistent stack replay and rollback tests | |
| run: npm run test:persistent | |
| env: | |
| RUN_PERSISTENT_STACK_TESTS: "1" | |
| DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/postgres | |
| AWS_REGION: ap-south-1 | |
| AWS_ENDPOINT_URL_S3: http://127.0.0.1:4566 | |
| AWS_S3_FORCE_PATH_STYLE: "true" | |
| AWS_ACCESS_KEY_ID: test | |
| AWS_SECRET_ACCESS_KEY: test | |
| OPERATOR_API_TOKEN: operator-test-token | |
| - name: Browser E2E tests | |
| run: npm run test:e2e | |
| - name: Install Lighthouse CI | |
| run: npm install --no-save @lhci/cli | |
| - name: Start E2E server for Lighthouse | |
| run: | | |
| NODE_ENV=test E2E_PORT=4211 npx tsx tests/e2e/test-server.ts & | |
| echo $! > /tmp/lhci-server.pid | |
| for i in $(seq 1 30); do curl -sf http://127.0.0.1:4211/health && break || sleep 1; done | |
| env: | |
| DATABASE_URL: postgres://postgres:postgres@127.0.0.1:5432/postgres | |
| AWS_REGION: ap-south-1 | |
| AWS_ENDPOINT_URL_S3: http://127.0.0.1:4566 | |
| AWS_S3_FORCE_PATH_STYLE: "true" | |
| AWS_ACCESS_KEY_ID: test | |
| AWS_SECRET_ACCESS_KEY: test | |
| OPERATOR_API_TOKEN: operator-test-token | |
| - name: Run Lighthouse CI | |
| run: npx lhci autorun --config=.lighthouserc.cjs || echo "Lighthouse warnings present — not blocking" | |
| - name: Stop E2E server | |
| if: always() | |
| run: | | |
| if [ -f /tmp/lhci-server.pid ]; then | |
| kill "$(cat /tmp/lhci-server.pid)" 2>/dev/null || true | |
| fi | |
| deploy: | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| needs: | |
| - secret-scan | |
| - verify | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: deploy-main | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| id-token: write | |
| env: | |
| AWS_REGION: ap-south-1 | |
| AWS_ACCOUNT_ID: "723951822728" | |
| ECR_REPOSITORY: nyaaywatch-staging | |
| PRODUCTION_STACK_NAME: nyaaywatch-production | |
| STATE_INTERNAL_FETCH_SCHEDULE_EXPRESSION: "cron(0 8 * * ? *)" | |
| STATE_INTERNAL_FETCH_SCHEDULE_TIMEZONE: Asia/Kolkata | |
| STATE_INTERNAL_FETCH_SCHEDULE_STATE: ENABLED | |
| SUPREME_COURT_INTERNAL_FETCH_SCHEDULE_EXPRESSION: "cron(10 8 * * ? *)" | |
| SUPREME_COURT_INTERNAL_FETCH_SCHEDULE_TIMEZONE: Asia/Kolkata | |
| SUPREME_COURT_INTERNAL_FETCH_SCHEDULE_STATE: ENABLED | |
| HIGH_COURT_INTERNAL_FETCH_SCHEDULE_EXPRESSION: "cron(20 8 * * ? *)" | |
| HIGH_COURT_INTERNAL_FETCH_SCHEDULE_TIMEZONE: Asia/Kolkata | |
| HIGH_COURT_INTERNAL_FETCH_SCHEDULE_STATE: ENABLED | |
| INTERNAL_FETCH_MANAGE_IAM: never | |
| INTERNAL_FETCH_SCHEDULER_ROLE_ARN: arn:aws:iam::723951822728:role/nyaaywatch-production-internal-fetch-scheduler | |
| PUBLIC_BASE_URL: https://nyaaywatch.in | |
| CLOUDFLARE_ZONE_NAME: nyaaywatch.in | |
| CLOUDFLARE_API_TOKEN_SECRET_ARN: ${{ secrets.CLOUDFLARE_API_TOKEN_SECRET_ARN }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 | |
| with: | |
| aws-region: ${{ env.AWS_REGION }} | |
| role-to-assume: arn:aws:iam::723951822728:role/nyaaywatch-github-deploy-role | |
| - name: Build and push deployment images | |
| env: | |
| IMAGE_SHA: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY }}:${{ github.sha }} | |
| IMAGE_LATEST: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY }}:latest | |
| run: | | |
| chmod +x infra/aws/staging/build-and-push.sh | |
| ./infra/aws/staging/build-and-push.sh "$IMAGE_SHA" "$IMAGE_LATEST" | |
| - name: Roll ECS service to the new image | |
| env: | |
| IMAGE_SHA: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY }}:${{ github.sha }} | |
| run: | | |
| chmod +x infra/aws/staging/redeploy-service.sh | |
| ./infra/aws/staging/redeploy-service.sh "$PRODUCTION_STACK_NAME" "$IMAGE_SHA" | |
| - name: Reconcile daily internal fetch schedule | |
| run: | | |
| chmod +x infra/aws/staging/reconcile-internal-fetch-schedule.sh | |
| ./infra/aws/staging/reconcile-internal-fetch-schedule.sh "$PRODUCTION_STACK_NAME" | |
| preview: | |
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| needs: | |
| - secret-scan | |
| runs-on: ubuntu-latest | |
| concurrency: | |
| group: preview-pr-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| id-token: write | |
| env: | |
| AWS_REGION: ap-south-1 | |
| AWS_ACCOUNT_ID: "723951822728" | |
| ECR_REPOSITORY: nyaaywatch-staging | |
| PREVIEW_SERVICE_NAME: nyaaywatch-pr-${{ github.event.pull_request.number }} | |
| APP_RUNNER_ACCESS_ROLE_ARN: arn:aws:iam::723951822728:role/nyaaywatch-apprunner-ecr-access-role | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 | |
| with: | |
| aws-region: ${{ env.AWS_REGION }} | |
| role-to-assume: arn:aws:iam::723951822728:role/nyaaywatch-github-preview-role | |
| - name: Compute active preview allowlist | |
| id: preview-allowlist | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const fs = require("fs"); | |
| const path = `${process.env.RUNNER_TEMP}/open-preview-services.txt`; | |
| const pulls = await github.paginate(github.rest.pulls.list, { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| state: "open", | |
| per_page: 100, | |
| }); | |
| const lines = pulls.map((pull) => `nyaaywatch-pr-${pull.number}`); | |
| fs.writeFileSync(path, lines.join("\n") + (lines.length > 0 ? "\n" : "")); | |
| core.setOutput("path", path); | |
| - name: Reconcile stale preview services | |
| run: | | |
| chmod +x infra/aws/preview/reconcile-services.sh infra/aws/preview/delete-service.sh | |
| ./infra/aws/preview/reconcile-services.sh "${{ steps.preview-allowlist.outputs.path }}" | |
| - name: Build and push preview image | |
| env: | |
| IMAGE_SHA: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY }}:pr-${{ github.event.pull_request.number }}-${{ github.sha }} | |
| run: | | |
| chmod +x infra/aws/staging/build-and-push.sh | |
| ./infra/aws/staging/build-and-push.sh "$IMAGE_SHA" | |
| - name: Deploy preview service | |
| id: preview | |
| env: | |
| IMAGE_SHA: ${{ env.AWS_ACCOUNT_ID }}.dkr.ecr.${{ env.AWS_REGION }}.amazonaws.com/${{ env.ECR_REPOSITORY }}:pr-${{ github.event.pull_request.number }}-${{ github.sha }} | |
| run: | | |
| chmod +x infra/aws/preview/reconcile-services.sh infra/aws/preview/delete-service.sh infra/aws/preview/deploy-service.sh | |
| deploy_once() { | |
| local stderr_file="$1" | |
| set +e | |
| preview_url="$(./infra/aws/preview/deploy-service.sh "$PREVIEW_SERVICE_NAME" "$IMAGE_SHA" "$APP_RUNNER_ACCESS_ROLE_ARN" 2>"$stderr_file")" | |
| status=$? | |
| set -e | |
| return "$status" | |
| } | |
| final_status="" | |
| final_url="" | |
| if deploy_once preview-stderr.log; then | |
| final_status="ready" | |
| final_url="$preview_url" | |
| else | |
| cat preview-stderr.log >&2 | |
| if grep -q 'ServiceQuotaExceededException' preview-stderr.log; then | |
| ./infra/aws/preview/reconcile-services.sh "${{ steps.preview-allowlist.outputs.path }}" | |
| if deploy_once preview-retry-stderr.log; then | |
| final_status="ready" | |
| final_url="$preview_url" | |
| else | |
| cat preview-retry-stderr.log >&2 | |
| if grep -q 'ServiceQuotaExceededException' preview-retry-stderr.log; then | |
| final_status="quota-exceeded" | |
| final_url="" | |
| else | |
| exit "$status" | |
| fi | |
| fi | |
| else | |
| exit "$status" | |
| fi | |
| fi | |
| echo "status=$final_status" >> "$GITHUB_OUTPUT" | |
| echo "url=$final_url" >> "$GITHUB_OUTPUT" | |
| - name: Comment preview URL | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 | |
| env: | |
| PREVIEW_URL: ${{ steps.preview.outputs.url }} | |
| PREVIEW_STATUS: ${{ steps.preview.outputs.status }} | |
| SERVICE_NAME: ${{ env.PREVIEW_SERVICE_NAME }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const marker = "<!-- nyaaywatch-preview -->"; | |
| const body = | |
| process.env.PREVIEW_STATUS === "quota-exceeded" | |
| ? `${marker} | |
| Preview unavailable: AWS App Runner preview quota is currently full, even after stale preview cleanup and one retry. | |
| Service: \`${process.env.SERVICE_NAME}\` | |
| Mode: fixture-backed public web preview | |
| Status: quota exceeded after reconcile and retry` | |
| : `${marker} | |
| Preview ready: ${process.env.PREVIEW_URL} | |
| Service: \`${process.env.SERVICE_NAME}\` | |
| Mode: fixture-backed public web preview`; | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100, | |
| }); | |
| const existing = comments.find((comment) => comment.body.includes(marker)); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body, | |
| }); | |
| } |