Skip to content
Open
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
19 changes: 0 additions & 19 deletions .github/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -274,25 +274,6 @@ runner-test-matrix:
- On Demand VRFV2 Performance Test
test_go_project_path: integration-tests

- id: smoke/vrf_test.go:*
path: integration-tests/smoke/vrf_test.go
test_env_type: docker
runs_on: ubuntu-latest
triggers:
- PR E2E Core Tests
- Merge Queue E2E Core Tests
- Nightly E2E Tests
- Push E2E Core Tests
- Workflow Dispatch E2E Core Tests
test_cmd: |
gotestsum \
--junitfile=/tmp/junit.xml \
--jsonfile=/tmp/gotest.log \
--format=github-actions \
-- -v -run "TestVRFBasic|TestVRFJobReplacement" -timeout 30m -count=1 -parallel=2 github.com/smartcontractkit/chainlink/integration-tests/smoke
pyroscope_env: ci-smoke-vrf-evm-simulated
test_go_project_path: integration-tests

- id: smoke/vrfv2_test.go:*
path: integration-tests/smoke/vrfv2_test.go
test_env_type: docker
Expand Down
78 changes: 70 additions & 8 deletions .github/workflows/devenv-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
schedule:
- cron: "0 6 * * *" # Run daily at 6 AM
workflow_dispatch:
pull_request:

defaults:
run:
Expand All @@ -14,29 +15,53 @@
cancel-in-progress: true

jobs:
changes:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are not actively maintaining these tests right now, however, it seems useful. What's your opinion, @Tofel?

name: Detect devenv changes
runs-on: ubuntu-latest
outputs:
devenv-changes: ${{ steps.devenv-changes.outputs.changes }}
steps:
- name: Checkout the repo
uses: actions/checkout@v6
with:
persist-credentials: false
- uses: dorny/paths-filter@9d7afb8d214ad99e78fbd4247752c4caed2b6e4c # v4.0.0
id: devenv-changes
with:
filters: |
changes:
- 'devenv/**/*.go'
- 'devenv/**/*.toml'
- 'devenv/**/go.mod'
- 'devenv/**/go.sum'
- 'devenv/**/*Dockerfile'
- '.github/workflows/devenv-nightly.yml'

summary:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
name: "Build Information"
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Print Summary
run: |
IMAGE_VERSION="nightly-$(date +%Y%m%d)"
FULL_IMAGE_HINT="<sdlc_registry>/chainlink:${IMAGE_VERSION}"
echo "**Image:** \`${FULL_IMAGE_HINT}\`" >> $GITHUB_STEP_SUMMARY

test-nightly:
name: ${{ matrix.display_name }}
needs: [changes]
permissions:
id-token: write
contents: read
pull-requests: write
runs-on: ${{ matrix.runner }}
# If there's a PR that's changing devenv, run the tests
if: ${{ github.event_name != 'pull_request' || needs.changes.outputs.devenv-changes == 'true' }}
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -73,6 +98,12 @@
runner: "ubuntu-latest"
tests_dir: "flux"
logs_archive_name: "flux"
- display_name: "Test VRF Smoke"
testcmd: "go test -v -timeout 10m -run TestVRFBasic\\|TestVRFJobReplacement"
envcmd: "cl u env.toml,products/vrf/basic.toml"
runner: "ubuntu-latest"
tests_dir: "vrf"
logs_archive_name: "vrf"
- display_name: "Test DF1 (OCR2) Smoke"
testcmd: "go test -v -timeout 20m -run TestSmoke/rounds"
envcmd: "cl u env.toml,products/ocr2/basic.toml"
Expand Down Expand Up @@ -141,74 +172,104 @@
runner: "ubuntu24.04-16cores-64GB"
tests_dir: "automation"
logs_archive_name: "automation-soak"
run_on_pr: false
- display_name: "Test DF1 (OCR2) Soak"
testcmd: "go test -v -timeout 4h -run TestOCR2Soak/clean"
envcmd: "cl u env.toml,products/ocr2/basic.toml,products/ocr2/soak.toml; cl obs up -f"
runner: "ubuntu24.04-16cores-64GB"
tests_dir: "ocr2"
logs_archive_name: "df1-soak"
run_on_pr: false
- display_name: "Test DF1 (OCR2) Chaos"
testcmd: "go test -v -timeout 30m -run TestOCR2Chaos"
envcmd: "cl u env.toml,products/ocr2/basic.toml; cl obs up -f"
runner: "ubuntu24.04-16cores-64GB"
tests_dir: "ocr2"
logs_archive_name: "df1-chaos"

run_on_pr: false
- display_name: "Test LogPoller Fixed Depth"
testcmd: "go test -v -timeout 30m -run TestLogPoller"
envcmd: "cl u env.toml,tests/logpoller/fixed_depth.toml"
runner: "ubuntu24.04-16cores-64GB"
tests_dir: "logpoller"
logs_archive_name: "logpoller-fixed-depth"

- display_name: "Test LogPoller Finality Tag"
testcmd: "go test -v -timeout 30m -run TestLogPoller"
envcmd: "cl u env.toml,tests/logpoller/finality_tag.toml"
runner: "ubuntu24.04-16cores-64GB"
tests_dir: "logpoller"
logs_archive_name: "logpoller-finality-tag"
steps:
- name: Check if job should run
id: gate
working-directory: .
run: |
if [[ "${{ github.event_name }}" == "pull_request" && "${{ matrix.run_on_pr }}" == "false" ]]; then
echo "should_run=false" >> "$GITHUB_OUTPUT"
echo "Skipping ${{ matrix.display_name }} on PR"
else
echo "should_run=true" >> "$GITHUB_OUTPUT"
fi

# DEBUG: Run monitor for tests
- name: Monitor
if: steps.gate.outputs.should_run == 'true'
uses: kalverra/octometrics-action@v0.0.10

Check failure on line 217 in .github/workflows/devenv-nightly.yml

View workflow job for this annotation

GitHub Actions / Validate Workflow Changes

1. v0.0.10 is not a valid SHA reference (sha-ref / error) 2. No version comment found (version-comment / warning)
with:
job_name: ${{ matrix.display_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout code
uses: actions/checkout@v5
if: steps.gate.outputs.should_run == 'true'
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
if: steps.gate.outputs.should_run == 'true'
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

- name: Install Just
if: steps.gate.outputs.should_run == 'true'
uses: extractions/setup-just@e33e0265a09d6d736e2ee1e0eb685ef1de4669ff # v3
with:
just-version: "1.40.0"

- name: Configure AWS credentials using OIDC
uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
if: steps.gate.outputs.should_run == 'true'
uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0
with:
role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_SDLC_ECR_READONLY_ARN }}
aws-region: us-west-2

- name: Authenticate to ECR
if: steps.gate.outputs.should_run == 'true'
id: login-ecr
uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1

- name: Set up Go
if: steps.gate.outputs.should_run == 'true'
uses: actions/setup-go@v6 # v6
with:
cache: true
go-version-file: devenv/go.mod
cache-dependency-path: devenv/go.sum

- name: Download Go dependencies
if: steps.gate.outputs.should_run == 'true'
run: |
go mod download

- name: Set environment variables
if: steps.gate.outputs.should_run == 'true'
run: |
IMAGE_VERSION="nightly-$(date +%Y%m%d)"
FULL_IMAGE="${{ secrets.REGISTRY_SDLC }}/chainlink:${IMAGE_VERSION}"
echo "CHAINLINK_IMAGE=${FULL_IMAGE}" >> $GITHUB_ENV

- name: Setup environment
if: steps.gate.outputs.should_run == 'true'
env:
FAKE_SERVER_IMAGE: ${{ secrets.FAKE_SERVER_IMAGE }}
run: |
Expand All @@ -218,6 +279,7 @@
eval $ENV_CMD

- name: Run tests
if: steps.gate.outputs.should_run == 'true'
working-directory: devenv/tests/${{ matrix.tests_dir }}
env:
CURRENT_TEST: ${{ matrix.testcmd }}
Expand All @@ -227,7 +289,7 @@
eval $TESTCMD

- name: Upload Logs
if: always()
if: always() && steps.gate.outputs.should_run == 'true'
uses: actions/upload-artifact@v4
with:
name: container-logs-${{ matrix.logs_archive_name }}
Expand Down
104 changes: 104 additions & 0 deletions devenv/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# Devenv — AI Agent Guidelines

This file documents conventions and constraints for the `devenv` module. Follow these rules when generating, modifying, or reviewing code under `devenv/`.

## Module Isolation

`devenv` is a standalone Go module: `github.com/smartcontractkit/chainlink/devenv`.

**Critical rule**: NEVER import `github.com/smartcontractkit/chainlink/v2` or any of its children (e.g. `chainlink/v2/core/...`, `chainlink/integration-tests/...`, `chainlink/deployment/...`). This is enforced by `depguard` in `.golangci.yml` and will fail CI.

### Allowed Dependencies

| Dependency | Use for |
| ------------------------------------------------------------------- | ------------------------------------------------------------------ |
| `github.com/smartcontractkit/chainlink-testing-framework/framework` | Docker orchestration, `clclient` (CL node HTTP API), observability |
| `github.com/smartcontractkit/chainlink-evm/gethwrappers` | On-chain contract interaction (deploy, call, transact) |
| `github.com/smartcontractkit/libocr` | OCR-specific contract wrappers |
| `github.com/ethereum/go-ethereum` | ETH client, `bind`, ABI, `common`, `crypto` |
| `github.com/stretchr/testify` | Test assertions (`require`, `assert`) |
| `github.com/google/uuid` | UUID generation |
| Standard library | Everything else |

### Denied Packages

These are enforced by depguard and will cause lint failures:

| Denied | Use instead |
| --------------------------------------------------------- | ------------------------------------------- |
| `github.com/smartcontractkit/chainlink/v2` (and children) | Local implementations or CTF equivalents |
| `github.com/BurntSushi/toml` | `github.com/pelletier/go-toml/v2` |
| `github.com/smartcontractkit/chainlink-integrations/evm` | `github.com/smartcontractkit/chainlink-evm` |
| `github.com/gofrs/uuid`, `github.com/satori/go.uuid` | `github.com/google/uuid` |
| `github.com/test-go/testify/*` | `github.com/stretchr/testify/*` |
| `go.uber.org/multierr` | `errors.Join` (standard library) |
| `gopkg.in/guregu/null.v1/v2/v3` | `gopkg.in/guregu/null.v4` |
| `github.com/go-gorm/gorm` | `github.com/jmoiron/sqlx` |

## Product Interface

Every Chainlink product in devenv implements the `Product` interface defined in [interface.go](interface.go). Read that file for the exact method signatures.

### Adding a New Product
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely useful, thanks. Will try to use it to automate the refactoring 🙏


1. Create `products/<name>/configuration.go` implementing `Product` — see any existing product (e.g. [products/cron/configuration.go](products/cron/configuration.go)) as a reference
2. Create `products/<name>/basic.toml` with default TOML config
3. Register in [environment.go](environment.go) — add a `case "<name>"` in `newProduct()`
4. Create `tests/<name>/smoke_test.go`
5. Add a matrix entry in [`.github/workflows/devenv-nightly.yml`](../.github/workflows/devenv-nightly.yml)

If migrating an existing test from `integration-tests/smoke/`, follow the full step-by-step process in [MIGRATION_GUIDE.md](MIGRATION_GUIDE.md).

### Product Lifecycle

The environment calls product methods in this order:

1. `Load()` — parse product config from merged TOML
2. `GenerateNodesConfig()` — return CL node TOML overrides
3. `GenerateNodesSecrets()` — return CL node secrets overrides
4. *(infrastructure starts: blockchain, fake server, CL nodes)*
5. `ConfigureJobsAndContracts()` — deploy contracts, create keys/jobs, fund nodes
6. `Store()` — write deployed state (addresses, job IDs) to `env-out.toml`

See [environment.go](environment.go) `NewEnvironment()` for the full orchestration flow.

## Test Conventions

Tests use a two-phase pattern: environment setup (via `cl` CLI) then test execution (via `go test`).

### Test File Structure

See [tests/cron/smoke_test.go](tests/cron/smoke_test.go) for the simplest example of the standard pattern. Every smoke test follows the same structure:

1. Load infrastructure output via `de.LoadOutput[de.Cfg]`
2. Load product output via `products.LoadOutput[<product>.Configurator]`
3. Save container logs in `t.Cleanup`
4. Create clients (ETH and/or CL node)
5. Interact with contracts and assert results

### Key Patterns

- Output file path from `tests/<product>/` is always `../../env-out.toml`
- Use `products.ETHClient()` for Ethereum client creation with gas settings
- Use `products.WaitMinedFast()` for fast transaction confirmation on Anvil
- Use `clclient.New()` for CL node API access (job runs, keys, jobs)
- Use `require.EventuallyWithT` for async assertions (typical: 2 min timeout, 2 s interval)
- Use gethwrappers from `chainlink-evm/gethwrappers` directly for contract bindings

## Configuration

- Base infra: `env.toml` (blockchain, fake server, node set)
- Product config: `products/<name>/basic.toml`
- CLI merges configs left-to-right: `cl u env.toml,products/<name>/basic.toml`
- Output written to `env-out.toml` after environment starts

## Formatting and Linting

- **Formatter**: goimports with local prefix `github.com/smartcontractkit/chainlink`
- **Linter config**: `devenv/.golangci.yml`
- **Run linter**: `golangci-lint run` from the `devenv/` directory
- **nolint directives**: must include both an explanation and a specific linter name

## CI

Tests run via [`.github/workflows/devenv-nightly.yml`](../.github/workflows/devenv-nightly.yml) using a matrix with `envcmd` and `testcmd` pairs. When adding a new test, copy an existing matrix entry and update the product name, test command, and directory fields.
5 changes: 4 additions & 1 deletion devenv/Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ push-fakes registry:

# Rebuild CLI
cli:
cd cmd/cl && go install -ldflags="-X main.Version=1.0.0" . && cd - > /dev/null || exit 1
cd cmd/cl && go install -ldflags="-X main.Version=1.0.0" . && cd - > /dev/null || exit 1

lint:
golangci-lint run ./... --fix
Loading
Loading