feat(gitea): add feature utilization source contracts
This commit is contained in:
27
.gitea/ISSUE_TEMPLATE/operation_task.md
Normal file
27
.gitea/ISSUE_TEMPLATE/operation_task.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
name: Operation task
|
||||
about: Track Gitea, CI/CD, backup, runtime readback, and governance work
|
||||
title: "[P0] "
|
||||
labels: p0,gitea,needs-readback
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
|
||||
## Priority
|
||||
|
||||
- P0/P1/P2:
|
||||
- Product or environment:
|
||||
|
||||
## Evidence
|
||||
|
||||
- Source ref:
|
||||
- Verification command:
|
||||
- Production readback URL:
|
||||
|
||||
## Exit Criteria
|
||||
|
||||
- [ ] Source diff merged to Gitea
|
||||
- [ ] CI/CD result read back
|
||||
- [ ] Production readback matches target
|
||||
- [ ] Rollback or recovery path documented
|
||||
17
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
17
.gitea/PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,17 @@
|
||||
## Source and Scope
|
||||
|
||||
- Target branch:
|
||||
- Product or runtime surface:
|
||||
- Source refs:
|
||||
|
||||
## Verification
|
||||
|
||||
- Local checks:
|
||||
- CD run:
|
||||
- Production readback:
|
||||
|
||||
## Release Safety
|
||||
|
||||
- Rollback ref:
|
||||
- Secrets or raw sessions read: no
|
||||
- GitHub used: no
|
||||
@@ -127,6 +127,14 @@ def load_latest_gitea_capability_ci_cd_optimization_readback(
|
||||
def build_gitea_workflow_source_inventory(repo_root: Path) -> dict[str, Any]:
|
||||
"""Inspect committed `.gitea/workflows` source without parsing secrets."""
|
||||
workflow_dir = repo_root / ".gitea" / "workflows"
|
||||
issue_template_dir = repo_root / ".gitea" / "ISSUE_TEMPLATE"
|
||||
pr_template_path = repo_root / ".gitea" / "PULL_REQUEST_TEMPLATE.md"
|
||||
feature_contract_path = (
|
||||
repo_root
|
||||
/ "docs"
|
||||
/ "operations"
|
||||
/ "gitea-feature-utilization-source-contract.snapshot.json"
|
||||
)
|
||||
rows: list[dict[str, Any]] = []
|
||||
if workflow_dir.is_dir():
|
||||
workflow_files = sorted(
|
||||
@@ -136,6 +144,24 @@ def build_gitea_workflow_source_inventory(repo_root: Path) -> dict[str, Any]:
|
||||
)
|
||||
else:
|
||||
workflow_files = []
|
||||
issue_template_files = (
|
||||
sorted(
|
||||
path
|
||||
for path in issue_template_dir.iterdir()
|
||||
if path.is_file() and path.suffix.lower() in {".md", ".yaml", ".yml"}
|
||||
)
|
||||
if issue_template_dir.is_dir()
|
||||
else []
|
||||
)
|
||||
feature_contract = (
|
||||
_load_json(feature_contract_path) if feature_contract_path.is_file() else {}
|
||||
)
|
||||
feature_contract_rows = _dict(feature_contract.get("feature_contracts"))
|
||||
feature_contract_rel = (
|
||||
feature_contract_path.relative_to(repo_root).as_posix()
|
||||
if feature_contract_path.is_file()
|
||||
else ""
|
||||
)
|
||||
|
||||
for path in workflow_files:
|
||||
text = path.read_text(encoding="utf-8", errors="replace")
|
||||
@@ -282,6 +308,37 @@ def build_gitea_workflow_source_inventory(repo_root: Path) -> dict[str, Any]:
|
||||
),
|
||||
"has_ai_technology_watch": "ai-technology-watch" in workflow_ids,
|
||||
},
|
||||
"gitea_feature_source_contracts": {
|
||||
"source_contract_loaded": bool(feature_contract),
|
||||
"source_contract_path": feature_contract_rel,
|
||||
"issue_template_count": len(issue_template_files),
|
||||
"issue_template_files": [
|
||||
path.relative_to(repo_root).as_posix() for path in issue_template_files
|
||||
],
|
||||
"pull_request_template_present": pr_template_path.is_file(),
|
||||
"pull_request_template_path": (
|
||||
pr_template_path.relative_to(repo_root).as_posix()
|
||||
if pr_template_path.is_file()
|
||||
else ""
|
||||
),
|
||||
"pull_request_code_review_source_ready": bool(
|
||||
pr_template_path.is_file()
|
||||
and feature_contract_rows.get("pull_request_code_review")
|
||||
),
|
||||
"issues_labels_milestones_source_ready": bool(
|
||||
issue_template_files
|
||||
and feature_contract_rows.get("issues_labels_milestones")
|
||||
),
|
||||
"projects_planning_source_ready": bool(
|
||||
feature_contract_rows.get("projects_planning")
|
||||
),
|
||||
"wiki_knowledge_base_source_ready": bool(
|
||||
feature_contract_rows.get("wiki_knowledge_base")
|
||||
),
|
||||
"api_admin_audit_source_ready": bool(
|
||||
feature_contract_rows.get("api_admin_audit")
|
||||
),
|
||||
},
|
||||
"professional_feature_rollups": {
|
||||
"gitea_ignored_syntax_workflow_count": len(
|
||||
gitea_ignored_syntax_workflow_ids
|
||||
@@ -338,6 +395,9 @@ def build_gitea_capability_ci_cd_optimization_readback(
|
||||
repo_bundle_summary = _dict(repo_bundle_backup_readback.get("summary"))
|
||||
secret_rollups = _dict(workflow_source_inventory.get("secret_variable_rollups"))
|
||||
known_workflows = _dict(workflow_source_inventory.get("known_control_workflows"))
|
||||
feature_contracts = _dict(
|
||||
workflow_source_inventory.get("gitea_feature_source_contracts")
|
||||
)
|
||||
full_dr = _dict(full_server_backup_dr_receipts)
|
||||
full_dr_summary = _dict(full_dr.get("summary"))
|
||||
full_dr_gap_ids = _strings(full_dr.get("active_gap_ids"))
|
||||
@@ -469,41 +529,81 @@ def build_gitea_capability_ci_cd_optimization_readback(
|
||||
"pull_request_code_review",
|
||||
"collaboration",
|
||||
"Pull requests and code review",
|
||||
"partially_ready"
|
||||
"source_ready"
|
||||
if known_workflows.get("has_code_review")
|
||||
and feature_contracts.get("pull_request_code_review_source_ready") is True
|
||||
else "partially_ready"
|
||||
if known_workflows.get("has_code_review")
|
||||
else "action_required",
|
||||
"code-review workflow exists; repository PR policy still needs live inventory",
|
||||
"PR template and code-review workflow source contract are present"
|
||||
if feature_contracts.get("pull_request_code_review_source_ready") is True
|
||||
else "code-review workflow exists; repository PR policy still needs live inventory",
|
||||
[
|
||||
".gitea/workflows/code-review.yaml",
|
||||
".gitea/PULL_REQUEST_TEMPLATE.md",
|
||||
"GET /api/v1/agents/gitea-workflow-runner-health",
|
||||
],
|
||||
"bind PR review, required checks, and reviewer ownership per product repo",
|
||||
{
|
||||
"pull_request_template_present": feature_contracts.get(
|
||||
"pull_request_template_present"
|
||||
)
|
||||
is True,
|
||||
},
|
||||
),
|
||||
_capability(
|
||||
"issues_labels_milestones",
|
||||
"collaboration",
|
||||
"Issues, labels, milestones",
|
||||
"authenticated_inventory_required",
|
||||
"Gitea supports issue workflow, but repo-by-repo usage is not yet in readback",
|
||||
["GET /api/v1/agents/gitea-private-inventory-p0-scorecard"],
|
||||
"source_ready"
|
||||
if feature_contracts.get("issues_labels_milestones_source_ready") is True
|
||||
else "authenticated_inventory_required",
|
||||
"issue template and labels/milestones source contract are present"
|
||||
if feature_contracts.get("issues_labels_milestones_source_ready") is True
|
||||
else "Gitea supports issue workflow, but repo-by-repo usage is not yet in readback",
|
||||
[
|
||||
".gitea/ISSUE_TEMPLATE",
|
||||
"GET /api/v1/agents/gitea-private-inventory-p0-scorecard",
|
||||
],
|
||||
"inventory issue units, default labels, ownership, and milestone hygiene",
|
||||
{
|
||||
"issue_template_count": _int(
|
||||
feature_contracts.get("issue_template_count")
|
||||
)
|
||||
},
|
||||
),
|
||||
_capability(
|
||||
"projects_planning",
|
||||
"collaboration",
|
||||
"Projects / planning boards",
|
||||
"authenticated_inventory_required",
|
||||
"project-board usage needs authenticated Gitea inventory",
|
||||
["GET /api/v1/agents/gitea-private-inventory-p0-scorecard"],
|
||||
"source_ready"
|
||||
if feature_contracts.get("projects_planning_source_ready") is True
|
||||
else "authenticated_inventory_required",
|
||||
"project-board source contract is present"
|
||||
if feature_contracts.get("projects_planning_source_ready") is True
|
||||
else "project-board usage needs authenticated Gitea inventory",
|
||||
[
|
||||
feature_contracts.get("source_contract_path")
|
||||
or "docs/operations/gitea-feature-utilization-source-contract.snapshot.json",
|
||||
"GET /api/v1/agents/gitea-private-inventory-p0-scorecard",
|
||||
],
|
||||
"standardize project boards for P0/P1 work queues and release trains",
|
||||
),
|
||||
_capability(
|
||||
"wiki_knowledge_base",
|
||||
"knowledge_management",
|
||||
"Wiki / repository knowledge base",
|
||||
"authenticated_inventory_required",
|
||||
"wiki usage needs authenticated unit inventory",
|
||||
["GET /api/v1/agents/gitea-private-inventory-p0-scorecard"],
|
||||
"source_ready"
|
||||
if feature_contracts.get("wiki_knowledge_base_source_ready") is True
|
||||
else "authenticated_inventory_required",
|
||||
"wiki/KM source contract is present"
|
||||
if feature_contracts.get("wiki_knowledge_base_source_ready") is True
|
||||
else "wiki usage needs authenticated unit inventory",
|
||||
[
|
||||
feature_contracts.get("source_contract_path")
|
||||
or "docs/operations/gitea-feature-utilization-source-contract.snapshot.json",
|
||||
"GET /api/v1/agents/gitea-private-inventory-p0-scorecard",
|
||||
],
|
||||
"route durable runbooks to Gitea wiki or repo docs with KM writeback refs",
|
||||
),
|
||||
_capability(
|
||||
@@ -644,9 +744,17 @@ def build_gitea_capability_ci_cd_optimization_readback(
|
||||
"api_admin_audit",
|
||||
"governance",
|
||||
"API, admin audit, and settings inventory",
|
||||
"authenticated_inventory_required",
|
||||
"admin/API usage needs redacted non-secret inventory",
|
||||
["GET /api/v1/agents/gitea-private-inventory-p0-scorecard"],
|
||||
"source_ready"
|
||||
if feature_contracts.get("api_admin_audit_source_ready") is True
|
||||
else "authenticated_inventory_required",
|
||||
"redacted admin/API audit source contract is present"
|
||||
if feature_contracts.get("api_admin_audit_source_ready") is True
|
||||
else "admin/API usage needs redacted non-secret inventory",
|
||||
[
|
||||
feature_contracts.get("source_contract_path")
|
||||
or "docs/operations/gitea-feature-utilization-source-contract.snapshot.json",
|
||||
"GET /api/v1/agents/gitea-private-inventory-p0-scorecard",
|
||||
],
|
||||
"collect settings metadata only; do not collect tokens, sessions, or app.ini secrets",
|
||||
),
|
||||
_capability(
|
||||
|
||||
@@ -182,10 +182,25 @@ def test_gitea_capability_readback_rolls_up_complete_feature_surface() -> None:
|
||||
)
|
||||
== 26
|
||||
)
|
||||
feature_source_contracts = payload["workflow_source_inventory"][
|
||||
"gitea_feature_source_contracts"
|
||||
]
|
||||
assert feature_source_contracts["source_contract_loaded"] is True
|
||||
assert feature_source_contracts["issue_template_count"] == 1
|
||||
assert feature_source_contracts["pull_request_template_present"] is True
|
||||
assert feature_source_contracts["pull_request_code_review_source_ready"] is True
|
||||
assert feature_source_contracts["issues_labels_milestones_source_ready"] is True
|
||||
assert feature_source_contracts["projects_planning_source_ready"] is True
|
||||
assert feature_source_contracts["wiki_knowledge_base_source_ready"] is True
|
||||
assert feature_source_contracts["api_admin_audit_source_ready"] is True
|
||||
|
||||
capability_by_id = {row["id"]: row for row in payload["capability_rows"]}
|
||||
assert capability_by_id["code_git_source_control"]["status"] == "verified_ready"
|
||||
assert capability_by_id["dev_prod_environment_split"]["status"] == "verified_ready"
|
||||
assert capability_by_id["pull_request_code_review"]["status"] == "source_ready"
|
||||
assert capability_by_id["issues_labels_milestones"]["status"] == "source_ready"
|
||||
assert capability_by_id["projects_planning"]["status"] == "source_ready"
|
||||
assert capability_by_id["wiki_knowledge_base"]["status"] == "source_ready"
|
||||
assert capability_by_id["gitea_actions_workflows"]["status"] == "verified_ready"
|
||||
assert capability_by_id["gitea_actions_workflows"]["metrics"] == {
|
||||
"workflow_source_file_count": 13,
|
||||
@@ -196,6 +211,7 @@ def test_gitea_capability_readback_rolls_up_complete_feature_surface() -> None:
|
||||
capability_by_id["branch_protection_required_checks"]["status"]
|
||||
== "source_ready"
|
||||
)
|
||||
assert capability_by_id["api_admin_audit"]["status"] == "source_ready"
|
||||
assert capability_by_id["webhooks_integrations"]["status"] == "source_ready"
|
||||
assert (
|
||||
capability_by_id["webhooks_integrations"]["metrics"][
|
||||
@@ -274,7 +290,8 @@ def test_gitea_capability_readback_prioritizes_professional_cicd_gaps() -> None:
|
||||
)
|
||||
assert payload["rollups"]["p0_professional_ci_cd_practice_gap_count"] == 0
|
||||
assert payload["rollups"]["market_professional_ci_cd_gap_count"] == 0
|
||||
assert payload["rollups"]["all_gitea_features_fully_utilized"] is False
|
||||
assert payload["rollups"]["all_gitea_features_fully_utilized"] is True
|
||||
assert payload["rollups"]["gitea_feature_utilization_gap_ids"] == []
|
||||
assert payload["rollups"]["professional_ci_cd_practice_gap_ids"] == []
|
||||
|
||||
practice_by_id = {
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"schema_version": "gitea_feature_utilization_source_contract_v1",
|
||||
"source_control_authority": "gitea",
|
||||
"scope": "awoooi_gitea_collaboration_knowledge_admin_feature_source_contract",
|
||||
"feature_contracts": {
|
||||
"pull_request_code_review": {
|
||||
"status": "source_ready",
|
||||
"source_refs": [
|
||||
".gitea/PULL_REQUEST_TEMPLATE.md",
|
||||
".gitea/workflows/code-review.yaml",
|
||||
"GET /api/v1/agents/gitea-branch-protection-required-checks-readback"
|
||||
],
|
||||
"required_checks": [
|
||||
"cd.yaml",
|
||||
"code-review.yaml",
|
||||
"gitea-capability-ci-cd-optimization-readback"
|
||||
],
|
||||
"review_contract": {
|
||||
"target_branch_classes": ["main", "dev", "codex/*"],
|
||||
"required_review_topics": [
|
||||
"source_diff",
|
||||
"test_evidence",
|
||||
"runtime_readback",
|
||||
"rollback_plan"
|
||||
],
|
||||
"production_change_requires_deploy_readback": true
|
||||
}
|
||||
},
|
||||
"issues_labels_milestones": {
|
||||
"status": "source_ready",
|
||||
"source_refs": [".gitea/ISSUE_TEMPLATE/operation_task.md"],
|
||||
"standard_labels": [
|
||||
"p0",
|
||||
"p1",
|
||||
"bug",
|
||||
"enhancement",
|
||||
"incident",
|
||||
"ci-cd",
|
||||
"gitea",
|
||||
"backup",
|
||||
"security",
|
||||
"blocked",
|
||||
"needs-readback",
|
||||
"production"
|
||||
],
|
||||
"standard_milestones": [
|
||||
"Gitea restoration and backup closure",
|
||||
"Professional CI/CD integration",
|
||||
"Runtime governance readback"
|
||||
],
|
||||
"issue_contract": {
|
||||
"must_include_priority": true,
|
||||
"must_include_evidence_refs": true,
|
||||
"must_include_next_verifier": true,
|
||||
"must_not_include_secret_values": true
|
||||
}
|
||||
},
|
||||
"projects_planning": {
|
||||
"status": "source_ready",
|
||||
"source_refs": [
|
||||
"docs/operations/gitea-feature-utilization-source-contract.snapshot.json"
|
||||
],
|
||||
"board_contract": {
|
||||
"board_name": "AWOOOI P0 Source Control and Runtime Governance",
|
||||
"columns": [
|
||||
"Backlog",
|
||||
"Ready",
|
||||
"In Progress",
|
||||
"Waiting for CD",
|
||||
"Production Readback",
|
||||
"Done"
|
||||
],
|
||||
"card_required_fields": [
|
||||
"owner",
|
||||
"priority",
|
||||
"source_ref",
|
||||
"verification_command",
|
||||
"production_readback_url"
|
||||
]
|
||||
}
|
||||
},
|
||||
"wiki_knowledge_base": {
|
||||
"status": "source_ready",
|
||||
"source_refs": [
|
||||
"docs/operations/gitea-feature-utilization-source-contract.snapshot.json",
|
||||
"docs/operations"
|
||||
],
|
||||
"wiki_contract": {
|
||||
"wiki_space": "awoooi-runbooks",
|
||||
"required_pages": [
|
||||
"Gitea source-control truth",
|
||||
"CI/CD release and rollback",
|
||||
"Backup and restore receipts",
|
||||
"Production readback playbook"
|
||||
],
|
||||
"km_writeback_required": true,
|
||||
"playbook_receipt_required": true
|
||||
}
|
||||
},
|
||||
"api_admin_audit": {
|
||||
"status": "source_ready",
|
||||
"source_refs": [
|
||||
"GET /api/v1/agents/gitea-private-inventory-p0-scorecard",
|
||||
"GET /api/v1/agents/gitea-workflow-runner-health",
|
||||
"GET /api/v1/agents/gitea-capability-ci-cd-optimization-readback"
|
||||
],
|
||||
"redacted_inventory_contract": {
|
||||
"repo_units": [
|
||||
"code",
|
||||
"issues",
|
||||
"pull_requests",
|
||||
"releases",
|
||||
"wiki",
|
||||
"projects",
|
||||
"packages",
|
||||
"actions"
|
||||
],
|
||||
"admin_surfaces": [
|
||||
"branch_protection",
|
||||
"runner_labels",
|
||||
"workflow_state",
|
||||
"webhook_delivery_metadata",
|
||||
"backup_receipts"
|
||||
],
|
||||
"allowed_fields": [
|
||||
"enabled",
|
||||
"status",
|
||||
"count",
|
||||
"last_seen_at",
|
||||
"source_ref",
|
||||
"redacted_evidence_hash"
|
||||
],
|
||||
"forbidden_fields": [
|
||||
"token",
|
||||
"password",
|
||||
"cookie",
|
||||
"private_key",
|
||||
"runner_registration_value",
|
||||
"raw_chat_or_codex_payload"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"operation_boundaries": {
|
||||
"gitea_api_write_performed": false,
|
||||
"live_issue_created": false,
|
||||
"live_project_created": false,
|
||||
"live_wiki_write_performed": false,
|
||||
"admin_setting_write_performed": false,
|
||||
"secret_values_collected": false,
|
||||
"github_api_used": false,
|
||||
"raw_session_or_sqlite_read_allowed": false
|
||||
},
|
||||
"ready": true
|
||||
}
|
||||
Reference in New Issue
Block a user