ayasee 0.1.0rc2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ayasee-0.1.0rc2/.github/workflows/ci.yml +150 -0
- ayasee-0.1.0rc2/.github/workflows/cockpit-collect.yml +289 -0
- ayasee-0.1.0rc2/.github/workflows/docs.yml +54 -0
- ayasee-0.1.0rc2/.github/workflows/e2e.yml +94 -0
- ayasee-0.1.0rc2/.github/workflows/iac-breakglass.yml +427 -0
- ayasee-0.1.0rc2/.github/workflows/iac-nightly.yml +382 -0
- ayasee-0.1.0rc2/.github/workflows/iac-pr.yml +579 -0
- ayasee-0.1.0rc2/.github/workflows/iac-staged.yml +861 -0
- ayasee-0.1.0rc2/.github/workflows/release.yml +276 -0
- ayasee-0.1.0rc2/.gitignore +37 -0
- ayasee-0.1.0rc2/.impeccable/design.json +962 -0
- ayasee-0.1.0rc2/.python-version +1 -0
- ayasee-0.1.0rc2/CHANGELOG.md +214 -0
- ayasee-0.1.0rc2/CONTRIBUTING.md +115 -0
- ayasee-0.1.0rc2/DESIGN.md +401 -0
- ayasee-0.1.0rc2/GOVERNANCE.md +24 -0
- ayasee-0.1.0rc2/LICENSE +202 -0
- ayasee-0.1.0rc2/NOTICE +15 -0
- ayasee-0.1.0rc2/PKG-INFO +41 -0
- ayasee-0.1.0rc2/PRODUCT.md +90 -0
- ayasee-0.1.0rc2/README.md +26 -0
- ayasee-0.1.0rc2/SECURITY.md +113 -0
- ayasee-0.1.0rc2/actions/apply/action.yml +79 -0
- ayasee-0.1.0rc2/actions/apply/apply.sh +187 -0
- ayasee-0.1.0rc2/actions/cockpit-site/action.yml +66 -0
- ayasee-0.1.0rc2/actions/guard/action.yml +39 -0
- ayasee-0.1.0rc2/actions/ledger/action.yml +58 -0
- ayasee-0.1.0rc2/actions/lib/ayasee-lib.sh +328 -0
- ayasee-0.1.0rc2/actions/notify/action.yml +55 -0
- ayasee-0.1.0rc2/actions/plan/action.yml +125 -0
- ayasee-0.1.0rc2/actions/plan/encryption.tofu.tmpl +14 -0
- ayasee-0.1.0rc2/actions/plan/plan.sh +126 -0
- ayasee-0.1.0rc2/actions/policy/action.yml +34 -0
- ayasee-0.1.0rc2/actions/policy/policy.sh +38 -0
- ayasee-0.1.0rc2/actions/risk/action.yml +54 -0
- ayasee-0.1.0rc2/actions/setup/action.yml +46 -0
- ayasee-0.1.0rc2/actions/setup/install.sh +54 -0
- ayasee-0.1.0rc2/cockpit-site/.gitignore +2 -0
- ayasee-0.1.0rc2/cockpit-site/index.html +26 -0
- ayasee-0.1.0rc2/cockpit-site/package-lock.json +2030 -0
- ayasee-0.1.0rc2/cockpit-site/package.json +21 -0
- ayasee-0.1.0rc2/cockpit-site/src/app.ts +169 -0
- ayasee-0.1.0rc2/cockpit-site/src/drawer.ts +358 -0
- ayasee-0.1.0rc2/cockpit-site/src/format.ts +53 -0
- ayasee-0.1.0rc2/cockpit-site/src/history.ts +98 -0
- ayasee-0.1.0rc2/cockpit-site/src/load.ts +60 -0
- ayasee-0.1.0rc2/cockpit-site/src/main.ts +10 -0
- ayasee-0.1.0rc2/cockpit-site/src/matrix.ts +334 -0
- ayasee-0.1.0rc2/cockpit-site/src/model.ts +68 -0
- ayasee-0.1.0rc2/cockpit-site/src/status.ts +110 -0
- ayasee-0.1.0rc2/cockpit-site/src/styles.css +225 -0
- ayasee-0.1.0rc2/cockpit-site/test/drawer.test.ts +381 -0
- ayasee-0.1.0rc2/cockpit-site/test/fixtures/snapshot.json +257 -0
- ayasee-0.1.0rc2/cockpit-site/test/history.test.ts +139 -0
- ayasee-0.1.0rc2/cockpit-site/test/load.test.ts +100 -0
- ayasee-0.1.0rc2/cockpit-site/test/matrix.test.ts +203 -0
- ayasee-0.1.0rc2/cockpit-site/test/model.test.ts +22 -0
- ayasee-0.1.0rc2/cockpit-site/test/status.test.ts +62 -0
- ayasee-0.1.0rc2/cockpit-site/tsconfig.json +20 -0
- ayasee-0.1.0rc2/cockpit-site/vite.config.ts +14 -0
- ayasee-0.1.0rc2/docs/README.md +87 -0
- ayasee-0.1.0rc2/docs/cockpit/setup.md +132 -0
- ayasee-0.1.0rc2/docs/comparison.md +204 -0
- ayasee-0.1.0rc2/docs/compliance/dora-art17.md +107 -0
- ayasee-0.1.0rc2/docs/concepts/architecture.md +258 -0
- ayasee-0.1.0rc2/docs/concepts/cockpit.md +153 -0
- ayasee-0.1.0rc2/docs/concepts/drift.md +119 -0
- ayasee-0.1.0rc2/docs/concepts/ledger.md +142 -0
- ayasee-0.1.0rc2/docs/concepts/plan-binding.md +202 -0
- ayasee-0.1.0rc2/docs/concepts/pr-checks.md +187 -0
- ayasee-0.1.0rc2/docs/concepts/risk-gate.md +191 -0
- ayasee-0.1.0rc2/docs/concepts/staged-run.md +298 -0
- ayasee-0.1.0rc2/docs/governance/PROVENANCE.md +51 -0
- ayasee-0.1.0rc2/docs/governance/decisions.md +26 -0
- ayasee-0.1.0rc2/docs/guides/migrate-from-env-branches.md +171 -0
- ayasee-0.1.0rc2/docs/guides/onboard-brownfield.md +141 -0
- ayasee-0.1.0rc2/docs/guides/quickstart.md +304 -0
- ayasee-0.1.0rc2/docs/guides/releasing.md +172 -0
- ayasee-0.1.0rc2/docs/reference/ayasee-yaml.md +88 -0
- ayasee-0.1.0rc2/docs/reference/policy-pack.md +80 -0
- ayasee-0.1.0rc2/docs/superpowers/plans/2026-11-06-ayasee-framework.md +599 -0
- ayasee-0.1.0rc2/e2e/README.md +206 -0
- ayasee-0.1.0rc2/e2e/__init__.py +0 -0
- ayasee-0.1.0rc2/e2e/ephemeral.py +650 -0
- ayasee-0.1.0rc2/e2e/fixture/.ayasee.yaml +11 -0
- ayasee-0.1.0rc2/e2e/fixture/.github/workflows/breakglass.yml +36 -0
- ayasee-0.1.0rc2/e2e/fixture/.github/workflows/main.yml +22 -0
- ayasee-0.1.0rc2/e2e/fixture/.github/workflows/nightly.yml +25 -0
- ayasee-0.1.0rc2/e2e/fixture/.github/workflows/pr.yml +18 -0
- ayasee-0.1.0rc2/e2e/fixture/e2e-generation.txt +1 -0
- ayasee-0.1.0rc2/e2e/fixture/e2e-grants-tag.txt +1 -0
- ayasee-0.1.0rc2/e2e/fixture/e2e-marker.txt +1 -0
- ayasee-0.1.0rc2/e2e/fixture/root.hcl +34 -0
- ayasee-0.1.0rc2/e2e/fixture/scripts/state-sync.sh +87 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/dev/base/main.tf +28 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/dev/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/dev/grants/main.tf +19 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/dev/grants/terragrunt.hcl +27 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/prod/base/main.tf +28 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/prod/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/prod/grants/main.tf +19 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/prod/grants/terragrunt.hcl +27 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/uat/base/main.tf +28 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/uat/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/uat/grants/main.tf +19 -0
- ayasee-0.1.0rc2/e2e/fixture/stages/uat/grants/terragrunt.hcl +27 -0
- ayasee-0.1.0rc2/e2e/ghes/README.md +91 -0
- ayasee-0.1.0rc2/e2e/run.py +119 -0
- ayasee-0.1.0rc2/e2e/sandbox.py +366 -0
- ayasee-0.1.0rc2/e2e/scenarios/__init__.py +16 -0
- ayasee-0.1.0rc2/e2e/scenarios/breakglass.py +58 -0
- ayasee-0.1.0rc2/e2e/scenarios/cascade.py +49 -0
- ayasee-0.1.0rc2/e2e/scenarios/common.py +99 -0
- ayasee-0.1.0rc2/e2e/scenarios/dev_apply_fail.py +37 -0
- ayasee-0.1.0rc2/e2e/scenarios/drift.py +26 -0
- ayasee-0.1.0rc2/e2e/scenarios/drift_cleared.py +40 -0
- ayasee-0.1.0rc2/e2e/scenarios/empty_prod.py +26 -0
- ayasee-0.1.0rc2/e2e/scenarios/gate_reject.py +24 -0
- ayasee-0.1.0rc2/e2e/scenarios/pr_plan_fail.py +22 -0
- ayasee-0.1.0rc2/e2e/scenarios/scan_fail.py +27 -0
- ayasee-0.1.0rc2/e2e/scenarios/stale_plan.py +55 -0
- ayasee-0.1.0rc2/e2e/scenarios/supersession.py +58 -0
- ayasee-0.1.0rc2/e2e/scenarios/valid.py +24 -0
- ayasee-0.1.0rc2/e2e/seed.sh +31 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.ayasee.yaml +23 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.github/workflows/breakglass.yml +35 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.github/workflows/cockpit.yml +34 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.github/workflows/main.yml +20 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.github/workflows/nightly.yml +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/.github/workflows/pr.yml +19 -0
- ayasee-0.1.0rc2/examples/databricks-azure/OWNERSHIP.md +66 -0
- ayasee-0.1.0rc2/examples/databricks-azure/README.md +182 -0
- ayasee-0.1.0rc2/examples/databricks-azure/bootstrap/.terraform.lock.hcl +73 -0
- ayasee-0.1.0rc2/examples/databricks-azure/bootstrap/main.tf +81 -0
- ayasee-0.1.0rc2/examples/databricks-azure/bootstrap/outputs.tf +14 -0
- ayasee-0.1.0rc2/examples/databricks-azure/bootstrap/variables.tf +57 -0
- ayasee-0.1.0rc2/examples/databricks-azure/renovate.json +33 -0
- ayasee-0.1.0rc2/examples/databricks-azure/root.hcl +35 -0
- ayasee-0.1.0rc2/examples/databricks-azure/shared/grants/main.tf +42 -0
- ayasee-0.1.0rc2/examples/databricks-azure/shared/unity-catalog/main.tf +119 -0
- ayasee-0.1.0rc2/examples/databricks-azure/shared/workspace/main.tf +113 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/grants/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/grants/terragrunt.hcl +28 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/unity-catalog/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/unity-catalog/terragrunt.hcl +33 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/workspace/.terraform.lock.hcl +39 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/dev/workspace/terragrunt.hcl +24 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/grants/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/grants/terragrunt.hcl +28 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/unity-catalog/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/unity-catalog/terragrunt.hcl +33 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/workspace/.terraform.lock.hcl +39 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/prod/workspace/terragrunt.hcl +24 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/grants/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/grants/terragrunt.hcl +28 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/unity-catalog/.terraform.lock.hcl +21 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/unity-catalog/terragrunt.hcl +33 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/workspace/.terraform.lock.hcl +39 -0
- ayasee-0.1.0rc2/examples/databricks-azure/stages/uat/workspace/terragrunt.hcl +24 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/.terraform.lock.hcl +39 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/README.md +49 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/main.tf +30 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/outputs.tf +14 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/tests/subjects.tftest.hcl +123 -0
- ayasee-0.1.0rc2/modules/azure-stage-identity/variables.tf +42 -0
- ayasee-0.1.0rc2/modules/github-environments/.terraform.lock.hcl +36 -0
- ayasee-0.1.0rc2/modules/github-environments/README.md +34 -0
- ayasee-0.1.0rc2/modules/github-environments/main.tf +86 -0
- ayasee-0.1.0rc2/modules/github-environments/outputs.tf +4 -0
- ayasee-0.1.0rc2/modules/github-environments/tests/defaults.tftest.hcl +203 -0
- ayasee-0.1.0rc2/modules/github-environments/variables.tf +61 -0
- ayasee-0.1.0rc2/policy/cloudflare/edge.rego +148 -0
- ayasee-0.1.0rc2/policy/cloudflare/edge_test.rego +133 -0
- ayasee-0.1.0rc2/policy/databricks/grants.rego +47 -0
- ayasee-0.1.0rc2/policy/databricks/grants_test.rego +103 -0
- ayasee-0.1.0rc2/policy/databricks/storage.rego +39 -0
- ayasee-0.1.0rc2/policy/databricks/storage_test.rego +85 -0
- ayasee-0.1.0rc2/policy/databricks/workspace.rego +30 -0
- ayasee-0.1.0rc2/policy/databricks/workspace_test.rego +34 -0
- ayasee-0.1.0rc2/pyproject.toml +58 -0
- ayasee-0.1.0rc2/renovate.json +5 -0
- ayasee-0.1.0rc2/rules/cloudflare.yaml +94 -0
- ayasee-0.1.0rc2/rules/databricks-azure.yaml +85 -0
- ayasee-0.1.0rc2/schema/fixtures/env-order.json +13 -0
- ayasee-0.1.0rc2/schema/fixtures/status-precedence.json +36 -0
- ayasee-0.1.0rc2/schema/snapshot.v1.json +85 -0
- ayasee-0.1.0rc2/scripts/build-docs-site.py +132 -0
- ayasee-0.1.0rc2/scripts/check-links.py +237 -0
- ayasee-0.1.0rc2/scripts/check-policy-fixture.sh +31 -0
- ayasee-0.1.0rc2/scripts/check-provenance.sh +42 -0
- ayasee-0.1.0rc2/scripts/install-dev-tools.sh +81 -0
- ayasee-0.1.0rc2/scripts/pin-release.sh +40 -0
- ayasee-0.1.0rc2/scripts/set-ayasee-ref.sh +45 -0
- ayasee-0.1.0rc2/scripts/snapshot-changed.sh +20 -0
- ayasee-0.1.0rc2/src/ayasee/__init__.py +3 -0
- ayasee-0.1.0rc2/src/ayasee/approvals.py +117 -0
- ayasee-0.1.0rc2/src/ayasee/binding.py +335 -0
- ayasee-0.1.0rc2/src/ayasee/cascade.py +81 -0
- ayasee-0.1.0rc2/src/ayasee/changed.py +250 -0
- ayasee-0.1.0rc2/src/ayasee/changeset.py +215 -0
- ayasee-0.1.0rc2/src/ayasee/cli.py +76 -0
- ayasee-0.1.0rc2/src/ayasee/cockpit/__init__.py +0 -0
- ayasee-0.1.0rc2/src/ayasee/cockpit/collect.py +326 -0
- ayasee-0.1.0rc2/src/ayasee/cockpit/render_md.py +282 -0
- ayasee-0.1.0rc2/src/ayasee/config.py +403 -0
- ayasee-0.1.0rc2/src/ayasee/drift.py +253 -0
- ayasee-0.1.0rc2/src/ayasee/features.py +131 -0
- ayasee-0.1.0rc2/src/ayasee/findings.py +52 -0
- ayasee-0.1.0rc2/src/ayasee/github.py +590 -0
- ayasee-0.1.0rc2/src/ayasee/guard.py +159 -0
- ayasee-0.1.0rc2/src/ayasee/issues.py +179 -0
- ayasee-0.1.0rc2/src/ayasee/labels.py +6 -0
- ayasee-0.1.0rc2/src/ayasee/ledger.py +747 -0
- ayasee-0.1.0rc2/src/ayasee/maintip.py +43 -0
- ayasee-0.1.0rc2/src/ayasee/notify.py +174 -0
- ayasee-0.1.0rc2/src/ayasee/planjson.py +159 -0
- ayasee-0.1.0rc2/src/ayasee/prcomment.py +84 -0
- ayasee-0.1.0rc2/src/ayasee/risk.py +315 -0
- ayasee-0.1.0rc2/src/ayasee/sarif.py +222 -0
- ayasee-0.1.0rc2/tests/actions/test_action_metadata.py +66 -0
- ayasee-0.1.0rc2/tests/actions/test_lib_check_mode.py +28 -0
- ayasee-0.1.0rc2/tests/actions/test_scripts_integration.py +837 -0
- ayasee-0.1.0rc2/tests/actions/test_setup_install.py +95 -0
- ayasee-0.1.0rc2/tests/actions/test_tool_mirror.py +167 -0
- ayasee-0.1.0rc2/tests/cockpit/test_collect.py +606 -0
- ayasee-0.1.0rc2/tests/cockpit/test_render_md.py +432 -0
- ayasee-0.1.0rc2/tests/e2e/fake_sandbox.py +425 -0
- ayasee-0.1.0rc2/tests/e2e/test_assets.py +92 -0
- ayasee-0.1.0rc2/tests/e2e/test_ephemeral.py +386 -0
- ayasee-0.1.0rc2/tests/e2e/test_run.py +146 -0
- ayasee-0.1.0rc2/tests/e2e/test_sandbox.py +436 -0
- ayasee-0.1.0rc2/tests/e2e/test_scenarios.py +138 -0
- ayasee-0.1.0rc2/tests/e2e/test_state_sync.py +178 -0
- ayasee-0.1.0rc2/tests/examples/test_example_wiring.py +463 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/bad_format_version.json +24 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/create.json +24 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/delete.json +24 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/forget.json +24 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/forget_metastore.json +24 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/grants_sensitive.json +50 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/grants_update.json +73 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/import.json +29 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/moved.json +27 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/noop.json +26 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/permissions_level.json +46 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/read.json +43 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/replace_create_delete.json +27 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/replace_delete_create.json +27 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/role_assignment_create.json +26 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/sensitive.json +30 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/unknown.json +26 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/update.json +28 -0
- ayasee-0.1.0rc2/tests/fixtures/plans/workspace_replace.json +29 -0
- ayasee-0.1.0rc2/tests/fixtures/policy/example_prod_plan.json +151 -0
- ayasee-0.1.0rc2/tests/fixtures/policy/example_prod_plan_public.json +151 -0
- ayasee-0.1.0rc2/tests/fixtures/policy/prod.data.json +1 -0
- ayasee-0.1.0rc2/tests/fixtures/policy/proxy_off.json +1 -0
- ayasee-0.1.0rc2/tests/fixtures/policy/public_workspace.json +1 -0
- ayasee-0.1.0rc2/tests/fixtures/tg/stages/dev/app/main.tf +3 -0
- ayasee-0.1.0rc2/tests/fixtures/tg/stages/dev/app/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg/stages/dev/base/main.tf +7 -0
- ayasee-0.1.0rc2/tests/fixtures/tg/stages/dev/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_dep/stages/dev/base/main.tf +11 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_dep/stages/dev/base/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_dep/stages/dev/grants/main.tf +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_dep/stages/dev/grants/terragrunt.hcl +25 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/base/main.tf +3 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/drift/main.tf +4 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/drift/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/last/main.tf +3 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_drift/stages/dev/last/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/bad/main.tf +7 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/bad/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/base/main.tf +3 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/base/terragrunt.hcl +10 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/last/main.tf +3 -0
- ayasee-0.1.0rc2/tests/fixtures/tg_fail/stages/dev/last/terragrunt.hcl +14 -0
- ayasee-0.1.0rc2/tests/test_approvals_issues.py +378 -0
- ayasee-0.1.0rc2/tests/test_binding.py +406 -0
- ayasee-0.1.0rc2/tests/test_cascade.py +79 -0
- ayasee-0.1.0rc2/tests/test_changed.py +273 -0
- ayasee-0.1.0rc2/tests/test_changeset.py +320 -0
- ayasee-0.1.0rc2/tests/test_check_links.py +165 -0
- ayasee-0.1.0rc2/tests/test_check_provenance.py +94 -0
- ayasee-0.1.0rc2/tests/test_cli.py +26 -0
- ayasee-0.1.0rc2/tests/test_config.py +434 -0
- ayasee-0.1.0rc2/tests/test_drift.py +357 -0
- ayasee-0.1.0rc2/tests/test_features.py +167 -0
- ayasee-0.1.0rc2/tests/test_findings.py +110 -0
- ayasee-0.1.0rc2/tests/test_github.py +413 -0
- ayasee-0.1.0rc2/tests/test_guard.py +360 -0
- ayasee-0.1.0rc2/tests/test_ledger.py +766 -0
- ayasee-0.1.0rc2/tests/test_maintip.py +49 -0
- ayasee-0.1.0rc2/tests/test_notify.py +179 -0
- ayasee-0.1.0rc2/tests/test_planjson.py +215 -0
- ayasee-0.1.0rc2/tests/test_prcomment.py +163 -0
- ayasee-0.1.0rc2/tests/test_risk.py +177 -0
- ayasee-0.1.0rc2/tests/test_risk_cloudflare.py +180 -0
- ayasee-0.1.0rc2/tests/test_sarif.py +298 -0
- ayasee-0.1.0rc2/tests/workflows/conftest.py +17 -0
- ayasee-0.1.0rc2/tests/workflows/test_breakglass.py +376 -0
- ayasee-0.1.0rc2/tests/workflows/test_cockpit_collect.py +428 -0
- ayasee-0.1.0rc2/tests/workflows/test_iac_nightly.py +295 -0
- ayasee-0.1.0rc2/tests/workflows/test_iac_pr.py +486 -0
- ayasee-0.1.0rc2/tests/workflows/test_iac_staged.py +641 -0
- ayasee-0.1.0rc2/tests/workflows/test_identity_profile.py +158 -0
- ayasee-0.1.0rc2/tests/workflows/test_release.py +263 -0
- ayasee-0.1.0rc2/uv.lock +1205 -0
- ayasee-0.1.0rc2/website/index.md +220 -0
- ayasee-0.1.0rc2/website/javascripts/tables.js +43 -0
- ayasee-0.1.0rc2/website/javascripts/vendor/mermaid-11.17.2.LICENSE.txt +21 -0
- ayasee-0.1.0rc2/website/javascripts/vendor/mermaid-11.17.2.min.js +3636 -0
- ayasee-0.1.0rc2/website/mkdocs.yml +140 -0
- ayasee-0.1.0rc2/website/overrides/main.html +13 -0
- ayasee-0.1.0rc2/website/overrides/partials/source.html +14 -0
- ayasee-0.1.0rc2/website/stylesheets/extra.css +450 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
# Jobs are added by the tasks that introduce their inputs.
|
|
11
|
+
jobs:
|
|
12
|
+
ruff:
|
|
13
|
+
name: ruff
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
19
|
+
with:
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
22
|
+
with:
|
|
23
|
+
enable-cache: false
|
|
24
|
+
- run: uv run ruff check
|
|
25
|
+
|
|
26
|
+
pytest:
|
|
27
|
+
name: pytest
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
33
|
+
with:
|
|
34
|
+
persist-credentials: false
|
|
35
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: false
|
|
38
|
+
- run: uv run pytest -m "not integration"
|
|
39
|
+
|
|
40
|
+
integration:
|
|
41
|
+
name: integration
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
permissions:
|
|
44
|
+
contents: read
|
|
45
|
+
steps:
|
|
46
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
47
|
+
with:
|
|
48
|
+
persist-credentials: false
|
|
49
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
50
|
+
with:
|
|
51
|
+
enable-cache: false
|
|
52
|
+
- uses: opentofu/setup-opentofu@a1320f892987e89d278cc92dc5adc984fb93aca4 # v2.0.2
|
|
53
|
+
with:
|
|
54
|
+
tofu_version: 1.13.9
|
|
55
|
+
tofu_wrapper: false
|
|
56
|
+
- run: scripts/install-dev-tools.sh terragrunt
|
|
57
|
+
- run: uv run pytest -m integration
|
|
58
|
+
|
|
59
|
+
tofu-test:
|
|
60
|
+
name: tofu test
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
permissions:
|
|
63
|
+
contents: read
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
66
|
+
with:
|
|
67
|
+
persist-credentials: false
|
|
68
|
+
- uses: opentofu/setup-opentofu@a1320f892987e89d278cc92dc5adc984fb93aca4 # v2.0.2
|
|
69
|
+
with:
|
|
70
|
+
tofu_version: 1.12.6
|
|
71
|
+
tofu_wrapper: false
|
|
72
|
+
- run: tofu fmt -check -recursive modules/
|
|
73
|
+
- name: tofu test each module
|
|
74
|
+
run: |
|
|
75
|
+
for m in modules/*/; do
|
|
76
|
+
(cd "$m" && tofu init -backend=false && tofu validate && tofu test)
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
cockpit-site:
|
|
80
|
+
name: cockpit-site
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
permissions:
|
|
83
|
+
contents: read
|
|
84
|
+
defaults:
|
|
85
|
+
run:
|
|
86
|
+
working-directory: cockpit-site
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
89
|
+
with:
|
|
90
|
+
persist-credentials: false
|
|
91
|
+
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
|
92
|
+
with:
|
|
93
|
+
node-version: 22
|
|
94
|
+
package-manager-cache: false
|
|
95
|
+
- run: npm ci --ignore-scripts --no-audit --no-fund
|
|
96
|
+
- run: npm run typecheck
|
|
97
|
+
- run: npm test
|
|
98
|
+
- run: npm run build
|
|
99
|
+
|
|
100
|
+
actionlint:
|
|
101
|
+
name: actionlint
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
permissions:
|
|
104
|
+
contents: read
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
107
|
+
with:
|
|
108
|
+
persist-credentials: false
|
|
109
|
+
- run: scripts/install-dev-tools.sh actionlint
|
|
110
|
+
- run: .tools/bin/actionlint
|
|
111
|
+
|
|
112
|
+
opa:
|
|
113
|
+
name: opa test
|
|
114
|
+
runs-on: ubuntu-latest
|
|
115
|
+
permissions:
|
|
116
|
+
contents: read
|
|
117
|
+
steps:
|
|
118
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
119
|
+
with:
|
|
120
|
+
persist-credentials: false
|
|
121
|
+
- run: scripts/install-dev-tools.sh opa conftest
|
|
122
|
+
- run: .tools/bin/opa check --strict policy/
|
|
123
|
+
- run: .tools/bin/opa fmt --fail policy/
|
|
124
|
+
- run: .tools/bin/opa test policy/ -v
|
|
125
|
+
- run: scripts/check-policy-fixture.sh
|
|
126
|
+
|
|
127
|
+
links:
|
|
128
|
+
name: doc links
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
permissions:
|
|
131
|
+
contents: read
|
|
132
|
+
steps:
|
|
133
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
134
|
+
with:
|
|
135
|
+
persist-credentials: false
|
|
136
|
+
- run: python3 scripts/check-links.py
|
|
137
|
+
|
|
138
|
+
zizmor:
|
|
139
|
+
name: zizmor
|
|
140
|
+
runs-on: ubuntu-latest
|
|
141
|
+
permissions:
|
|
142
|
+
contents: read
|
|
143
|
+
steps:
|
|
144
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
145
|
+
with:
|
|
146
|
+
persist-credentials: false
|
|
147
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
148
|
+
with:
|
|
149
|
+
enable-cache: false
|
|
150
|
+
- run: uvx zizmor@1.32.0 --offline .github/ actions/
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Cockpit collector: runs `ayasee cockpit collect` across the estate, commits snapshot.json and a
|
|
2
|
+
# dated history copy to the data repository, then renders it (pages | issue | summary).
|
|
3
|
+
# Callers add their own `workflow_run` (iac-staged and iac-nightly completed) and `schedule`
|
|
4
|
+
# (*/30 * * * *) triggers: see docs/cockpit/setup.md for a wrapper. Do not set a concurrency group
|
|
5
|
+
# named ayasee-cockpit in the wrapper: it would collide with the group below. The group allows
|
|
6
|
+
# one run at a time; while one runs, a newer pending run replaces an older pending one (the older
|
|
7
|
+
# is cancelled), so at most one run waits. The group is per repository: use one wrapper
|
|
8
|
+
# repository per data repository, or two wrappers would push to the data repository concurrently.
|
|
9
|
+
#
|
|
10
|
+
# Lines marked AYASEE_REF, AYASEE_REPO and AYASEE_SHA are placeholders (all-zero SHA, owner
|
|
11
|
+
# OWNER): scripts/set-ayasee-ref.sh rewrites them at release. This file is not callable before
|
|
12
|
+
# that. The collect job checks out the ayasee source at the same pinned commit into
|
|
13
|
+
# ayasee-src/ for scripts/ (R33: a reusable workflow cannot rely on github.job_workflow_sha);
|
|
14
|
+
# the pages job builds cockpit-site/ through the pinned cockpit-site action. The `--local`
|
|
15
|
+
# (./actions) form is not supported for this workflow: no job checks out the repository root, so
|
|
16
|
+
# ./actions would not exist.
|
|
17
|
+
#
|
|
18
|
+
# Ledgers: the collector reads only github-branch:// ledger URLs, through the read token (it has
|
|
19
|
+
# no cloud login). `ayasee cockpit repos` refuses any other store URL before a token is minted.
|
|
20
|
+
name: cockpit-collect
|
|
21
|
+
|
|
22
|
+
on:
|
|
23
|
+
workflow_call:
|
|
24
|
+
inputs:
|
|
25
|
+
tool-mirror:
|
|
26
|
+
description: >-
|
|
27
|
+
Optional https base URL (no trailing slash) replacing https://github.com for tool
|
|
28
|
+
downloads (GitHub Enterprise Server or offline runners). SHA-256 checks still apply.
|
|
29
|
+
type: string
|
|
30
|
+
required: false
|
|
31
|
+
default: ""
|
|
32
|
+
renderer:
|
|
33
|
+
description: How to present the snapshot (pages, issue or summary).
|
|
34
|
+
type: string
|
|
35
|
+
required: false
|
|
36
|
+
default: pages
|
|
37
|
+
repos-file:
|
|
38
|
+
description: Path of the repos file inside the data repository.
|
|
39
|
+
type: string
|
|
40
|
+
required: false
|
|
41
|
+
default: repos.yaml
|
|
42
|
+
data-repository:
|
|
43
|
+
description: The cockpit data repository, as owner/name. Also the owner of the estate installation.
|
|
44
|
+
type: string
|
|
45
|
+
required: true
|
|
46
|
+
issue-number:
|
|
47
|
+
description: Issue of the data repository that the issue renderer updates.
|
|
48
|
+
type: string
|
|
49
|
+
required: false
|
|
50
|
+
default: ""
|
|
51
|
+
history-days:
|
|
52
|
+
description: Days of history the site shows (integer, 1 to 365). Pages renderer only.
|
|
53
|
+
type: string
|
|
54
|
+
required: false
|
|
55
|
+
default: "30"
|
|
56
|
+
secrets:
|
|
57
|
+
app-id:
|
|
58
|
+
description: ID of the GitHub App (see docs/cockpit/setup.md).
|
|
59
|
+
required: true
|
|
60
|
+
app-private-key:
|
|
61
|
+
description: Private key of the GitHub App.
|
|
62
|
+
required: true
|
|
63
|
+
|
|
64
|
+
permissions: {}
|
|
65
|
+
|
|
66
|
+
concurrency:
|
|
67
|
+
group: ayasee-cockpit
|
|
68
|
+
cancel-in-progress: false
|
|
69
|
+
|
|
70
|
+
jobs:
|
|
71
|
+
collect:
|
|
72
|
+
name: collect
|
|
73
|
+
runs-on: ubuntu-latest
|
|
74
|
+
permissions:
|
|
75
|
+
contents: read # the App tokens carry the real access
|
|
76
|
+
timeout-minutes: 30
|
|
77
|
+
env:
|
|
78
|
+
SNAPSHOT_CACHE: .ayasee/etag-cache.json
|
|
79
|
+
steps:
|
|
80
|
+
- id: inputs
|
|
81
|
+
name: Validate the inputs
|
|
82
|
+
env:
|
|
83
|
+
RENDERER: ${{ inputs.renderer }}
|
|
84
|
+
DATA_REPOSITORY: ${{ inputs.data-repository }}
|
|
85
|
+
REPOS_FILE: ${{ inputs.repos-file }}
|
|
86
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
87
|
+
HISTORY_DAYS: ${{ inputs.history-days }}
|
|
88
|
+
run: |
|
|
89
|
+
case "$RENDERER" in pages|issue|summary) ;; *)
|
|
90
|
+
echo "::error::renderer must be pages, issue or summary"
|
|
91
|
+
exit 1 ;;
|
|
92
|
+
esac
|
|
93
|
+
[[ "$DATA_REPOSITORY" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*/[A-Za-z0-9][A-Za-z0-9._-]*$ ]] || {
|
|
94
|
+
echo "::error::data-repository must be owner/name"
|
|
95
|
+
exit 1
|
|
96
|
+
}
|
|
97
|
+
case "$REPOS_FILE" in /*|*..*|"") echo "::error::repos-file must be a relative path inside the data repository"; exit 1 ;; esac
|
|
98
|
+
if ! { [[ "$HISTORY_DAYS" =~ ^[1-9][0-9]{0,2}$ ]] && [ "$HISTORY_DAYS" -le 365 ]; }; then
|
|
99
|
+
echo "::error::history-days must be an integer between 1 and 365"
|
|
100
|
+
exit 1
|
|
101
|
+
fi
|
|
102
|
+
if [ "$RENDERER" = issue ]; then
|
|
103
|
+
[[ "$ISSUE_NUMBER" =~ ^[1-9][0-9]*$ ]] || {
|
|
104
|
+
echo "::error::the issue renderer needs issue-number (a positive integer)"
|
|
105
|
+
exit 1
|
|
106
|
+
}
|
|
107
|
+
fi
|
|
108
|
+
{
|
|
109
|
+
echo "owner=${DATA_REPOSITORY%%/*}"
|
|
110
|
+
echo "name=${DATA_REPOSITORY#*/}"
|
|
111
|
+
} >>"$GITHUB_OUTPUT"
|
|
112
|
+
- id: write-token
|
|
113
|
+
name: Write token for the data repository only (contents)
|
|
114
|
+
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
|
115
|
+
with:
|
|
116
|
+
app-id: ${{ secrets.app-id }}
|
|
117
|
+
private-key: ${{ secrets.app-private-key }}
|
|
118
|
+
owner: ${{ steps.inputs.outputs.owner }}
|
|
119
|
+
repositories: ${{ steps.inputs.outputs.name }}
|
|
120
|
+
permission-contents: write
|
|
121
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
122
|
+
with:
|
|
123
|
+
repository: ${{ inputs.data-repository }}
|
|
124
|
+
token: ${{ steps.write-token.outputs.token }}
|
|
125
|
+
path: data
|
|
126
|
+
persist-credentials: false
|
|
127
|
+
- name: Check out the ayasee source (scripts/)
|
|
128
|
+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
129
|
+
with:
|
|
130
|
+
repository: OWNER/ayasee # AYASEE_REPO
|
|
131
|
+
ref: 0000000000000000000000000000000000000000 # AYASEE_SHA
|
|
132
|
+
path: ayasee-src
|
|
133
|
+
persist-credentials: false
|
|
134
|
+
- uses: OWNER/ayasee/actions/setup@0000000000000000000000000000000000000000 # AYASEE_REF
|
|
135
|
+
with:
|
|
136
|
+
tool-mirror: ${{ inputs.tool-mirror }}
|
|
137
|
+
- id: repos
|
|
138
|
+
name: List the repositories of the estate
|
|
139
|
+
env:
|
|
140
|
+
REPOS_FILE: ${{ inputs.repos-file }}
|
|
141
|
+
OWNER: ${{ steps.inputs.outputs.owner }}
|
|
142
|
+
run: |
|
|
143
|
+
# fails when a repository belongs to another owner or there are more than 500
|
|
144
|
+
list="$(ayasee cockpit repos --repos-file "data/$REPOS_FILE" --owner "$OWNER")"
|
|
145
|
+
echo "list=$list" >>"$GITHUB_OUTPUT"
|
|
146
|
+
- id: read-token
|
|
147
|
+
name: Read token for the listed repositories only
|
|
148
|
+
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
|
149
|
+
with:
|
|
150
|
+
app-id: ${{ secrets.app-id }}
|
|
151
|
+
private-key: ${{ secrets.app-private-key }}
|
|
152
|
+
owner: ${{ steps.inputs.outputs.owner }}
|
|
153
|
+
repositories: ${{ steps.repos.outputs.list }}
|
|
154
|
+
permission-metadata: read
|
|
155
|
+
permission-actions: read
|
|
156
|
+
permission-issues: read
|
|
157
|
+
permission-contents: read
|
|
158
|
+
permission-deployments: read
|
|
159
|
+
permission-security-events: read
|
|
160
|
+
- id: issue-token
|
|
161
|
+
name: Issue token (issues write on the data repository, nothing else)
|
|
162
|
+
if: ${{ inputs.renderer == 'issue' }}
|
|
163
|
+
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
|
164
|
+
with:
|
|
165
|
+
app-id: ${{ secrets.app-id }}
|
|
166
|
+
private-key: ${{ secrets.app-private-key }}
|
|
167
|
+
owner: ${{ steps.inputs.outputs.owner }}
|
|
168
|
+
repositories: ${{ steps.inputs.outputs.name }}
|
|
169
|
+
permission-issues: write
|
|
170
|
+
- id: etag
|
|
171
|
+
name: Restore the ETag cache
|
|
172
|
+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
173
|
+
with:
|
|
174
|
+
path: ${{ env.SNAPSHOT_CACHE }}
|
|
175
|
+
# Never an exact hit: the newest entry under restore-keys is restored. The prefix is
|
|
176
|
+
# scoped to the data repository; Actions caches are scoped by ref, so a cache saved from a
|
|
177
|
+
# PR ref is never visible to the default-branch collector.
|
|
178
|
+
key: ayasee-cockpit-etag-${{ inputs.data-repository }}-${{ github.run_id }}
|
|
179
|
+
restore-keys: ayasee-cockpit-etag-${{ inputs.data-repository }}-
|
|
180
|
+
- name: Collect the snapshot
|
|
181
|
+
env:
|
|
182
|
+
GITHUB_TOKEN: ${{ steps.read-token.outputs.token }}
|
|
183
|
+
REPOS_FILE: ${{ inputs.repos-file }}
|
|
184
|
+
run: |
|
|
185
|
+
# exit 1 means every repository failed: the job fails and nothing is committed
|
|
186
|
+
ayasee cockpit collect \
|
|
187
|
+
--repos-file "data/$REPOS_FILE" \
|
|
188
|
+
--etag-cache "$SNAPSHOT_CACHE" \
|
|
189
|
+
--out snapshot.json
|
|
190
|
+
- id: diff
|
|
191
|
+
name: Compare with the committed snapshot
|
|
192
|
+
run: |
|
|
193
|
+
# assigned first so a failing script fails the step (not swallowed by echo "$(...)")
|
|
194
|
+
result="$(ayasee-src/scripts/snapshot-changed.sh data/snapshot.json snapshot.json)"
|
|
195
|
+
echo "result=$result" >>"$GITHUB_OUTPUT"
|
|
196
|
+
- name: Write snapshot.json and the history copy
|
|
197
|
+
if: ${{ steps.diff.outputs.result == 'changed' }}
|
|
198
|
+
run: |
|
|
199
|
+
cp snapshot.json data/snapshot.json
|
|
200
|
+
hist="data/history/$(date -u +%Y/%m/%d)"
|
|
201
|
+
mkdir -p "$hist"
|
|
202
|
+
cp snapshot.json "$hist/$(date -u +%H%M).json"
|
|
203
|
+
- name: Commit and push
|
|
204
|
+
if: ${{ steps.diff.outputs.result == 'changed' }}
|
|
205
|
+
env:
|
|
206
|
+
WRITE_TOKEN: ${{ steps.write-token.outputs.token }}
|
|
207
|
+
GIT_CONFIG_COUNT: "1"
|
|
208
|
+
GIT_CONFIG_KEY_0: credential.${{ github.server_url }}.helper
|
|
209
|
+
GIT_CONFIG_VALUE_0: '!f() { echo username=x-access-token; echo "password=$WRITE_TOKEN"; }; f'
|
|
210
|
+
run: |
|
|
211
|
+
git -C data config user.name "ayasee-cockpit[bot]"
|
|
212
|
+
git -C data config user.email "ayasee-cockpit[bot]@users.noreply.github.com"
|
|
213
|
+
git -C data add snapshot.json history
|
|
214
|
+
git -C data commit -m "cockpit: snapshot $(date -u +%Y-%m-%dT%H:%MZ)"
|
|
215
|
+
git -C data push
|
|
216
|
+
- name: Save the ETag cache (only when its content changed)
|
|
217
|
+
# No status function in the condition: GitHub adds success(), so this never runs after a
|
|
218
|
+
# failed collect, diff or push. The key carries the content hash: an unchanged cache
|
|
219
|
+
# matches the restored key and is not saved again.
|
|
220
|
+
if: ${{ hashFiles(env.SNAPSHOT_CACHE) != '' && steps.etag.outputs.cache-matched-key != format('ayasee-cockpit-etag-{0}-{1}', inputs.data-repository, hashFiles(env.SNAPSHOT_CACHE)) }}
|
|
221
|
+
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
222
|
+
with:
|
|
223
|
+
path: ${{ env.SNAPSHOT_CACHE }}
|
|
224
|
+
key: ayasee-cockpit-etag-${{ inputs.data-repository }}-${{ hashFiles(env.SNAPSHOT_CACHE) }}
|
|
225
|
+
- name: Render to the job summary
|
|
226
|
+
if: ${{ inputs.renderer == 'summary' }}
|
|
227
|
+
run: ayasee cockpit render-md --snapshot snapshot.json --summary "$GITHUB_STEP_SUMMARY"
|
|
228
|
+
- name: Render to an issue of the data repository
|
|
229
|
+
if: ${{ inputs.renderer == 'issue' }}
|
|
230
|
+
env:
|
|
231
|
+
GITHUB_TOKEN: ${{ steps.issue-token.outputs.token }}
|
|
232
|
+
ISSUE_NUMBER: ${{ inputs.issue-number }}
|
|
233
|
+
DATA_REPOSITORY: ${{ inputs.data-repository }}
|
|
234
|
+
run: |
|
|
235
|
+
ayasee cockpit render-md --snapshot snapshot.json \
|
|
236
|
+
--issue-number "$ISSUE_NUMBER" --repo "$DATA_REPOSITORY"
|
|
237
|
+
- name: Build the history index (generated for Pages only, never committed)
|
|
238
|
+
if: ${{ inputs.renderer == 'pages' }}
|
|
239
|
+
env:
|
|
240
|
+
HISTORY_DAYS: ${{ inputs.history-days }}
|
|
241
|
+
run: |
|
|
242
|
+
mkdir -p data/history
|
|
243
|
+
ayasee cockpit history-index --dir data/history --days "$HISTORY_DAYS" \
|
|
244
|
+
--out data/history/index.json
|
|
245
|
+
- name: Stage the data for the site (the fresh snapshot, not the committed one)
|
|
246
|
+
if: ${{ inputs.renderer == 'pages' }}
|
|
247
|
+
# data/snapshot.json only changes when the estate does, so its generated_at would make the
|
|
248
|
+
# site's stale banner fire on a quiet estate; the site gets this run's snapshot.json.
|
|
249
|
+
run: |
|
|
250
|
+
mkdir site-data
|
|
251
|
+
cp snapshot.json site-data/snapshot.json
|
|
252
|
+
cp -R data/history site-data/history
|
|
253
|
+
- name: Upload the data for the site
|
|
254
|
+
if: ${{ inputs.renderer == 'pages' }}
|
|
255
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
256
|
+
with:
|
|
257
|
+
name: cockpit-data
|
|
258
|
+
path: site-data
|
|
259
|
+
if-no-files-found: error
|
|
260
|
+
retention-days: 1
|
|
261
|
+
|
|
262
|
+
pages:
|
|
263
|
+
name: pages
|
|
264
|
+
needs: collect
|
|
265
|
+
if: ${{ inputs.renderer == 'pages' }}
|
|
266
|
+
runs-on: ubuntu-latest
|
|
267
|
+
permissions:
|
|
268
|
+
pages: write # deploy-pages
|
|
269
|
+
id-token: write # deploy-pages proves the deployment origin
|
|
270
|
+
environment:
|
|
271
|
+
name: github-pages
|
|
272
|
+
url: ${{ steps.deploy.outputs.page_url }}
|
|
273
|
+
steps:
|
|
274
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
275
|
+
with:
|
|
276
|
+
name: cockpit-data
|
|
277
|
+
path: cockpit-data
|
|
278
|
+
# builds the site and puts snapshot.json and history/ (with index.json) at the site root,
|
|
279
|
+
# where the page fetches ./snapshot.json and ./history/index.json
|
|
280
|
+
- uses: OWNER/ayasee/actions/cockpit-site@0000000000000000000000000000000000000000 # AYASEE_REF
|
|
281
|
+
with:
|
|
282
|
+
snapshot: cockpit-data/snapshot.json
|
|
283
|
+
history-dir: cockpit-data/history
|
|
284
|
+
out: site
|
|
285
|
+
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
286
|
+
with:
|
|
287
|
+
path: site
|
|
288
|
+
- id: deploy
|
|
289
|
+
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
name: docs
|
|
2
|
+
|
|
3
|
+
# Documentation site on GitHub Pages. The site is assembled from the repository's Markdown by
|
|
4
|
+
# scripts/build-docs-site.py and built with mkdocs in strict mode (a broken link or anchor fails
|
|
5
|
+
# the build). Pull requests build only; a push to main also deploys.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
pull_request:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
|
|
13
|
+
permissions: {}
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: docs-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
name: build
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
27
|
+
with:
|
|
28
|
+
persist-credentials: false
|
|
29
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
30
|
+
with:
|
|
31
|
+
enable-cache: false
|
|
32
|
+
- run: uv run --locked --only-group docs python scripts/build-docs-site.py
|
|
33
|
+
- run: uv run --locked --only-group docs mkdocs build --strict -f website/mkdocs.yml
|
|
34
|
+
env:
|
|
35
|
+
NO_MKDOCS_2_WARNING: "1"
|
|
36
|
+
- if: github.event_name != 'pull_request'
|
|
37
|
+
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
38
|
+
with:
|
|
39
|
+
path: build/site
|
|
40
|
+
|
|
41
|
+
deploy:
|
|
42
|
+
name: deploy
|
|
43
|
+
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main'
|
|
44
|
+
needs: build
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
permissions:
|
|
47
|
+
pages: write
|
|
48
|
+
id-token: write
|
|
49
|
+
environment:
|
|
50
|
+
name: github-pages
|
|
51
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
52
|
+
steps:
|
|
53
|
+
- id: deployment
|
|
54
|
+
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# End-to-end scenarios against a sandbox repository (never this repository). See e2e/README.md.
|
|
2
|
+
# Manual or nightly, canonical repository only. Nothing here touches production.
|
|
3
|
+
#
|
|
4
|
+
# Environment `e2e` holds: secrets E2E_TOKEN (maintainer identity), E2E_APPROVER_APP_ID and
|
|
5
|
+
# E2E_APPROVER_APP_KEY (the second identity, a GitHub App installed on the sandbox repository),
|
|
6
|
+
# E2E_WEBHOOK_URL (webhook echo); variable E2E_REPO (owner/name, name ends in -sandbox).
|
|
7
|
+
# OWNER is a placeholder replaced at release.
|
|
8
|
+
name: e2e
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
scenario:
|
|
14
|
+
description: One scenario, or all of them.
|
|
15
|
+
type: choice
|
|
16
|
+
default: all
|
|
17
|
+
options:
|
|
18
|
+
- all
|
|
19
|
+
- valid
|
|
20
|
+
- scan_fail
|
|
21
|
+
- pr_plan_fail
|
|
22
|
+
- dev_apply_fail
|
|
23
|
+
- gate_reject
|
|
24
|
+
- drift
|
|
25
|
+
- drift_cleared
|
|
26
|
+
- supersession
|
|
27
|
+
- stale_plan
|
|
28
|
+
- empty_prod
|
|
29
|
+
- breakglass
|
|
30
|
+
schedule:
|
|
31
|
+
- cron: "43 3 * * *"
|
|
32
|
+
|
|
33
|
+
permissions: {}
|
|
34
|
+
|
|
35
|
+
concurrency:
|
|
36
|
+
group: e2e
|
|
37
|
+
cancel-in-progress: false
|
|
38
|
+
|
|
39
|
+
jobs:
|
|
40
|
+
e2e:
|
|
41
|
+
name: e2e
|
|
42
|
+
if: ${{ github.repository == 'OWNER/ayasee' }}
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment: e2e
|
|
45
|
+
timeout-minutes: 300
|
|
46
|
+
permissions:
|
|
47
|
+
contents: read
|
|
48
|
+
env:
|
|
49
|
+
UV_NO_CACHE: "1"
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
|
|
52
|
+
with:
|
|
53
|
+
persist-credentials: false
|
|
54
|
+
- uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
|
|
55
|
+
with:
|
|
56
|
+
enable-cache: false
|
|
57
|
+
- name: Install the pinned dependencies (before any token exists)
|
|
58
|
+
run: uv sync --frozen
|
|
59
|
+
- id: target
|
|
60
|
+
name: Split the sandbox repository name
|
|
61
|
+
env:
|
|
62
|
+
E2E_REPO: ${{ vars.E2E_REPO }}
|
|
63
|
+
run: |
|
|
64
|
+
case "$E2E_REPO" in
|
|
65
|
+
*/*-sandbox) ;;
|
|
66
|
+
*) echo "::error::vars.E2E_REPO must be owner/<name>-sandbox"; exit 1 ;;
|
|
67
|
+
esac
|
|
68
|
+
{
|
|
69
|
+
echo "owner=${E2E_REPO%%/*}"
|
|
70
|
+
echo "name=${E2E_REPO#*/}"
|
|
71
|
+
} >>"$GITHUB_OUTPUT"
|
|
72
|
+
- id: approver
|
|
73
|
+
name: Token of the second identity
|
|
74
|
+
uses: actions/create-github-app-token@64ab729a6294000f5aa4a4bc0b73d1f32bc45510 # v3.3.0
|
|
75
|
+
with:
|
|
76
|
+
app-id: ${{ secrets.E2E_APPROVER_APP_ID }}
|
|
77
|
+
private-key: ${{ secrets.E2E_APPROVER_APP_KEY }}
|
|
78
|
+
owner: ${{ steps.target.outputs.owner }}
|
|
79
|
+
repositories: ${{ steps.target.outputs.name }}
|
|
80
|
+
permission-actions: read # run and pending-deployment state
|
|
81
|
+
permission-deployments: write # approve or reject environment gates
|
|
82
|
+
- name: Run the scenarios
|
|
83
|
+
env:
|
|
84
|
+
E2E_REPO: ${{ vars.E2E_REPO }}
|
|
85
|
+
E2E_TOKEN: ${{ secrets.E2E_TOKEN }}
|
|
86
|
+
E2E_APPROVER_TOKEN: ${{ steps.approver.outputs.token }}
|
|
87
|
+
E2E_WEBHOOK_URL: ${{ secrets.E2E_WEBHOOK_URL }}
|
|
88
|
+
SCENARIO: ${{ inputs.scenario }}
|
|
89
|
+
run: |
|
|
90
|
+
if [ -z "$SCENARIO" ] || [ "$SCENARIO" = all ]; then
|
|
91
|
+
uv run python -m e2e.run --all
|
|
92
|
+
else
|
|
93
|
+
uv run python -m e2e.run --scenario "$SCENARIO"
|
|
94
|
+
fi
|