diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c7d1178..065ef48 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,17 +32,12 @@ jobs: python-version: "3.12" - name: Install dependencies - run: pip install outerbounds ob-project-utils pyyaml + run: pip install outerbounds ob-project-utils - name: Configure Outerbounds run: | - PROJECT_NAME=$(yq .project obproject.toml) - PLATFORM=$(yq .platform obproject.toml) - CICD_USER="${PROJECT_NAME//_/-}-cicd" outerbounds service-principal-configure \ - --name $CICD_USER \ - --deployment-domain $PLATFORM \ - --perimeter default \ + --from-obproject-toml \ --github-actions - name: Deploy Project @@ -67,23 +62,24 @@ jobs: python-version: "3.12" - name: Install dependencies - run: pip install outerbounds ob-project-utils pyyaml + run: pip install outerbounds ob-project-utils - name: Configure Outerbounds run: | - PROJECT_NAME=$(yq .project obproject.toml) - PLATFORM=$(yq .platform obproject.toml) - CICD_USER="${PROJECT_NAME//_/-}-cicd" outerbounds service-principal-configure \ - --name $CICD_USER \ - --deployment-domain $PLATFORM \ - --perimeter default \ + --from-obproject-toml \ --github-actions - name: Teardown branch resources run: | BRANCH=${{ github.head_ref || github.event.ref }} - PROJECT=$(yq .project obproject.toml) + PROJECT=$(python3 -c " + try: + import tomllib + except ImportError: + import toml as tomllib + print(tomllib.load(open('obproject.toml','rb'))['project']) + ") echo "Tearing down $PROJECT/$BRANCH" outerbounds flowproject teardown-branch \ --id "$PROJECT/$BRANCH" --yes -o json diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f504edb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,44 @@ +# Prod Event Example (prod_event_example) + +Demonstrates branch-scoped event triggering where only the production +(main branch) deployment reacts to external signals. Shows the difference +between `@project_trigger`, `@trigger_on_finish`, `@schedule`, and `@trigger`. + +## Platform Features Used + +- **Events**: `@project_trigger(event="external_signal")` for branch-scoped external events; `prj.safe_publish_event("ingest_complete")` for internal events +- **Schedules**: `@schedule(cron="0 8 * * 1-5")` weekday morning ingest +- **Flow chaining**: `@trigger_on_finish(flow="EventProcessorFlow")` (auto branch-scoped) +- **Dev-assets**: `[dev-assets] branch = "main"` for cross-branch data reads + +## Flows + +| Flow | Trigger | Purpose | +|------|---------|---------| +| ScheduledIngestFlow | @schedule(cron) | Daily ingest, publishes `ingest_complete` event | +| EventProcessorFlow | @project_trigger(external_signal) | Processes external events, branch-isolated | +| ChainedReporterFlow | @trigger_on_finish(EventProcessor) | Reports after event processing | + +## Event Scoping + +`@project_trigger` creates sensors scoped to `prj...`: +- Main: `prj.prod_event_example.main.external_signal` +- Feature branch: `prj.prod_event_example..external_signal` + +External systems target prod by publishing to the `main` event name explicitly. + +## Run Locally + +```bash +cd prod-event-example +python flows/scheduled_ingest/flow.py run +python flows/event_processor/flow.py run +# chained_reporter requires an upstream run in Argo (uses current.trigger.run) +``` + +## Common Pitfalls + +- `@trigger(event=...)` is NOT branch-scoped -- all branches react to the same event. Use `@project_trigger` instead. +- ChainedReporterFlow cannot run locally without a trigger context (`current.trigger.run` would be None) +- External event publishers must specify both project and branch to target the correct deployment +- See TESTING.md for the full verification plan including branch isolation tests