> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# GitHub Actions in blueprints

> Use GitHub Actions to install languages, tools, and SDKs in your Devin environment without writing shell scripts.

Instead of writing shell scripts to install tools, you can reference GitHub Actions directly in your blueprint's `initialize` or `maintenance` sections. Devin downloads and runs the action during the snapshot build, the same way GitHub's CI runners execute action steps.

This is especially useful for language setup actions like `setup-python`, `setup-node`, and `setup-go`, which handle version management and PATH configuration automatically.

## Syntax

Add a `uses` step to any section of your blueprint:

```yaml theme={null}
initialize:
  - name: Install Python 3.12
    uses: github.com/actions/setup-python@v5
    with:
      python-version: "3.12"
```

| Field  | Type              | Description                                                            |
| ------ | ----------------- | ---------------------------------------------------------------------- |
| `name` | string (optional) | Human-readable label shown in build logs                               |
| `uses` | string            | GitHub Action reference (see [format](#action-reference-format) below) |
| `with` | map (optional)    | Input parameters passed to the action                                  |
| `env`  | map (optional)    | Extra environment variables for the step                               |

<Info>
  A step must specify either `run` (a shell command) **or** `uses` (an action), not both.
</Info>

## Action reference format

```
github.com/<owner>/<repo>@<ref>
github.com/<owner>/<repo>/<subpath>@<ref>
```

The `github.com/` prefix and `@<ref>` suffix are both **required**. The ref is typically a version tag like `v5`.

**Examples:**

| Reference                                   | What it resolves to                                          |
| ------------------------------------------- | ------------------------------------------------------------ |
| `github.com/actions/setup-python@v5`        | `actions/setup-python` at tag `v5`                           |
| `github.com/actions/setup-node@v4`          | `actions/setup-node` at tag `v4`                             |
| `github.com/gradle/actions/setup-gradle@v4` | `gradle/actions` repo, `setup-gradle` subdirectory, tag `v4` |

## Passing inputs

Use the `with` field to pass inputs to the action. All values are treated as strings, matching GitHub Actions behavior:

```yaml theme={null}
initialize:
  - uses: github.com/actions/setup-java@v4
    with:
      java-version: "21"
      distribution: "temurin"
```

<Warning>
  Always **quote version numbers** in `with` values. YAML interprets bare `3.10` as the float `3.1`, which is not what you want. Write `python-version: "3.10"` instead.
</Warning>

## Setting environment variables

Use the `env` field to set environment variables scoped to a single action step:

```yaml theme={null}
initialize:
  - uses: github.com/actions/setup-node@v4
    with:
      node-version: "20"
    env:
      RUNNER_DEBUG: "1"
```

Environment variables set by an action (via `GITHUB_ENV` or `GITHUB_PATH`) are automatically propagated to subsequent steps in the blueprint.

## Examples

### Python project with a specific version

```yaml theme={null}
initialize:
  - name: Install Python 3.12
    uses: github.com/actions/setup-python@v5
    with:
      python-version: "3.12"

maintenance: |
  pip install -r requirements.txt

knowledge:
  - name: test
    contents: pytest
```

### Multi-language project

```yaml theme={null}
initialize:
  - name: Install Node.js
    uses: github.com/actions/setup-node@v4
    with:
      node-version: "20"
  - name: Install Python
    uses: github.com/actions/setup-python@v5
    with:
      python-version: "3.12"
  - name: Install Go
    uses: github.com/actions/setup-go@v5
    with:
      go-version: "1.22"
```

### Mixing actions with shell commands

Actions and shell commands can be freely mixed in the same section:

```yaml theme={null}
initialize:
  - name: Install Python
    uses: github.com/actions/setup-python@v5
    with:
      python-version: "3.12"
  - name: Install project tools
    run: pip install ruff pytest
  - name: Install Node.js
    uses: github.com/actions/setup-node@v4
    with:
      node-version: "20"
  - name: Install frontend deps
    run: npm install -g pnpm
```

### Java project with Gradle

```yaml theme={null}
initialize:
  - name: Install JDK 21
    uses: github.com/actions/setup-java@v4
    with:
      java-version: "21"
      distribution: "temurin"
  - name: Install Gradle
    uses: github.com/gradle/actions/setup-gradle@v4

maintenance: |
  ./gradlew dependencies

knowledge:
  - name: build
    contents: ./gradlew build
  - name: test
    contents: ./gradlew test
```

### Actions vs. shell scripts

You don't have to use actions — plain shell commands work fine. Actions are a convenience when the equivalent shell script would be long or error-prone.

<Tabs>
  <Tab title="With GitHub Actions">
    ```yaml theme={null}
    initialize:
      - uses: github.com/actions/setup-go@v5
        with:
          go-version: "1.23"
    ```
  </Tab>

  <Tab title="Equivalent shell script">
    ```yaml theme={null}
    initialize: |
      GO_VERSION=1.23.5
      ARCH=$(dpkg --print-architecture)
      curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-${ARCH}.tar.gz" \
        | sudo tar -xz -C /usr/local
      echo 'export PATH="/usr/local/go/bin:$HOME/go/bin:$PATH"' \
        | sudo tee /etc/profile.d/golang.sh > /dev/null
    ```
  </Tab>
</Tabs>

## How it works

When Devin encounters a `uses` step during a snapshot build:

1. **Downloads** the action repository (shallow clone at the pinned ref)
2. **Reads** the action's `action.yml` metadata to determine the runtime and entry points
3. **Builds** the execution environment with `INPUT_*`, `GITHUB_*`, and `RUNNER_*` variables
4. **Runs** the action's `pre` step (if defined) then the `main` entry point
5. **Propagates** side effects — any entries written to `GITHUB_PATH` or `GITHUB_ENV` by the action are applied to subsequent blueprint steps

<Info>
  Actions run outside of a real GitHub workflow. Context variables like `github.repository` are populated with stub values. Actions that require live GitHub API access (e.g., commenting on PRs, creating releases) will not work in blueprints.
</Info>

## Limitations

* **Node.js actions only** — Only GitHub Actions that use a Node.js runtime (`node16`, `node20`, `node24`) are supported. Docker-based and composite actions are not supported.
* **No `post` lifecycle** — Devin runs `pre` and `main` steps but skips `post` cleanup steps, since builds run in disposable VMs.
* **Stub GitHub context** — Actions that rely on GitHub API calls, workflow event data, or repository context may not work correctly because these values are placeholders in the build environment.
* **Pin your versions** — Always reference a specific version tag (e.g., `@v5`) rather than a branch name for reproducible builds.

## Related pages

* [Declarative environment configuration](/onboard-devin/environment/blueprints)
* [Blueprint reference](/onboard-devin/environment/blueprint-reference)
* [Template library](/onboard-devin/environment/templates)
