You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: skills/building-integration/SKILL.md
+13-5Lines changed: 13 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -141,16 +141,22 @@ pytest <name>/ -v
141
141
142
142
Only runs tests in `test_*_unit.py` files (configured in `pyproject.toml`).
143
143
144
-
### Step 5 — Auto-fix lint and formatting issues
144
+
### Step 5 — Verify `.env.example` for integration-test env vars
145
145
146
-
If steps 2–4 report ruff errors, auto-fix with:
146
+
If the integration has `test_*_integration.py` files, check whether they reference environment variables via `env_credentials(...)`, `os.environ.get(...)`, `os.getenv(...)`, `os.environ[...]`, or equivalent helpers. Every referenced variable must appear as a blank template entry in the repository root `.env.example`.
147
+
148
+
This is a manual review/build requirement: `.env` stays local and uncommitted, but `.env.example` is the committed contract that tells humans, reviewers, and automation what to provide.
| Internal-only documentation (`INTERNAL.md`, `RUNBOOK.md` referencing internal infra) | Keep in private repo or rewrite without internal references. |
123
123
|`.env*` files | Should not exist anywhere; if they do, abort Step 1. |
124
+
| Migrated integration tests reference env vars but root `.env.example` was not updated | Add blank entries for every referenced env var in the public repo's root `.env.example`. |
- Strip any internal references (Slack channels, Notion links, employee names) from the README before copying.
156
+
-**Root `.env.example`** → if migrated tests read environment variables, add every required and optional test variable to the public repo's root `.env.example` in the same PR. Include variables read through `env_credentials(...)`, `os.environ.get(...)`, `os.getenv(...)`, `os.environ[...]`, or equivalent helpers. Do **not** copy private `.env*` files; only add blank template entries such as `MYINTEGRATION_ACCESS_TOKEN=` and `MYINTEGRATION_TEST_ITEM_ID=`.
155
157
156
158
### Update the repo-level READMEs
157
159
@@ -173,6 +175,7 @@ Required outcome:
173
175
-`validate_integration.py` → `0` exit code (warnings about deprecated SDK pin are OK for a pure migration).
174
176
-`check_code.py` → `✅ CODE CHECK PASSED`.
175
177
-`pytest` → no failures (placeholder tests are fine; new tests are out of scope for a migration).
178
+
- If migrated tests reference env vars, root `.env.example` includes all of them as blank template entries.
If the integration tests read credentials or test resource IDs from environment variables, also verify the repository root `.env.example` lists every variable used by those tests. Add missing entries in the same PR. This applies to variables read through `env_credentials(...)`, `os.environ.get(...)`, `os.getenv(...)`, `os.environ[...]`, or equivalent helpers. The local `.env` file remains uncommitted; `.env.example` is the committed setup contract for humans and tooling.
214
+
213
215
### Step 7 — Local validation (required before pushing)
214
216
215
217
Run the **same checks CI runs** locally. Skipping this step will result in CI failures. The tooling repo must be cloned alongside the integrations repo (see [CONTRIBUTING.md](CONTRIBUTING.md) for setup).
@@ -263,6 +265,7 @@ Before considering an integration upgraded, verify:
263
265
-[ ] Unit test error assertions use `result.type == ResultType.ACTION_ERROR` and `result.result.message`
264
266
-[ ]`pytest.raises(ValidationError)` replaced with `result.type == ResultType.VALIDATION_ERROR`
265
267
-[ ] Integration test `real_fetch` returns `FetchResponse(...)` (if applicable)
268
+
-[ ] Integration test env vars are documented in root `.env.example` (if integration tests read env vars)
266
269
-[ ]`FetchResponse` and `ResultType` are imported where needed
267
270
-[ ] All unit tests pass
268
271
-[ ]`ruff check` and `ruff format --config ../autohive-integrations-tooling/ruff.toml` pass
@@ -299,3 +302,5 @@ Before considering an integration upgraded, verify:
299
302
The 2.0.0 upgrade is the right time to catch this because you're already touching the auth path to convert error returns to `ActionError`.
300
303
301
304
10. **PyPI package name collision**: If your integration folder name matches a PyPI package the source imports (e.g. an integration in`supadata/` that does `from supadata import Supadata`), an empty `<integration>/__init__.py` will shadow the real PyPI package and every test fails with`ImportError`. Drop `<integration>/__init__.py` — the validator's "missing __init__.py" warning is correct to ignore in this case, and the Lambda runtime is unaffected (the entry point is the action source file, not the package). See the `writing-unit-tests` skill for the matching test-side guidance.
305
+
306
+
11. **Missing `.env.example` entries after touching integration tests**: SDK upgrades often touch `live_context`and credential handling. If the integration test file references `FOO_ACCESS_TOKEN`, `FOO_TEST_ID`, or similar, root `.env.example` must contain `FOO_ACCESS_TOKEN=`, `FOO_TEST_ID=`, etc. Do not rely on future contributors or automation to grep test code for setup requirements.
Copy file name to clipboardExpand all lines: skills/writing-integration-tests/SKILL.md
+18-5Lines changed: 18 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
---
2
2
name: writing-integration-tests
3
-
description: "Writes pytest end-to-end integration tests for an Autohive integration that call real APIs using the live_context fixture pattern. Use when asked to write integration tests, add e2e tests, create live API tests, or test an integration against a real service. Covers file structure, live_context fixture variants, environment variable handling, destructive markers, and test organization."
3
+
description: "Writes pytest end-to-end integration tests for an Autohive integration that call real APIs using the live_context fixture pattern. Use when asked to write integration tests, add e2e tests, create live API tests, or test an integration against a real service. Covers file structure, live_context fixture variants, required root .env.example updates, environment variable handling, destructive markers, and test organization."
4
4
---
5
5
6
6
# Writing Integration Tests for an Integration
@@ -125,9 +125,18 @@ class TestGetItem:
125
125
...
126
126
```
127
127
128
-
### .env.example Documentation
128
+
### .env.example Documentation (required)
129
129
130
-
Document all required and optional environment variables in the integration's `.env.example`:
130
+
If an integration test reads any environment variable, you **must** add that variable to the repository root `.env.example` in the same PR. This is not optional documentation — it is part of the integration-test deliverable.
131
+
132
+
Why this matters:
133
+
- Humans can set up local integration tests without digging through test code for variable names.
134
+
- Automated and AI tooling can discover which credentials, test IDs, and optional knobs it needs to ask for.
135
+
- Reviewers have one canonical place to verify the local test contract.
136
+
137
+
Add every variable used by `env_credentials(...)`, `os.environ.get(...)`, `os.getenv(...)`, `os.environ[...]`, or equivalent helpers. Include both required credentials and optional test resource IDs. Keep real secrets only in local `.env`; never commit `.env`.
138
+
139
+
Use a clearly labeled block in root `.env.example`:
131
140
132
141
```bash
133
142
# -- MyIntegration --
@@ -136,6 +145,8 @@ MYINTEGRATION_TEST_ITEM_ID=
136
145
MYINTEGRATION_TEST_PROJECT_ID=
137
146
```
138
147
148
+
Before finishing, cross-check the integration test file against `.env.example`: every env var referenced in tests must appear in `.env.example`, even if the test skips when it is missing.
149
+
139
150
## The live_context Fixture
140
151
141
152
The `live_context` fixture provides a `MagicMock` of the SDK's `ExecutionContext` but replaces the `fetch` method with a real async HTTP client using `aiohttp`. This lets the integration code run unchanged while making real network calls.
@@ -455,7 +466,7 @@ Write actions (create/update/delete) need at least:
455
466
1.**Read the integration source** — understand each action and its auth mechanism
456
467
2.**Check `config.json`** — determine auth type (none / API key / platform OAuth)
457
468
3.**Choose the right `live_context` variant** — see the three variants above
458
-
4.**Document env vars** in `.env.example`
469
+
4.**Document env vars in root `.env.example` (required)** — add every env var referenced by the integration test file in the same PR
459
470
5.**Write read-only tests first** — these are safe to run repeatedly
460
471
6.**Add destructive tests** with `@pytest.mark.destructive` for write actions
461
472
7.**Run read-only tests**:
@@ -483,7 +494,9 @@ Write actions (create/update/delete) need at least:
483
494
484
495
5.**Destructive test cleanup**: Always clean up created data at the end of lifecycle tests. Use `os.getpid()` in created object names to avoid collisions when running tests in parallel.
485
496
486
-
6.**OAuth token expiry**: Platform OAuth tokens expire. Document the refresh process in the integration's README or `.env.example`.
497
+
6.**Missing `.env.example` entries**: If you add `env_credentials("FOO")`, `os.environ.get("FOO")`, or similar test env-var usage, add `FOO=` to root `.env.example` before you commit. Do not make reviewers or future contributors grep test files to discover setup requirements.
498
+
499
+
7.**OAuth token expiry**: Platform OAuth tokens expire. Document the refresh process in the integration's README or root `.env.example`.
0 commit comments