Skip to content

Refresh cell footer time when cell scrolls into view #2039

Refresh cell footer time when cell scrolls into view

Refresh cell footer time when cell scrolls into view #2039

name: "PR Test Checker"
# Grades whether the PR has adequate test coverage and posts a verdict comment.
# Scope: runs only for PR authors / commenters in the posit-dev `positron-dev`
# team. GitHub Actions `if:` has no team-membership predicate, and the default
# GITHUB_TOKEN cannot read org membership, so a dedicated `gate` job resolves
# membership at runtime via the GitHub API. It mints a short-lived token from
# the "Positron Projects" GitHub App (secrets POSITRON_PROJECTS_CLIENT_ID +
# POSITRON_PROJECTS_PEM, shared with release-generate-sbom.yml) scoped to the
# posit-dev org, which carries the App's `Members: read` permission, and
# exposes an `ok` output the grading jobs depend on via `needs`. The gate
# FAILS CLOSED: if the token can't be minted or any API call fails (e.g. the
# App is missing `Members: read`), `ok=false` and nothing is graded. Membership
# is always live -- there is no allowlist to maintain. To change who PETE runs
# for, edit the `positron-dev` team on GitHub, not this file.
#
# Trigger recovery: we listen for `opened`, `synchronize`, AND `ready_for_review`
# on `pull_request`, not just `opened`. GitHub occasionally drops `opened`
# deliveries (see #13664, where the `pull_request_target` CLA event fired but
# `pull_request: opened` didn't, leaving PETE with no verdict), so the extra
# types give us a recovery path on the next push or draft->ready transition.
# Observable behavior: PETE grades on PR creation, and only re-grades on
# explicit `/recheck-tests`. To avoid re-grading on every push, the action
# short-circuits any `pull_request`-triggered run when a PETE comment already
# exists on the PR -- `synchronize` and `ready_for_review` therefore only do
# work in the rare case where the initial `opened` was missed. `/recheck-tests`
# (an `issue_comment` event) sets `force-regrade=true` and bypasses the guard.
#
# Security model: each job checks out two trees -- the BASE branch (trusted
# action + skill code, used to run the analyzer with secrets) and the PR HEAD
# (untrusted source code, mounted as read-only data for the agent's
# Read/Grep/Glob tools). The analyzer is invoked from the base checkout via
# `uses: ./base/.github/actions/pr-test-checker` so that PR-head code is never
# executed with secrets in scope. This closes the "pwn request" pattern where
# a fork PR modifies action code, and a positron-dev member comments
# /recheck-tests (an `issue_comment` event that runs in base context with
# full secrets, unlike `pull_request` events which strip secrets for forks).
on:
pull_request:
types:
- opened
- synchronize
- ready_for_review
issue_comment:
types:
- created
jobs:
# Resolve positron-dev team membership at runtime. This is a pure GitHub API
# read with a short-lived App token; it checks out no PR code, so it is safe
# to run in base context. Emits `ok=true` only when the relevant user(s) are
# *active* team members, and FAILS CLOSED (`ok=false`) on a token/API error.
# The grading jobs depend on this via `needs: gate`.
gate:
name: Check positron-dev membership
# Cheap event-shape pre-filter so we don't spin up a runner (or hit the API)
# for every PR comment -- only PR events and recheck-command comments on PRs
# reach the membership check below. Recognized recheck commands: /recheck-tests,
# /rePETE, /re-pete (contains() is case-insensitive, so casing doesn't matter).
# NOTE: keep this command list in sync with the on-recheck job's `if` below.
if: |
github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
(contains(github.event.comment.body, '/recheck-tests') ||
contains(github.event.comment.body, '/repete') ||
contains(github.event.comment.body, '/re-pete')))
runs-on: ubuntu-latest
# No GITHUB_TOKEN scopes needed: the check uses the App token in GH_TOKEN.
permissions: {}
concurrency:
group: pr-test-checker-gate-${{ github.event.pull_request.number || github.event.issue.number }}
cancel-in-progress: true
outputs:
ok: ${{ steps.check.outputs.ok }}
steps:
- name: Mint org-scoped App token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.POSITRON_PROJECTS_CLIENT_ID }}
private-key: ${{ secrets.POSITRON_PROJECTS_PEM }}
owner: posit-dev
- name: Check team membership
id: check
env:
# Short-lived token from the Positron Projects GitHub App, scoped to
# the posit-dev org. Reading team membership needs the App's
# `Members: read` permission; without it the gh calls 404 and the gate
# stays ok=false -- fail closed.
GH_TOKEN: ${{ steps.app-token.outputs.token }}
EVENT_NAME: ${{ github.event_name }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
COMMENTER: ${{ github.event.comment.user.login }}
ISSUE_AUTHOR: ${{ github.event.issue.user.login }}
run: |
set -uo pipefail
# Active member -> HTTP 200 {"state":"active"}; non-member -> 404
# (gh exits non-zero, stdout empty). Pending invite -> "pending".
is_member() {
local state
state=$(gh api "orgs/posit-dev/teams/positron-dev/memberships/$1" --jq '.state' 2>/dev/null)
[ "$state" = "active" ]
}
ok=false
if [ "$EVENT_NAME" = "pull_request" ]; then
# on-open: the PR author must be a team member.
if is_member "$PR_AUTHOR"; then
ok=true
fi
else
# on-recheck: BOTH the commenter and the PR author must be members,
# so an attacker can't bait /recheck-tests by commenting on a PR
# whose author is outside the team.
if is_member "$COMMENTER" && is_member "$ISSUE_AUTHOR"; then
ok=true
fi
fi
echo "Membership gate result: ok=$ok"
echo "ok=$ok" >> "$GITHUB_OUTPUT"
on-open:
name: Grade on PR change
needs: gate
if: |
github.event_name == 'pull_request' &&
needs.gate.outputs.ok == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: pr-test-checker-${{ github.event.pull_request.number }}
cancel-in-progress: true
steps:
- name: Checkout BASE (trusted action + skill code)
uses: actions/checkout@v6
with:
ref: ${{ github.event.repository.default_branch }}
path: base
sparse-checkout: |
.claude/skills/pr-test-checker
.claude/rules
.github/actions/pr-test-checker
- name: Checkout PR HEAD (untrusted source data)
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
path: pr-head
sparse-checkout: |
CLAUDE.md
src
extensions
test/e2e
- name: Load Anthropic API key
uses: 1password/load-secrets-action@v4
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
ANTHROPIC_KEY: "op://Positron/Anthropic/credential"
- name: Run pr-test-checker (from base, source from PR head)
uses: ./base/.github/actions/pr-test-checker
with:
pr-number: ${{ github.event.pull_request.number }}
anthropic-api-key: ${{ env.ANTHROPIC_KEY }}
repo-root: ${{ github.workspace }}/pr-head
on-recheck:
name: Re-grade on recheck command
needs: gate
# Fires when a positron-dev member comments a recheck command (/recheck-tests,
# /rePETE, /re-pete) on a PR. The issue_comment event runs in base-repo context
# with full secrets even when the PR is from a fork, so two layers of defense:
# 1. The `gate` job requires BOTH the commenter AND the PR author to be
# positron-dev members (the PR-author check blocks comments on fork
# PRs by non-members -- attackers can't bait a recheck on a PR
# whose author is outside the team).
# 2. The job checks out the base branch to RUN the action and the
# PR head only as READ-ONLY DATA -- PR-head code never executes.
# NOTE: keep the recheck-command list in sync with the gate job's `if` above.
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request != null &&
(contains(github.event.comment.body, '/recheck-tests') ||
contains(github.event.comment.body, '/repete') ||
contains(github.event.comment.body, '/re-pete')) &&
needs.gate.outputs.ok == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
issues: write
concurrency:
group: pr-test-checker-${{ github.event.issue.number }}
cancel-in-progress: true
steps:
# Acknowledge the recheck command with an "eyes" reaction so the commenter
# gets immediate visual confirmation that PETE picked it up and is running.
# First step so it lands before the slower checkout/analysis steps. Capture
# the reaction id so the finalize step can remove it once PETE is done.
- name: Acknowledge recheck command
id: ack
env:
GH_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
COMMENT_ID: ${{ github.event.comment.id }}
run: |
REACTION_ID=$(gh api --method POST \
"repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}/reactions" \
-f content=eyes --jq '.id' 2>/dev/null) || echo "Failed to add reaction (non-fatal)"
echo "reaction_id=${REACTION_ID}" >> "$GITHUB_OUTPUT"
- name: Resolve PR head SHA
id: pr
env:
GH_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.issue.number }}
run: |
HEAD_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}" --jq '.head.sha')
echo "head_sha=${HEAD_SHA}" >> "$GITHUB_OUTPUT"
- name: Checkout BASE (trusted action + skill code)
uses: actions/checkout@v6
with:
ref: ${{ github.event.repository.default_branch }}
path: base
sparse-checkout: |
.claude/skills/pr-test-checker
.claude/rules
.github/actions/pr-test-checker
- name: Checkout PR HEAD (untrusted source data)
uses: actions/checkout@v6
with:
ref: ${{ steps.pr.outputs.head_sha }}
path: pr-head
sparse-checkout: |
CLAUDE.md
src
extensions
test/e2e
- name: Load Anthropic API key
uses: 1password/load-secrets-action@v4
with:
export-env: true
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
ANTHROPIC_KEY: "op://Positron/Anthropic/credential"
- name: Run pr-test-checker (from base, source from PR head)
uses: ./base/.github/actions/pr-test-checker
with:
pr-number: ${{ github.event.issue.number }}
anthropic-api-key: ${{ env.ANTHROPIC_KEY }}
repo-root: ${{ github.workspace }}/pr-head
force-regrade: "true"
# Replace the "eyes" acknowledgement with a terminal reaction once PETE
# finishes: rocket on success, confused on failure. Runs on always() so the
# comment never gets stuck showing "running". Skipped if the ack step never
# recorded a reaction id (e.g. the initial reaction POST failed).
- name: Finalize recheck reaction
if: always() && steps.ack.outputs.reaction_id != ''
env:
GH_TOKEN: ${{ github.token }}
GITHUB_REPOSITORY: ${{ github.repository }}
COMMENT_ID: ${{ github.event.comment.id }}
REACTION_ID: ${{ steps.ack.outputs.reaction_id }}
JOB_STATUS: ${{ job.status }}
run: |
# Remove the "eyes" acknowledgement reaction.
gh api --method DELETE \
"repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}/reactions/${REACTION_ID}" \
|| echo "Failed to remove eyes reaction (non-fatal)"
# Signal completion: rocket on success, confused otherwise.
if [ "$JOB_STATUS" = "success" ]; then
FINAL=rocket
else
FINAL=confused
fi
gh api --method POST \
"repos/${GITHUB_REPOSITORY}/issues/comments/${COMMENT_ID}/reactions" \
-f content="$FINAL" || echo "Failed to add ${FINAL} reaction (non-fatal)"