Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## Unreleased

- Assign preview URLs to a Composal project and track the PR number or source branch.
- Auto-detect PR, workflow-run, and branch-push context; register branch previews even before an open PR exists.
- Confirm the requested project and deployed branch, and publish the registered environment identity.
- Document project environment listing and automatic archival after PR merge.


## 1

- Request PR verification against a ready CI preview or a configured Composal-managed preview.
Expand Down
88 changes: 71 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,62 @@ Test the product journeys affected by your PR against its deployed preview. Veri
with:
token: ${{ secrets.COMPOSAL_TOKEN }}
org: ${{ vars.COMPOSAL_ORG }}
project: ${{ vars.COMPOSAL_PROJECT }}
preview-url: ${{ steps.deploy.outputs.url }}
```

Configure the connected repository once in **Verify → PR verification**. Select **Preview supplied by CI**, your scenario pack, and an external Verify environment template containing your personas and safety policy. Add a Composal administrator API token as the `COMPOSAL_TOKEN` Actions secret and your organization slug as the `COMPOSAL_ORG` variable.
Configure the Composal project in **Verify → Projects → your project → PR Testing**. Select its source repository and **Your CI**, your scenario pack, and an external Verify environment template containing your personas and safety policy. Add a Composal administrator API token as the `COMPOSAL_TOKEN` Actions secret and your organization slug as the `COMPOSAL_ORG` variable.

Run this step after deploying **`github.event.pull_request.head.sha`** and waiting for the preview to become reachable. GitHub's `github.sha` can be a synthetic merge commit; Verify deliberately uses the PR head. Your existing deployment provider supplies the URL; this action does not build an arbitrary app.

The action infers the PR number and repository name. Set `repository` if the connected Composal repository has a different slug. It needs no checkout, installed CLI, or GitHub token: Composal's connected GitHub App maintains the results comment.
Set `COMPOSAL_PROJECT` to your Composal project slug or public ID. Each URL handoff automatically registers a preview in that project’s **Environments** page, labelled with its PR number and branch. Repeated handoffs reuse the environment; new requests keep separate preview records. When the connected GitHub App observes the PR merge, Composal archives its generated previews after active verification finishes. Use **Show Archived** to view their retained history. This does not delete the deployment at your provider.

The action accepts either `pr` or `branch`; both are optional when GitHub supplies the context. It infers PR numbers from PR events and source branches from PR, `workflow_run`, or branch `push` events. The required `project` selects the saved source connection; there is no repository input. It needs no checkout, installed CLI, or GitHub token: Composal's connected GitHub App maintains the results comment.

For a branch deployment with no open PR, supply the preview URL and project. The action registers the environment and succeeds with `status: preview_registered` and an `environment-id`; it does not report a browser test pass. When a PR later opens for that branch, Verify links the branch previews to it and archives them after merge. If a branch has multiple open PRs, supply `pr` explicitly. Branches registered in multiple projects need an explicit project selection before they can be linked automatically.

```yaml
# After a deployment in a branch push workflow; branch and SHA are auto-detected.
- uses: composalai/verify@1
with:
token: ${{ secrets.COMPOSAL_TOKEN }}
org: ${{ vars.COMPOSAL_ORG }}
project: ${{ vars.COMPOSAL_PROJECT }}
preview-url: ${{ steps.deploy.outputs.url }}
# For another event type, set branch OR pr and the deployed sha explicitly:
# branch: feature/checkout
# sha: <full deployed commit SHA>
```

## Set up with an agent

Open the project's **PR Testing** page and choose **Copy Instructions for Agent**. The instructions include the current organization and project, the workflow step, and commands for creating an expiring Composal token directly in GitHub's secret store:

```sh
com login
com whoami
gh auth status
gh repo view --json nameWithOwner --jq .nameWithOwner
set +x
set -o pipefail
com pat create --name verify-ci --expires-in 90d | gh secret set COMPOSAL_TOKEN
gh variable set COMPOSAL_ORG --body acme
gh variable set COMPOSAL_PROJECT --body storefront
gh secret list
```

Run these in the target GitHub checkout; replace `acme` and `storefront` with your organization and project. The token creator needs administrator access. Keep its value out of logs, prompts, and committed files. The API resolves the source repository from the project's saved PR Testing settings.

## Composal-hosted previews

If the repository is configured to **Build a Composal preview**, leave out `preview-url`. Verify provisions and deploys the exact PR commit using the configured profile. The same minimal step works with **GitHub deployment preview** discovery.
If the project is configured to **Composal Preview**, leave out `preview-url`. Verify provisions and deploys the exact PR commit using the configured profile. The same minimal step works with **GitHub deployment preview** discovery.

```yaml
- uses: composalai/verify@1
with:
token: ${{ secrets.COMPOSAL_TOKEN }}
org: ${{ vars.COMPOSAL_ORG }}
project: ${{ vars.COMPOSAL_PROJECT }}
```

For a pipeline that already readies a Verify preview environment, pass its slug with `environment` instead of `preview-url`. CI must attest the deployed commit; Composal-managed targets also validate their healthy deployments against that SHA.
Expand Down Expand Up @@ -55,6 +93,7 @@ jobs:
with:
token: ${{ secrets.COMPOSAL_TOKEN }}
org: ${{ vars.COMPOSAL_ORG }}
project: ${{ vars.COMPOSAL_PROJECT }}
```

The fork condition avoids running a secret-dependent step when GitHub withholds secrets. Keep your deployment and secret use on trusted workflow events; do not switch to `pull_request_target` just to expose secrets to fork code.
Expand All @@ -63,20 +102,21 @@ By default the action waits up to 15 minutes. Passed or explicitly skipped reque

## Inputs and outputs

| Input | Default | Meaning |
| ------------- | ---------------------- | ----------------------------------------------------------------------------------------------- |
| `token` | Required | Composal API token, supplied through a secret. |
| `org` | Required | Composal organization slug. |
| `preview-url` | Omitted | Ready URL deployed from this PR head. Requires CI preview mode and an external Verify template. |
| `environment` | Omitted | Ready Verify preview environment slug; mutually exclusive with `preview-url`. |
| `repository` | GitHub repository name | Connected Composal repository slug. |
| `pr` | PR event | PR number. `workflow_run` works when it identifies one PR. |
| `sha` | PR head | Full deployed PR head SHA. Supply it with `pr` on other event types. |
| `wait` | `'true'` | Wait for results; `'false'` only requests verification. |
| `timeout` | `'15'` | Wait limit in minutes, between 1 and 60. Set the job timeout higher. |
| `api-url` | `https://composal.ai` | HTTPS API origin, for installations using another endpoint. |

Outputs: `url` (PR verification history), `pull-request-id`, `run-id`, `sweep-id` (when started), and `status`. The workflow summary links to the full results. Critical/high issue recordings remain authenticated links in Verify.
| Input | Default | Meaning |
| ------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `token` | Required | Composal API token, supplied through a secret. |
| `org` | Required | Composal organization slug. |
| `preview-url` | Omitted | Ready URL deployed from this PR head or branch commit. Requires CI preview mode and an external Verify template. |
| `environment` | Omitted | Ready Verify preview environment slug; mutually exclusive with `preview-url`. |
| `project` | Required | Composal project slug or public ID with a saved PR Testing source connection. |
| `branch` | GitHub source branch | Optional alternative to `pr`. Resolves an open PR or registers a branch preview when none exists. |
| `pr` | PR event | Optional alternative to `branch`. `workflow_run` works when it identifies one PR. |
| `sha` | PR head or branch push | Full deployed commit SHA. PR heads and branch pushes are inferred; supply it for other event types. |
| `wait` | `'true'` | Wait for results; `'false'` only requests verification. |
| `timeout` | `'15'` | Wait limit in minutes, between 1 and 60. Set the job timeout higher. |
| `api-url` | `https://composal.ai` | HTTPS API origin, for installations using another endpoint. |

Outputs: `url` (PR history or registered branch environment), `pull-request-id`, `run-id`, `sweep-id` (when started), `environment-id` (branch registration), and `status`. The workflow summary links to the full results. Critical/high issue recordings remain authenticated links in Verify.

Retries within the same workflow attempt reuse the same verification request. Rerunning the workflow creates a fresh request. A workflow for an obsolete head cannot start a run for the newer head.

Expand All @@ -85,3 +125,17 @@ Retries within the same workflow attempt reuse the same verification request. Re
This directory is the complete dependency-free action distribution. It runs on GitHub's [Node 24 action runtime](https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#runs-for-javascript-actions). No build or dependency installation is needed by consumers.

The `1` tag is the supported major release. To publish an update from the Vex monorepo, copy `action.yml`, `index.mjs`, `verify.mjs`, the tests, and this README to that repository's root. Run `node --test verify.test.mjs`, commit the reviewed files, and create the `1` release tag at that commit. Update that major tag deliberately for compatible releases; use immutable commit pins where your workflow requires them.

## GitLab CI

For GitLab.com merge request pipelines, include
`https://composal.ai/ci/verify/v1/gitlab.yml` and extend `.composal-verify`
after your preview deployment. The copyable configuration in your project’s PR
Testing includes direct MR pipeline rules and the connected Composal repo slug.
The helper reads GitLab's IID and source SHA, hands off the exact preview, waits
for its own verification run, and writes safe result IDs/links to
`composal-verify.json`.

See [GitLab setup and CI variables](https://composal.ai/docs/verify/source-control/gitlab#gitlab-ci)
for dotenv handoff, fork and synthetic-commit restrictions, merge protection,
and CLI/API examples.
13 changes: 9 additions & 4 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ inputs:
description: URL deployed from this PR head. Omit when Composal deploys or discovers the preview.
environment:
description: Ready Verify preview environment slug, instead of preview-url.
repository:
description: Composal repository slug. Defaults to the GitHub repository name.
project:
description: Composal project slug or ID. Configure its source connection in the project's PR Testing page.
required: true
pr:
description: PR number. Inferred from pull_request or a single-PR workflow_run event.
description: Optional PR number. Inferred from pull_request or a single-PR workflow_run event. Supply pr or branch.
branch:
description: Optional deployed source branch. Inferred from PR, workflow_run, or push context. Registers a project preview even without an open PR.
sha:
description: Exact deployed PR head SHA. Inferred from the PR event, never the merge commit.
description: Exact deployed source SHA. Inferred from the PR head or branch push, never a PR merge commit.
wait:
description: Wait for verification results and fail on unsuccessful outcomes.
default: 'true'
Expand All @@ -41,6 +44,8 @@ outputs:
description: Browser sweep identity, when started.
status:
description: Verification state or terminal outcome. queued means accepted, not passed.
environment-id:
description: Registered Verify environment identity for a branch preview without an open PR.
runs:
using: node24
main: index.mjs
10 changes: 8 additions & 2 deletions index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ const inputs = Object.fromEntries(
'org',
'preview-url',
'environment',
'repository',
'project',
'pr',
'branch',
'sha',
'wait',
'timeout',
Expand All @@ -27,6 +28,10 @@ try {
runId: process.env.GITHUB_RUN_ID,
runAttempt: process.env.GITHUB_RUN_ATTEMPT,
job: process.env.GITHUB_JOB,
eventName: process.env.GITHUB_EVENT_NAME,
refType: process.env.GITHUB_REF_TYPE,
refName: process.env.GITHUB_REF_NAME,
sha: process.env.GITHUB_SHA,
})
outputs = await verify(config, {
publish: async (values) => {
Expand All @@ -47,9 +52,10 @@ try {
} finally {
if (outputs && process.env.GITHUB_STEP_SUMMARY) {
const status = outputs.status.replace(/[^a-z_]/g, '')
const label = outputs['pull-request-id'] ? 'PR verification history' : 'Preview environment'
await appendFile(
process.env.GITHUB_STEP_SUMMARY,
`### Composal Verify\n\n**${status}** · [PR verification history](${outputs.url})\n\nFindings, recordings, and feedback are available in Verify and the GitHub results comment.\n`
`### Composal Verify\n\n**${status}** · [${label}](${outputs.url})\n\n${outputs['pull-request-id'] ? 'Findings, recordings, and feedback are available in Verify and the GitHub results comment.' : 'The branch preview is registered in your project. No PR verification run was requested.'}\n`
)
}
}
Loading
Loading