Skip to content

Commit 992691f

Browse files
chore: add Github live sync integration tests (#542)
1 parent c6f41d8 commit 992691f

31 files changed

Lines changed: 1725 additions & 102 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ venv/
132132
ENV/
133133
env.bak/
134134
venv.bak/
135+
/server/application-server/src/test/resources/application-github-integration-local.yml
135136

136137
# Spyder project settings
137138
.spyderproject

AGENTS.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
This file governs the entire repository. Combine these guardrails with the scoped instructions under `.github/instructions/**` (general coding, TSX, Storybook, Java tests).
44

55
## 1. Architecture map
6+
67
- `server/application-server/`: Spring Boot 3.5, Liquibase-managed PostgreSQL schema, synchronous + reactive APIs, generated OpenAPI spec in `openapi.yaml`.
78
- `webapp/`: React 19 + TanStack Router/Query, Tailwind 4 UI kit (`src/components/ui`), generated API client in `src/api/**`.
89
- `server/intelligence-service/`: FastAPI service orchestrating AI models. OpenAPI spec is exported via Poetry and mirrored into the Java client under the application server.
910
- `server/webhook-ingest/`: FastAPI webhook intake that forwards events into NATS JetStream.
1011
- `docs/`: Contributor docs (including the ERD that `db:generate-erd-docs` regenerates).
1112

1213
## 2. Toolchain & environment prerequisites
14+
1315
- **Node.js**: Use the exact version from `.node-version` (currently 22.10.0). Stick with npm—the repo maintains `package-lock.json` and uses npm workspaces.
1416
- **Java**: JDK 21 (see `pom.xml`). Maven wrapper is checked in; **always run builds through `./mvnw`** (Maven wrapper) to ensure consistent Maven versions.
1517
- **Python**: Python 3.13 with Poetry 2.x. Both Python services keep virtualenvs inside their folders (`.venv`). Run `npm run bootstrap:py` before formatting/linting to ensure dev dependencies are installed.
@@ -18,6 +20,7 @@ This file governs the entire repository. Combine these guardrails with the scope
1820
- **Environment variables**: When generating intelligence service OpenAPI specs locally, set `MODEL_NAME=fake:model` and `DETECTION_MODEL_NAME=fake:model` (the FastAPI settings expect a provider-qualified model name).
1921

2022
## 3. Quality gates & routine commands
23+
2124
Run the relevant commands locally before opening a PR:
2225

2326
| Concern | Commands |
@@ -27,13 +30,14 @@ Run the relevant commands locally before opening a PR:
2730
| Webapp build | `npm --workspace webapp run build` (Vite build + `tsc --noEmit`) |
2831
| Webapp tests | `npm --workspace webapp run test` (Vitest) and add focused unit tests when touching logic. |
2932
| Storybook | `npm --workspace webapp run build-storybook` (Chromatic depends on a clean build). |
30-
| Application-server tests | Use Maven groups to mirror CI: `./mvnw test -Dgroups=unit`, `-Dgroups=integration`, `-Dgroups=architecture`. |
33+
| Application-server tests | Use Maven groups to mirror CI: `./mvnw test -Dgroups=unit`, `-Dgroups=integration`, `-Dgroups=architecture`. Live GitHub sync tests stay skipped unless you pass `-Dgroups=github-integration`, which activates the `github-integration-tests` profile. |
3134
| Intelligence service lint/type check | `poetry run black --check .`, `poetry run flake8 .`, `poetry run mypy .` inside `server/intelligence-service`. |
3235
| Webhook ingest lint | `poetry run black --check .` and `poetry run flake8 .` inside `server/webhook-ingest`. |
3336

3437
Document any skipped gate in the PR description with a rationale. Always finish a change set by running `npm run format` followed by `npm run lint` so both styling and type checks reflect the final state.
3538

3639
## 4. Code generation & forbidden edits
40+
3741
We rely heavily on generated artifacts. Never hand-edit these directories—regenerate instead:
3842

3943
| Artifact | Source command |
@@ -48,6 +52,7 @@ We rely heavily on generated artifacts. Never hand-edit these directories—rege
4852
Regeneration is destructive; stash local edits before running these commands. Check diffs carefully—generated clients must be committed alongside API changes.
4953

5054
## 5. Database workflow (Liquibase)
55+
5156
- Liquibase changelog files live under `server/application-server/src/main/resources/db/changelog/` and are included via `master.xml`.
5257
- Use `npm run db:draft-changelog` after changing JPA entities. The script will:
5358
1. Spin up PostgreSQL through Docker (ensure Docker is running or set `CI=true` with a ready Postgres).
@@ -58,6 +63,7 @@ Regeneration is destructive; stash local edits before running these commands. Ch
5863
- Never manually edit generated Liquibase diff sections unless you fully understand the implications. Prefer creating a follow-up changelog to fix mistakes.
5964

6065
## 6. Frontend (webapp) expectations
66+
6167
- Follow the container/presentation split already in place (route files under `src/routes/**` fetch data and pass it to components under `src/components/**`). Keep components pure and side-effect free.
6268
- Fetch data exclusively with TanStack Query v5 and the generated helpers in `@/api/@tanstack/react-query.gen.ts`. Spread the option objects: `useQuery(getTeamsOptions({ ... }))`. Use the generated `*.QueryKey()` helpers for cache invalidation.
6369
- Do not call `fetch` directly; reuse the generated `@hey-api` client configured in `src/api/client.ts` and the shared QueryClient from `src/integrations/tanstack-query/root-provider.tsx`.
@@ -70,6 +76,7 @@ Regeneration is destructive; stash local edits before running these commands. Ch
7076
- Never hand-edit `routeTree.gen.ts`; it is generated by TanStack Router tooling.
7177

7278
## 7. Application server (Java/Spring) expectations
79+
7380
- Keep business logic in services annotated with `@Service` and transactional boundaries (`@Transactional`) where needed. Controllers should be thin (input validation + delegation).
7481
- Use Lombok consistently (`@Getter`, `@Setter`, etc.) but prefer explicit builders or records when immutability helps.
7582
- Group new tests under the proper JUnit tag so CI picks them up (`@Tag("unit")`, `@Tag("integration")`, or `@Tag("architecture")`). Follow the mantra in `.github/instructions/java-tests.instructions.md` (AAA structure, single assertion focus, deterministic data).
@@ -80,6 +87,7 @@ Regeneration is destructive; stash local edits before running these commands. Ch
8087
- When integrating with the intelligence-service client, always regenerate (`npm run generate:api:intelligence-service:client`) after touching the spec and commit the updated Java files.
8188

8289
## 8. Python services expectations
90+
8391
- Both services rely on Poetry with in-project virtualenvs. Run `poetry install --with dev --no-root` before running tooling.
8492
- Intelligence service:
8593
- Settings live in `app/settings.py`; `MODEL_NAME` and `DETECTION_MODEL_NAME` must be provider-qualified (`openai:gpt-4o`, `fake:model`, etc.). For tooling/CI we rely on the `fake` provider.
@@ -91,19 +99,23 @@ Regeneration is destructive; stash local edits before running these commands. Ch
9199
- Formatting: run `poetry run black .` (or `--check`) and `poetry run flake8 .`. Add type hints so mypy stays green in the intelligence service.
92100

93101
## 9. Documentation & assets
102+
94103
- ERD diagrams live under `docs/contributor/erd/`. Regenerate via `npm run db:generate-erd-docs` after schema changes.
95104
- Contributor documentation should stay in `docs/` (GitHub Pages). Keep README/CONTRIBUTING updates concise and actionable.
96105
- Screenshots or large binary assets belong under `docs/images/` or the Storybook stories, not inside source directories.
97106

98107
## 10. Commit & PR checklist
108+
99109
Before marking work ready for review:
110+
100111
- [ ] Regenerate and commit any impacted OpenAPI specs, clients, ERD docs, or generated SQLAlchemy models.
101112
- [ ] Run the formatting/linting/typecheck/test commands relevant to the modified modules; capture output for the PR description if CI cannot run a job locally.
102113
- [ ] Verify database migrations through `db:draft-changelog` when JPA entities change and inspect the produced XML.
103114
- [ ] Double-check that no generated files were edited manually.
104115
- [ ] Follow Conventional Commit semantics for PR titles (`feat(webapp): ...`, etc., see `CONTRIBUTING.md`).
105116

106117
## 11. Known command caveats
118+
107119
- `npm run db:draft-changelog` requires Docker to be installed and available on PATH. In CI we set `CI=true`; locally ensure Docker Desktop/daemon is running before invoking the script.
108120
- `npm run generate:api:intelligence-service:specs` fails unless `MODEL_NAME` and `DETECTION_MODEL_NAME` are set (use the `fake:model` provider for tooling).
109121
- `npm run generate:api:application-server:specs` performs a full Maven `verify` against the specs profile. The initial run downloads the entire Spring Boot dependency tree (~hundreds of MB); expect several minutes on a cold cache.

docs/contributor/testing.mdx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,60 @@ Available examples include `label.created`, `repository.created`, `create`, `pus
9696

9797
Use the optional `-Dgroups=unit` or `-Dgroups=integration` flags once category support lands.
9898

99+
## GitHub live sync integration tests
100+
101+
Some regression scenarios can only be validated against GitHub itself. We ship a focused suite that exercises the live GitHub App installation and verifies end-to-end sync behaviour (repository metadata, labels, milestones, and teams).
102+
103+
### Prerequisites
104+
105+
1. **Sandbox installation** – the `Hephaestus IntegrationTests` GitHub App must be installed in a sandbox organisation you control. The tests create and delete repositories, milestones, labels, and teams on each run.
106+
2. **Credentials** – provide both a GitHub App private key and a Personal Access Token with the following scopes:
107+
- `repo` (full)
108+
- `admin:org`
109+
- `read:packages`
110+
3. **Local config file** – copy the template that lives alongside the tests:
111+
112+
```bash
113+
cd server/application-server/src/test/resources
114+
cp application-github-integration-local.example.yml application-github-integration-local.yml
115+
```
116+
117+
Fill in the placeholders with the sandbox organisation slug, the installation id, and either an inline PEM key (`github.app.privateKey`) or a readable `privateKeyLocation`. Keep this file out of version control—it is already listed in `.gitignore`.
118+
119+
Alternatively, export the matching environment variables:
120+
121+
```bash
122+
export GH_IT_APP_ID=2250297
123+
export GH_IT_APP_PAT=ghp_xxx... # PAT with the scopes above
124+
export GH_IT_INSTALLATION_ID=93512943
125+
export GH_IT_ORGANIZATION=HephaestusTest
126+
export GH_IT_APP_PRIVATE_KEY_PATH=/absolute/path/to/private-key.pem
127+
```
128+
129+
Use either the file _or_ the environment variables; the suite checks both and aborts if key material is missing.
130+
131+
### Running the suite
132+
133+
From `server/application-server/` run:
134+
135+
```bash
136+
./mvnw test -Dgroups=github-integration
137+
```
138+
139+
Passing the `groups` system property automatically activates the `github-integration-tests` Maven profile, which clears the default exclusion and runs only the live GitHub scenarios. The regular CI pipeline never sets this flag, so these tests remain skipped unless you opt in locally.
140+
141+
The run takes roughly two minutes and prints the GitHub artefacts it provisions. Clean-up is handled automatically, but if a failure interrupts execution you can safely delete any `hephaestus-it-*` repositories, milestones, or teams that remain in the sandbox.
142+
143+
### Authoring new GitHub sync tests
144+
145+
1. Extend `AbstractGitHubSyncIntegrationTest` (or fall back to `BaseGitHubIntegrationTest` when repositories are not needed). These bases set up credential checks, provide the `workspaceRepository`, and expose helpers such as `createEphemeralRepository`, `registerRepositoryToMonitor`, `createEphemeralTeam`, and `seedOrganizationMembers`.
146+
2. Use the supplied helpers to create and track temporary GitHub artefacts. They automatically register clean-up handlers via `@AfterEach`, so add new resources to the provided lists instead of implementing manual deletion logic.
147+
3. Keep tests deterministic: rely on `databaseTestUtils.cleanDatabase()` in `@BeforeEach` (already invoked by the base), and generate unique slugs via `nextEphemeralSlug("suffix")` when naming repositories, branches, or teams.
148+
4. If a scenario needs extra Spring configuration, extend `application-github-integration-local.yml` in `server/application-server/src/test/resources/`. The checked-in `.example` file documents every property; copy it on demand and keep secrets out of version control.
149+
150+
### Troubleshooting
151+
152+
- **Skipping because of missing credentials** – check the console output; the base test class verifies that the App id, private key, PAT, and installation id are all present before executing.
153+
- **Hub4j rate-limit failures** – the suite creates several entities per run. Prefer a dedicated sandbox organisation so you do not clash with production automation limits.
154+
- **Longer runtimes** – each suite bootstraps a Testcontainers PostgreSQL instance and provisions GitHub resources. Expect higher runtimes than the pure Testcontainers integration tests; avoid running them on every PR and instead use them before releases or when touching the GitHub sync layer.
155+

0 commit comments

Comments
 (0)