Skip to content

Add production previews to the observability PR preview workflow - #6172

Open
backspace wants to merge 2 commits into
mainfrom
cs-13013-add-observability-pr-previews-for-production
Open

backspace wants to merge 2 commits into
mainfrom
cs-13013-add-observability-pr-previews-for-production

Conversation

@backspace

@backspace backspace commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

What this changes

The PR preview pushed the changed dashboards to the staging Grafana only. It now pushes them to the production Grafana also.

The PR gets one sticky comment, not one comment for each environment. The comment shows each changed dashboard one time, with one link for each environment:

Grafana preview

Preview deployed for 2 dashboards in staging and production.

Dashboards:

Why there are two workflows

The first revision of this PR ran the production push from the pull_request workflow. A review found that this hands production credentials to code the pull request controls. GitHub loads a pull_request workflow, and every script that workflow calls, from the pull request itself. A contributor could change those files and read the temporary AWS credentials, the decrypted production grafanactl token, and GRAFANA_SECRET. The same path also defeats the main-only guard in observability-apply-production.yml.

No guard inside the pull_request workflow fixes this, because the pull request can edit the guard.

GitHub always loads a workflow_run workflow from the default branch. The production preview therefore lives in its own workflow:

Workflow Trigger Credentials
observability-preview.yml pull_request staging only
observability-preview-production.yml workflow_run production only

The trust boundary is the "Overlay" step. The production job checks out the default branch, installs grafanactl while only default-branch code is on disk, then checks out the pull request and restores .github and packages/observability from the default branch. It takes back only packages/observability/grafanactl/resources. Those manifests are the single pull-request input, they are data, and no step runs them.

Three further controls:

  • render-preview.sh fails if a manifest it emits lacks the pr<n>- prefix, so a crafted manifest cannot address a canonical dashboard.
  • The production job asserts the production server URL in config.yaml before it reads any credential.
  • The production sweep refuses any ref other than main.

How the comment stays single

observability-preview.yml posts a comment for staging. observability-preview-production.yml rewrites that same comment with a link for each environment. If the production job fails, the staging-only comment stands. If the staging run failed, the comment lists production and shows a warning.

Tests

  • actionlint and prettier --check pass on all three workflows. shellcheck passes on every observability script.
  • I ran both comment scripts against stub github, context and core objects, over five conditions: staging only, both environments, staging failed, no dashboard changed, and one dashboard.
  • I ran render-preview.sh against a real two-dashboard change. It produced pr999- UIDs for both dashboards and the folder.
  • I then removed the prefix from prefix_uid and ran it again. The new assertion failed the render with exit 1, so the check is not vacuous.

Note for the reviewer

The production preview substitutes the real GRAFANA_SECRET, so operator buttons on a preview dashboard act on production. Tell me if you prefer a dummy value there.

This branch is 556 commits behind main. I have not merged main in, because the merge touches files that carry uncommitted local work.

🤖 Generated with Claude Code

The workflow pushed the changed dashboards to the staging Grafana only. It
now pushes them to the production Grafana also.

- The workflow applies the preview to both environments in one job. The job
  posts one sticky comment. The comment shows each changed dashboard one
  time, with one link for each environment.
- The workflow applies staging first. The comment step runs also when an
  apply step fails. If production fails, the comment keeps the staging links
  and shows a warning.
- The new script scripts/ci-apply-preview.sh holds the steps for one
  environment. Staging and production run the same code.
- Each Grafana token stays in its own step. The workflow writes no token to
  $GITHUB_ENV.
- The cleanup job deletes the preview from both environments when the PR
  closes.
- The daily sweep workflow sweeps both environments.

The production IAM role trusts repo:cardstack/boxel:* with no ref condition.
The role grants the three SSM parameters that the preview reads. This change
needs no infrastructure work.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 17, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-17T09:22:38.726531Z a57d7b1 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a57d7b1649

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/observability-preview.yml Outdated
A code review found that the previous design gave production credentials to
pull-request-controlled code. GitHub loads a `pull_request` workflow, and
every script that workflow calls, from the pull request itself. A contributor
could therefore change those files and read the temporary production AWS
credentials, the decrypted production grafanactl token, and GRAFANA_SECRET.

GitHub always loads a `workflow_run` workflow from the default branch. The
production preview moves there:

- observability-preview.yml keeps staging credentials only.
- observability-preview-production.yml applies the production preview, and
  removes it when the pull request closes. It restores every script from the
  default branch, then overlays only
  packages/observability/grafanactl/resources from the pull request. Those
  manifests are data, and no step runs them.
- render-preview.sh fails now if a manifest that it emits lacks the `pr<n>-`
  prefix. A crafted manifest cannot address a canonical dashboard.
- The production workflow asserts the production server URL before it reads
  a credential.
- The production sweep refuses a ref other than main.

The staging workflow posts a comment for staging. The production workflow
rewrites that comment with one link for each environment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Host Test Results

    1 files      1 suites   1h 51m 5s ⏱️
4 859 tests 4 845 ✅ 14 💤 0 ❌
4 874 runs  4 860 ✅ 14 💤 0 ❌

Results for commit 299d137.

Realm Server Test Results

    1 files    235 suites   1h 22m 8s ⏱️
3 395 tests 3 395 ✅ 0 💤 0 ❌
3 444 runs  3 444 ✅ 0 💤 0 ❌

Results for commit 299d137.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant