# How to Use YAML Anchors for Reusable Configurations in Probe Workflows

> Master YAML anchors in Probe workflows to create reusable configurations. Define steps, variables, and dependencies once and reference them effortlessly.

- Repository: [Tomohisa Oda/probe](https://github.com/linyows/probe)
- Tags: how-to-guide
- Published: 2026-03-06

---

**Probe natively supports YAML anchors and aliases to eliminate repetitive configuration blocks, allowing you to define reusable steps, environment variables, and dependency lists once and reference them across multiple jobs.**

Probe executes workflows defined in YAML files that describe directed-acyclic graphs (DAGs) of jobs. Because Probe parses these files using the standard Go `gopkg.in/yaml.v3` package, you can leverage native YAML anchor (`&`) and alias (`*`) syntax to factor out repeated configuration blocks before the workflow is ever loaded into Probe's internal structures.

## How Probe Resolves YAML Anchors

When Probe loads a workflow file, the YAML parser resolves all anchors and aliases during the unmarshaling process. In [`workflow.go`](https://github.com/linyows/probe/blob/main/workflow.go), the `Workflow` struct defines the schema with YAML struct tags (e.g., `yaml:"jobs"`), but by the time the data reaches these Go structs, the anchors have already been expanded by the underlying library.

This means the rest of Probe's execution pipeline—including the DAG builder in [`executor.go`](https://github.com/linyows/probe/blob/main/executor.go) and the topological sorter in [`dag/topo.go`](https://github.com/linyows/probe/blob/main/dag/topo.go)—works with fully expanded configurations. You do not need any special Probe-specific syntax or plugins to use anchors; they are resolved automatically before the workflow validation and execution phases begin.

## Reusable Configuration Patterns

Because anchors are resolved before Probe builds its internal DAG, you can use them with any Probe-specific fields—including `needs`, `if`, `continue_on_error`, and `retry`—without losing semantics. Below are three practical patterns demonstrated in [`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml) and verified in [`workflow_test.go`](https://github.com/linyows/probe/blob/main/workflow_test.go).

### Reusing Step Sequences

Define common steps once and reference them in multiple jobs to avoid duplication.

```yaml
steps-common: &common_steps
  - name: Install dependencies
    shell: npm ci
  - name: Run lint
    shell: npm run lint

jobs:
  build:
    runs-on: ubuntu-latest
    steps: *common_steps

  test:
    runs-on: ubuntu-latest
    steps:
      - *common_steps
      - name: Run tests
        shell: npm test

```

In this example from [`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml), the `&common_steps` anchor captures a list of steps. Both the `build` and `test` jobs reference these steps using `*common_steps`. The test job extends the list by merging the alias with additional steps.

### Sharing Environment Variables and Retry Policies

Use anchors to maintain consistent environment variables and retry configurations across jobs.

```yaml
shared-env: &env
  DATABASE_URL: postgres://user:pass@localhost/db
  LOG_LEVEL: debug

retry-default: &retry
  attempts: 5
  interval: 10s

jobs:
  migrate:
    runs-on: ubuntu-latest
    env: *env
    retry: *retry
    steps:
      - name: Run migrations
        shell: ./migrate.sh

  seed:
    runs-on: ubuntu-latest
    env: *env
    retry: *retry
    steps:
      - name: Seed data
        shell: ./seed.sh

```

Here, the `shared-env` and `retry-default` anchors ensure that both the `migrate` and `seed` jobs use identical database connections and retry behavior. This pattern is particularly effective for maintaining consistent timeout and backoff strategies across microservice deployments.

### Centralizing Dependency Relationships

Anchor lists of job dependencies to simplify complex workflow graphs.

```yaml
needs-all: &all_needs [ build, lint ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - shell: make build

  lint:
    runs-on: ubuntu-latest
    steps:
      - shell: make lint

  test:
    runs-on: ubuntu-latest
    needs: *all_needs
    steps:
      - shell: make test

```

By anchoring the `needs-all` array, you can reference the complete dependency chain with `*all_needs` instead of repeating `[ build, lint ]` in every downstream job. This reduces the risk of synchronization errors when adding new upstream dependencies.

## Source Code Implementation

The support for YAML anchors is built into Probe's parsing layer rather than the execution engine. The following files handle the anchor resolution and workflow processing:

- **[`workflow.go`](https://github.com/linyows/probe/blob/main/workflow.go)** — Defines the `Workflow` struct with YAML tags that map directly to the workflow file schema. The standard Go YAML library populates these structs after resolving all anchors.
- **[`executor.go`](https://github.com/linyows/probe/blob/main/executor.go)** — Consumes the fully expanded workflow structure to build the execution DAG. Because anchors are flattened during parsing, the executor sees only concrete values.
- **[`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml)** — Provides a working demonstration of anchor syntax for steps, environment variables, and needs.
- **[`workflow_test.go`](https://github.com/linyows/probe/blob/main/workflow_test.go)** — Contains test cases that load [`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml) and verify that aliased configurations are correctly interpreted as distinct job definitions.

## Summary

- Probe uses the standard Go `gopkg.in/yaml.v3` parser, which automatically resolves YAML anchors and aliases before workflow execution begins.
- You can anchor any configuration block—**steps**, **environment variables**, **retry policies**, or **needs** arrays—and reference them with aliases to keep workflows DRY.
- The `Workflow` struct in [`workflow.go`](https://github.com/linyows/probe/blob/main/workflow.go) receives fully expanded configurations, meaning the execution engine in [`executor.go`](https://github.com/linyows/probe/blob/main/executor.go) requires no special handling for aliases.
- The repository includes a working example at [`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml) that demonstrates reusable patterns validated by [`workflow_test.go`](https://github.com/linyows/probe/blob/main/workflow_test.go).

## Frequently Asked Questions

### Can I use YAML anchors with Probe's conditional logic and job dependencies?

Yes. Because the Go YAML parser resolves anchors before Probe unmarshals the file into the `Workflow` struct, all Probe-specific fields—including `if` conditions, `needs` dependencies, and `continue_on_error` settings—work normally with aliased values. The execution engine receives the fully expanded configuration.

### Do I need to install additional plugins to enable YAML anchors in Probe?

No. YAML anchor and alias support is native to the YAML specification and is handled automatically by the `gopkg.in/yaml.v3` library that Probe uses. You can use `&` to define anchors and `*` to reference them without any configuration changes or plugins.

### How do I override specific values when reusing an anchored configuration block?

To modify a referenced configuration, define a new anchor with the variations or explicitly list the values in the job definition. Simple aliases (`*anchor`) insert the exact block defined at the anchor point. For granular overrides, you must create separate anchors for each variation or define the values directly in the job rather than using the alias.

### Where can I find working examples of Probe workflows using anchors?

The repository includes [`examples/yaml-alias.yml`](https://github.com/linyows/probe/blob/main/examples/yaml-alias.yml), which demonstrates reusable steps, shared environment variables, and centralized dependency lists. The [`workflow_test.go`](https://github.com/linyows/probe/blob/main/workflow_test.go) file loads this example and verifies that the parser correctly interprets all aliases, providing a reference implementation you can adapt for your own workflows.