> For the complete documentation index, see [llms.txt](https://docs.duku.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.duku.ai/integrations/github-actions/quickstart-environment-action.md).

# Quickstart: environment action

Use this workflow for a target you keep in Viewport, such as staging or a production canary.

{% stepper %}
{% step %}

### 1. Create the target in Viewport

Open the product in Viewport.

Create the target from the target menu in the top-right navbar, next to the active product.

Store its ID as a repository variable such as `DUKU_STAGING_TARGET_ID`.
{% endstep %}

{% step %}

### 2. Add the repository secret

Create `PLATFORM_API_KEY` in Viewport, under **Settings → API Keys**.

Store it as the repository secret `PLATFORM_API_KEY`.
{% endstep %}

{% step %}

### 3. Create the workflow file

Copy this file into `.github/workflows/duku-environment.yml`:

```yaml
name: Duku environment

on:
  push:
    branches: [main]
  workflow_dispatch:

concurrency:
  group: duku-env-${{ vars.DUKU_STAGING_TARGET_ID }}
  cancel-in-progress: false

jobs:
  explore:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: duku-ai/actions/environment@environment/v0.3.0
        with:
          api-key: ${{ secrets.PLATFORM_API_KEY }}
          target-id: ${{ vars.DUKU_STAGING_TARGET_ID }}
```

{% endstep %}

{% step %}

### 4. Update the workflow values

* `branches: [main]` should match the branch that deploys this environment.
* `api-key` reads the repository secret `PLATFORM_API_KEY`.
* `target-id` points to the target you created in Viewport.

The action explores the target's configured build URL.

Set `url:` if you need to override that URL for a specific workflow run.

`cancel-in-progress: false` serializes runs per target so overlapping pushes do not create duplicate explorations. Set it to `true` if you would rather drop earlier in flight runs.
{% endstep %}
{% endstepper %}

If the target has test cases configured, the action also starts a full test-case run.

### Run on a pull request against a fixed environment

Use this mode when you merge into a protected branch, such as `prod`, and want Duku to gate the PR by exploring a permanent environment.

```yaml
name: Duku prod gate

on:
  pull_request:
    branches: [prod]

jobs:
  explore:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: duku-ai/actions/environment@environment/v0.3.0
        with:
          api-key: ${{ secrets.PLATFORM_API_KEY }}
          target-id: ${{ vars.DUKU_PROD_TARGET_ID }}
          github-token: ${{ github.token }}
```

On a native `pull_request` event, results are also posted to the PR comment when the Duku GitHub App is installed.

On `pull_request` runs, pass `github-token: ${{ github.token }}` so the action can post the sticky status comment. On `push`, `schedule`, or `workflow_dispatch`, it is not used, so the other two examples do not need it.

Without the App, the action still runs and results still appear in Viewport.

### Nightly health checks

A scheduled workflow is a good fit for nightly health checks against staging.

```yaml
name: Duku nightly staging

on:
  schedule:
    - cron: '0 3 * * *'
  workflow_dispatch:

jobs:
  explore:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: duku-ai/actions/environment@environment/v0.3.0
        with:
          api-key: ${{ secrets.PLATFORM_API_KEY }}
          target-id: ${{ vars.DUKU_STAGING_TARGET_ID }}
```

### Read next

* [Choosing preview vs environment](/integrations/github-actions/choosing-preview-vs-environment.md)
* [Configuration reference](/integrations/github-actions/configuration-reference.md)
* [Troubleshooting](/integrations/github-actions/troubleshooting.md)
