Skip to content

Deploying the dashboard with GitHub Actions

The GitHub Actions only deployment is the default way to host the dashboard. Everything runs in your control repository:

  1. The CAO Activity workflow collects evidence.
  2. The CAO Dashboard workflow builds a static site and its data payload.
  3. GitHub Pages serves the site.

Queries run in each viewer’s browser, in a web worker over a local IndexedDB database. You don’t operate a server, a database, or a cloud account. For more information about how the browser loads data, see Browser data pipeline.

RequirementDetails
Control repositoryA private repository that runs CAO. GitHub Enterprise is not required.
GitHub ActionsEnabled for the repository. You need GitHub-hosted ubuntu-latest runners or compatible self-hosted runners, and enough minutes for an hourly Activity run.
Actions cacheStores the Activity snapshot (cao-activity-v5-*) and the built dashboard (central-agentic-ops-dashboard). If the cache is evicted, the dashboard uses the latest successful Activity artifact instead. For more information, see Cache contract.
Actions artifactsStores the cao-activity-index and central-agentic-ops-dashboard artifacts. The dashboard artifact is kept for one day.
GitHub PagesThe publishing source must be GitHub Actions. To make the site private, you need a plan that supports access control for Pages, such as GitHub Enterprise Cloud. Otherwise, the site is public.
github-pages environmentCreated automatically by GitHub Pages. You can protect it with required reviewers.
BrowserA current browser that supports web workers, IndexedDB, and JavaScript modules. The browser downloads and indexes the data on first load.

The dashboard build, Pages artifact, and deploy jobs don’t need additional secrets. The build job uses the automatic github.token with actions: read and contents: read permissions. A separate job packages and uploads the Pages artifact before the deploy job uses OpenID Connect (OIDC) with pages: write and id-token: write permissions.

The Pages artifact and deploy jobs rely on the standard Pages actions to report configuration and deployment errors; they do not separately verify Pages visibility with the Actions token. The Configure Pages step sets ignore-if-missing: true, but the pinned action does not currently support that input, so it can still fail when Pages settings are unavailable. Confirm the publishing source and intended access boundary in Settings > Pages before deployment.

The Activity collector, orchestrators, and workers call the GitHub API with a credential that you configure in the control repository. That credential determines which evidence the dashboard can show and which repositories campaigns can reach. Choose one profile before the first run.

ProfileBest forCredentialsLimitations
GitHub AppsProductionA private read app and a private write appYou need permission to create and install private GitHub Apps.
Fine-grained PATGetting started and experimentationA read PAT and write PAT for each resource ownerNot for production. The tokens are tied to one user, expire, need manual rotation, don’t support every API, and each owner pair has its own rate limit.

At runtime, CAO uses the explicitly selected App or owner-scoped PAT profile. The repository-provided github.token remains only as a bounded control-repository fallback.

For more information, see Configure authentication.

  1. Install the dashboard. The supported CAO installer includes it through the explicit root package. Advanced users can install only the Activity and dashboard components; unpinned package coordinates resolve the latest release automatically.

    Terminal window
    gh aw add githubnext/gh-cao/activity
    gh aw add githubnext/gh-cao/dashboard
  2. Review, commit, and push the installed files. These include .github/workflows/cao-activity.yml, .github/workflows/cao-dashboard.yml, and the activity/ and dashboard/ directories.

  3. Configure your cross-repository credential profile. Follow the procedure for GitHub Apps or for fine-grained PATs.

  4. Run gh cao setup in the control repository to configure GitHub Pages with GitHub Actions as its source. For a private repository it also restricts access to repository readers; this requires a plan that supports private Pages and permission to manage Pages settings. Setup fails rather than leaving a public site eligible for deployment if access cannot be restricted. If setup was already completed, confirm the Pages source and visibility in Settings > Pages.

  5. Optionally, protect the github-pages environment. For more information, see Managing environments for deployment in the GitHub documentation.

  6. Run the Activity workflow.

    1. Under your repository name, click Actions.
    2. In the left sidebar, click CAO Activity.
    3. Click Run workflow, then wait for the run to succeed.

    The dashboard build fails if no successful Activity run exists. If the run fails, see Routine monitoring.

  7. Wait for the automatically triggered CAO Dashboard workflow to finish, then open the URL from its deploy job. Confirm that the site shows data only from your control repository.

To learn how to read the dashboard, see Dashboard and Overview.

The CAO Activity workflow runs when you push changes to any of these paths on the default branch:

  • .github/workflows/cao.json
  • .github/workflows/cao-dashboard.yml
  • */dashboard.json
  • dashboard/**

Dashboard has no push trigger or schedule. Every successful default-branch Activity run triggers one Dashboard build, so a relevant push produces one collection-and-publication sequence without a duplicate deployment.

Failed or cancelled Activity runs produce skipped Dashboard runs rather than publishing an invalid snapshot. If every Activity-triggered Dashboard run is skipped, inspect the upstream Activity run first. A confirmed API capacity limit is recoverable: Activity indexes retained and downloaded runs, marks the affected repository coverage as partial, and skips further issue-status and operational-value API work. Authentication, visibility, and invalid-data failures still block publication.

An automatically triggered Dashboard build restores the exact triggering Activity run and attempt’s cache, falling back only to that run’s artifact. It cannot silently publish a different run’s older snapshot. Manual dispatch can still rebuild from the last cached snapshot without collecting fresh evidence.

SettingLocationDefaultDescription
control-plane.campaigns.dashboard.deploy.github/workflows/cao.jsontrueA boolean. When false, the workflow still builds and caches the dashboard artifact but doesn’t deploy it to Pages.
Activity schedule.github/workflows/cao-activity.ymlHourlyControls how fresh the evidence is. Change it in the campaign source and run gh aw update. Don’t edit the installed lock file.
Activity retentionIngestion steps in cao-activity.yml and cao-dashboard.yml30 daysLimits the size of the payload that browsers download. For more information, see Update and retain browser data.
Pages visibilityRepository Pages settingsDepends on your planControls who can read the site.

Pages destinations follow each campaign’s rollout mode. In review mode, the dashboard publishes to access-controlled review Pages. In live mode, it publishes to production Pages. For more information, see Pages report routing.

Publishing from an existing Pages workflow

Section titled “Publishing from an existing Pages workflow”

If another workflow already publishes your Pages site, set control-plane.campaigns.dashboard.deploy to false. In your existing workflow, find the latest successful cao-dashboard.yml run on the default branch, download its central-agentic-ops-dashboard artifact into your site output, and deploy the combined result.

This option has no server, so there’s no server-side OpenTelemetry endpoint to configure for the dashboard. Use these signals instead.

SignalWhat to check
Workflow healthGitHub Actions run history is the primary record. When an Activity or dashboard job fails, CAO opens or updates a CAO Activity workflow failure or CAO Dashboard workflow failure issue with a stable failure code, such as CAO_DASHBOARD_DEPLOY_FAILED.
Data healthThe build runs activity/cao.mjs validate-activity-data and activity/cao.mjs doctor against the restored database. The results appear in the job log.
Credential healthSkipped create-github-app-token steps, admission capacity gates, and authentication failures show which credential a run used. For details, see the GitHub Apps and fine-grained PAT profiles.
Agentic workflow tracesOrchestrators and workers export OpenTelemetry spans through gh-aw. To turn on export, set the GH_AW_DEFAULT_OTLP_ENDPOINT variable and the GH_AW_DEFAULT_OTLP_HEADERS secret at the repository, organization, or enterprise level. For more information, see Optional observability.
Browser diagnosticsAdd ?debug=1, ?debug=*, or a category filter such as ?debug=data:query,-render:* to the dashboard URL. The browser console then shows structured diagnostics that contain no sensitive data. ?debug=data:query shows timings for each query stage.
Local reproductionIn a checkout of the catalog repository, run npm run dashboard:local -- --repo OWNER/REPOSITORY to download the published data and preview it locally. To query the same data with SQLite, see Use local SQLite.
  • Exact source. The site is built from the exact workflow commit (github.workflow_sha). It publishes only the payload files listed in the manifest.
  • Complete payloads. Every payload file is hash-verified before the browser loads it. If the payload is incomplete, the build fails instead of publishing partial data.
  • No long-lived credentials. The build, Pages artifact, and deploy jobs don’t hold long-lived credentials. The deploy job uses OIDC.
  • One deployment at a time. A running dashboard build finishes publishing its snapshot without being cancelled by newer triggers. GitHub Actions keeps at most one pending eligible build, replacing it when a newer eligible run arrives. Ineligible triggers use separate concurrency groups and cannot displace that pending build.
  • Safe failures. If a build or deployment fails, the previously deployed site stays in place.
  • Freshness. The site is a snapshot of the last successful deployment. It can lag behind the latest Activity run.
  • Confidentiality. A private repository doesn’t make its Pages site private. Access control depends on the Pages visibility settings that your plan supports.
  • Durability. Actions caches can be evicted, and artifacts expire. The site isn’t an archive. Target repository history and Actions run metadata remain the source of truth. To keep history longer, see Create a historical archive.
  • Scale. Each viewer’s browser downloads and queries all of the data. Large fleets can exceed browser memory or load slowly. If that happens, consider a server-backed option.
  • Per-user authorization. Anyone who can read the Pages site can read all of its data. There is no per-user or per-repository filtering.
  • Availability. Availability depends on GitHub Pages and GitHub Actions. CAO adds no SLA.
  • Coverage. The dashboard shows only evidence that your credential can read. Repositories that the credential can’t reach appear as incomplete coverage, not as healthy repositories with no activity.
  • To roll back, run the CAO Dashboard workflow from a known-good commit, or revert the change and push.
  • To stop future deployments, set control-plane.campaigns.dashboard.deploy to false. This setting doesn’t remove the current site.
  • To take the site down, unpublish it from your repository’s Pages settings, or block the github-pages environment.

If private data was exposed, treat it as a Pages incident. For more information, see Incident response.