From 84e347c040861aa54c5ee4bb7a85aabc8da3f385 Mon Sep 17 00:00:00 2001 From: fullsend-code <278716306+fullsend-ai-coder[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:49:43 +0000 Subject: [PATCH] feat(#1512): remove abandoned generated documentation files Add cleanup logic to the documentation generation process that removes stale generated .adoc files when their corresponding CLI commands, Rego builtins, or Tekton tasks are removed. Each documentation template now includes a generated-file marker comment at the top of each output file. The GenerateAsciidoc function collects all file paths written by the CLI, Rego, and Tekton generators, then scans the pages directory for .adoc files with the marker that were not produced in the current run. These stale files are removed automatically. Handwritten documentation files (which lack the marker) are never touched. The generator functions (GenerateCommandLineDocumentation, GenerateRegoReference, GenerateTektonDocumentation) now return the list of page file paths they wrote, enabling the cleanup logic in the parent GenerateAsciidoc function. Closes #1512 --- .../ROOT/pages/collect-keyless-params.adoc | 1 + docs/modules/ROOT/pages/ec.adoc | 1 + docs/modules/ROOT/pages/ec_compare.adoc | 1 + docs/modules/ROOT/pages/ec_fetch.adoc | 1 + docs/modules/ROOT/pages/ec_fetch_policy.adoc | 1 + docs/modules/ROOT/pages/ec_init.adoc | 1 + docs/modules/ROOT/pages/ec_init_policies.adoc | 1 + docs/modules/ROOT/pages/ec_inspect.adoc | 1 + .../ROOT/pages/ec_inspect_policy-data.adoc | 1 + .../modules/ROOT/pages/ec_inspect_policy.adoc | 1 + docs/modules/ROOT/pages/ec_oci_blob.adoc | 1 + .../modules/ROOT/pages/ec_oci_blob_files.adoc | 1 + .../modules/ROOT/pages/ec_oci_descriptor.adoc | 1 + .../ROOT/pages/ec_oci_image_files.adoc | 1 + .../ROOT/pages/ec_oci_image_index.adoc | 1 + .../ROOT/pages/ec_oci_image_manifest.adoc | 1 + .../ROOT/pages/ec_oci_image_manifests.adoc | 1 + .../ROOT/pages/ec_oci_image_referrers.adoc | 1 + .../ROOT/pages/ec_oci_image_tag_refs.adoc | 1 + .../ROOT/pages/ec_oci_parsed_blob.adoc | 1 + docs/modules/ROOT/pages/ec_opa.adoc | 1 + docs/modules/ROOT/pages/ec_opa_bench.adoc | 1 + docs/modules/ROOT/pages/ec_opa_build.adoc | 1 + .../ROOT/pages/ec_opa_capabilities.adoc | 1 + docs/modules/ROOT/pages/ec_opa_check.adoc | 1 + docs/modules/ROOT/pages/ec_opa_deps.adoc | 1 + docs/modules/ROOT/pages/ec_opa_eval.adoc | 1 + docs/modules/ROOT/pages/ec_opa_exec.adoc | 1 + docs/modules/ROOT/pages/ec_opa_fmt.adoc | 1 + docs/modules/ROOT/pages/ec_opa_inspect.adoc | 1 + docs/modules/ROOT/pages/ec_opa_parse.adoc | 1 + docs/modules/ROOT/pages/ec_opa_run.adoc | 1 + docs/modules/ROOT/pages/ec_opa_sign.adoc | 1 + docs/modules/ROOT/pages/ec_opa_test.adoc | 1 + docs/modules/ROOT/pages/ec_opa_version.adoc | 1 + docs/modules/ROOT/pages/ec_purl_is_valid.adoc | 1 + docs/modules/ROOT/pages/ec_purl_parse.adoc | 1 + docs/modules/ROOT/pages/ec_sigstore.adoc | 1 + .../ROOT/pages/ec_sigstore_initialize.adoc | 1 + .../pages/ec_sigstore_verify_attestation.adoc | 1 + .../ROOT/pages/ec_sigstore_verify_image.adoc | 1 + docs/modules/ROOT/pages/ec_test.adoc | 1 + docs/modules/ROOT/pages/ec_track.adoc | 1 + docs/modules/ROOT/pages/ec_track_bundle.adoc | 1 + docs/modules/ROOT/pages/ec_validate.adoc | 1 + .../modules/ROOT/pages/ec_validate_image.adoc | 1 + .../modules/ROOT/pages/ec_validate_input.adoc | 1 + .../ROOT/pages/ec_validate_policy.adoc | 1 + docs/modules/ROOT/pages/ec_validate_vsa.adoc | 1 + docs/modules/ROOT/pages/ec_version.adoc | 1 + docs/modules/ROOT/pages/rego_builtins.adoc | 1 + .../pages/verify-conforma-konflux-ta.adoc | 1 + .../pages/verify-enterprise-contract.adoc | 1 + internal/documentation/asciidoc/asciidoc.go | 88 ++++++++++- .../documentation/asciidoc/asciidoc_test.go | 149 ++++++++++++++++++ internal/documentation/asciidoc/cli/cli.go | 17 +- internal/documentation/asciidoc/cli/cli.tmpl | 1 + .../documentation/asciidoc/rego/builtins.tmpl | 1 + internal/documentation/asciidoc/rego/rego.go | 33 ++-- .../documentation/asciidoc/rego/rego.tmpl | 1 + .../documentation/asciidoc/tekton/task.tmpl | 1 + .../documentation/asciidoc/tekton/tekton.go | 21 +-- 62 files changed, 331 insertions(+), 34 deletions(-) create mode 100644 internal/documentation/asciidoc/asciidoc_test.go diff --git a/docs/modules/ROOT/pages/collect-keyless-params.adoc b/docs/modules/ROOT/pages/collect-keyless-params.adoc index c5f182322..4de5d28ab 100644 --- a/docs/modules/ROOT/pages/collect-keyless-params.adoc +++ b/docs/modules/ROOT/pages/collect-keyless-params.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = collect-keyless-params Version: 0.1 diff --git a/docs/modules/ROOT/pages/ec.adoc b/docs/modules/ROOT/pages/ec.adoc index 8ac0e863a..9679be253 100644 --- a/docs/modules/ROOT/pages/ec.adoc +++ b/docs/modules/ROOT/pages/ec.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec Conforma CLI diff --git a/docs/modules/ROOT/pages/ec_compare.adoc b/docs/modules/ROOT/pages/ec_compare.adoc index 22237ba99..ab77552d9 100644 --- a/docs/modules/ROOT/pages/ec_compare.adoc +++ b/docs/modules/ROOT/pages/ec_compare.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec compare Compare two Conforma Policy specs for equivalence diff --git a/docs/modules/ROOT/pages/ec_fetch.adoc b/docs/modules/ROOT/pages/ec_fetch.adoc index 2083f0a81..7d5c66d9e 100644 --- a/docs/modules/ROOT/pages/ec_fetch.adoc +++ b/docs/modules/ROOT/pages/ec_fetch.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec fetch Fetch remote resources diff --git a/docs/modules/ROOT/pages/ec_fetch_policy.adoc b/docs/modules/ROOT/pages/ec_fetch_policy.adoc index ae385a509..5ffc26c79 100644 --- a/docs/modules/ROOT/pages/ec_fetch_policy.adoc +++ b/docs/modules/ROOT/pages/ec_fetch_policy.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec fetch policy Fetch policy rules from a git repository or other source diff --git a/docs/modules/ROOT/pages/ec_init.adoc b/docs/modules/ROOT/pages/ec_init.adoc index e94c703a0..e02495637 100644 --- a/docs/modules/ROOT/pages/ec_init.adoc +++ b/docs/modules/ROOT/pages/ec_init.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec init Initialize a directory for use diff --git a/docs/modules/ROOT/pages/ec_init_policies.adoc b/docs/modules/ROOT/pages/ec_init_policies.adoc index 1ff8d89ac..4c966ceb6 100644 --- a/docs/modules/ROOT/pages/ec_init_policies.adoc +++ b/docs/modules/ROOT/pages/ec_init_policies.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec init policies Initialize a directory with minimal EC scaffolding diff --git a/docs/modules/ROOT/pages/ec_inspect.adoc b/docs/modules/ROOT/pages/ec_inspect.adoc index 297a627e4..511886ee0 100644 --- a/docs/modules/ROOT/pages/ec_inspect.adoc +++ b/docs/modules/ROOT/pages/ec_inspect.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec inspect Inspect policy rules diff --git a/docs/modules/ROOT/pages/ec_inspect_policy-data.adoc b/docs/modules/ROOT/pages/ec_inspect_policy-data.adoc index 7279cfdc5..4580121eb 100644 --- a/docs/modules/ROOT/pages/ec_inspect_policy-data.adoc +++ b/docs/modules/ROOT/pages/ec_inspect_policy-data.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec inspect policy-data Read policy data from source urls and displays the data diff --git a/docs/modules/ROOT/pages/ec_inspect_policy.adoc b/docs/modules/ROOT/pages/ec_inspect_policy.adoc index 9b280aa11..afb0cd950 100644 --- a/docs/modules/ROOT/pages/ec_inspect_policy.adoc +++ b/docs/modules/ROOT/pages/ec_inspect_policy.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec inspect policy Read policies from source urls and show information about the rules inside them diff --git a/docs/modules/ROOT/pages/ec_oci_blob.adoc b/docs/modules/ROOT/pages/ec_oci_blob.adoc index 22a14b5c9..0cd554a00 100644 --- a/docs/modules/ROOT/pages/ec_oci_blob.adoc +++ b/docs/modules/ROOT/pages/ec_oci_blob.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.blob Fetch a blob from an OCI registry. diff --git a/docs/modules/ROOT/pages/ec_oci_blob_files.adoc b/docs/modules/ROOT/pages/ec_oci_blob_files.adoc index 366a46491..6dc743831 100644 --- a/docs/modules/ROOT/pages/ec_oci_blob_files.adoc +++ b/docs/modules/ROOT/pages/ec_oci_blob_files.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.blob_files Fetch structured files (YAML or JSON) from within a blob tar archive. diff --git a/docs/modules/ROOT/pages/ec_oci_descriptor.adoc b/docs/modules/ROOT/pages/ec_oci_descriptor.adoc index 4fd2e5c2c..73bd9c538 100644 --- a/docs/modules/ROOT/pages/ec_oci_descriptor.adoc +++ b/docs/modules/ROOT/pages/ec_oci_descriptor.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.descriptor Fetch a raw Image from an OCI registry. diff --git a/docs/modules/ROOT/pages/ec_oci_image_files.adoc b/docs/modules/ROOT/pages/ec_oci_image_files.adoc index fec7ccf2c..3f6c751b2 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_files.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_files.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_files Fetch structured files (YAML or JSON) from within an image. diff --git a/docs/modules/ROOT/pages/ec_oci_image_index.adoc b/docs/modules/ROOT/pages/ec_oci_image_index.adoc index b7aa6baf3..a48e51a2f 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_index.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_index.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_index Fetch an Image Index from an OCI registry. diff --git a/docs/modules/ROOT/pages/ec_oci_image_manifest.adoc b/docs/modules/ROOT/pages/ec_oci_image_manifest.adoc index 83cad8c91..71e8362db 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_manifest.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_manifest.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_manifest Fetch an Image Manifest from an OCI registry. diff --git a/docs/modules/ROOT/pages/ec_oci_image_manifests.adoc b/docs/modules/ROOT/pages/ec_oci_image_manifests.adoc index aaee30eea..11dab9c0b 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_manifests.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_manifests.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_manifests Fetch Image Manifests from an OCI registry in parallel. diff --git a/docs/modules/ROOT/pages/ec_oci_image_referrers.adoc b/docs/modules/ROOT/pages/ec_oci_image_referrers.adoc index d5088f3db..805798dad 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_referrers.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_referrers.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_referrers Discover artifacts attached to an image via OCI Referrers API. diff --git a/docs/modules/ROOT/pages/ec_oci_image_tag_refs.adoc b/docs/modules/ROOT/pages/ec_oci_image_tag_refs.adoc index 2bd6dcea5..e8d24c058 100644 --- a/docs/modules/ROOT/pages/ec_oci_image_tag_refs.adoc +++ b/docs/modules/ROOT/pages/ec_oci_image_tag_refs.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.image_tag_refs Discover artifacts attached to an image via legacy tag-based discovery (cosign .sig, .att, .sbom suffixes). diff --git a/docs/modules/ROOT/pages/ec_oci_parsed_blob.adoc b/docs/modules/ROOT/pages/ec_oci_parsed_blob.adoc index 21d6d7e30..7c7a2bf46 100644 --- a/docs/modules/ROOT/pages/ec_oci_parsed_blob.adoc +++ b/docs/modules/ROOT/pages/ec_oci_parsed_blob.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.oci.parsed_blob Fetch a blob from an OCI registry and return the parsed JSON value. Results are cached per component. diff --git a/docs/modules/ROOT/pages/ec_opa.adoc b/docs/modules/ROOT/pages/ec_opa.adoc index afed1b6f3..bee5a5464 100644 --- a/docs/modules/ROOT/pages/ec_opa.adoc +++ b/docs/modules/ROOT/pages/ec_opa.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa Open Policy Agent (OPA) (embedded) diff --git a/docs/modules/ROOT/pages/ec_opa_bench.adoc b/docs/modules/ROOT/pages/ec_opa_bench.adoc index dad61241e..bf6cf91da 100644 --- a/docs/modules/ROOT/pages/ec_opa_bench.adoc +++ b/docs/modules/ROOT/pages/ec_opa_bench.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa bench Benchmark a Rego query diff --git a/docs/modules/ROOT/pages/ec_opa_build.adoc b/docs/modules/ROOT/pages/ec_opa_build.adoc index 5fa218022..bc8169aaa 100644 --- a/docs/modules/ROOT/pages/ec_opa_build.adoc +++ b/docs/modules/ROOT/pages/ec_opa_build.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa build Build an OPA bundle diff --git a/docs/modules/ROOT/pages/ec_opa_capabilities.adoc b/docs/modules/ROOT/pages/ec_opa_capabilities.adoc index f71ab31fd..61e87e0b6 100644 --- a/docs/modules/ROOT/pages/ec_opa_capabilities.adoc +++ b/docs/modules/ROOT/pages/ec_opa_capabilities.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa capabilities Print the capabilities of OPA diff --git a/docs/modules/ROOT/pages/ec_opa_check.adoc b/docs/modules/ROOT/pages/ec_opa_check.adoc index 51d4ed086..f068c1719 100644 --- a/docs/modules/ROOT/pages/ec_opa_check.adoc +++ b/docs/modules/ROOT/pages/ec_opa_check.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa check Check Rego source files diff --git a/docs/modules/ROOT/pages/ec_opa_deps.adoc b/docs/modules/ROOT/pages/ec_opa_deps.adoc index f28a41c07..870d9f20f 100644 --- a/docs/modules/ROOT/pages/ec_opa_deps.adoc +++ b/docs/modules/ROOT/pages/ec_opa_deps.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa deps Analyze Rego query dependencies diff --git a/docs/modules/ROOT/pages/ec_opa_eval.adoc b/docs/modules/ROOT/pages/ec_opa_eval.adoc index 9ab7194cd..676ed11e4 100644 --- a/docs/modules/ROOT/pages/ec_opa_eval.adoc +++ b/docs/modules/ROOT/pages/ec_opa_eval.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa eval Evaluate a Rego query diff --git a/docs/modules/ROOT/pages/ec_opa_exec.adoc b/docs/modules/ROOT/pages/ec_opa_exec.adoc index 271b1ff83..fba2a87d6 100644 --- a/docs/modules/ROOT/pages/ec_opa_exec.adoc +++ b/docs/modules/ROOT/pages/ec_opa_exec.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa exec Execute against input files diff --git a/docs/modules/ROOT/pages/ec_opa_fmt.adoc b/docs/modules/ROOT/pages/ec_opa_fmt.adoc index 2f08c5475..96f3d211d 100644 --- a/docs/modules/ROOT/pages/ec_opa_fmt.adoc +++ b/docs/modules/ROOT/pages/ec_opa_fmt.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa fmt Format Rego source files diff --git a/docs/modules/ROOT/pages/ec_opa_inspect.adoc b/docs/modules/ROOT/pages/ec_opa_inspect.adoc index 777cbee99..65897a6f6 100644 --- a/docs/modules/ROOT/pages/ec_opa_inspect.adoc +++ b/docs/modules/ROOT/pages/ec_opa_inspect.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa inspect Inspect OPA bundle(s) diff --git a/docs/modules/ROOT/pages/ec_opa_parse.adoc b/docs/modules/ROOT/pages/ec_opa_parse.adoc index fd177051a..f0f1fc3c1 100644 --- a/docs/modules/ROOT/pages/ec_opa_parse.adoc +++ b/docs/modules/ROOT/pages/ec_opa_parse.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa parse Parse Rego source file diff --git a/docs/modules/ROOT/pages/ec_opa_run.adoc b/docs/modules/ROOT/pages/ec_opa_run.adoc index ff4c807ff..57ecc2b11 100644 --- a/docs/modules/ROOT/pages/ec_opa_run.adoc +++ b/docs/modules/ROOT/pages/ec_opa_run.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa run Start OPA in interactive or server mode diff --git a/docs/modules/ROOT/pages/ec_opa_sign.adoc b/docs/modules/ROOT/pages/ec_opa_sign.adoc index bcea3820d..a02944634 100644 --- a/docs/modules/ROOT/pages/ec_opa_sign.adoc +++ b/docs/modules/ROOT/pages/ec_opa_sign.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa sign Generate an OPA bundle signature diff --git a/docs/modules/ROOT/pages/ec_opa_test.adoc b/docs/modules/ROOT/pages/ec_opa_test.adoc index 7f6dec917..d7c83407f 100644 --- a/docs/modules/ROOT/pages/ec_opa_test.adoc +++ b/docs/modules/ROOT/pages/ec_opa_test.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa test Execute Rego test cases diff --git a/docs/modules/ROOT/pages/ec_opa_version.adoc b/docs/modules/ROOT/pages/ec_opa_version.adoc index 1d5d03119..fd69ffe3f 100644 --- a/docs/modules/ROOT/pages/ec_opa_version.adoc +++ b/docs/modules/ROOT/pages/ec_opa_version.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec opa version Print the version of OPA diff --git a/docs/modules/ROOT/pages/ec_purl_is_valid.adoc b/docs/modules/ROOT/pages/ec_purl_is_valid.adoc index d6e828e17..6206d8950 100644 --- a/docs/modules/ROOT/pages/ec_purl_is_valid.adoc +++ b/docs/modules/ROOT/pages/ec_purl_is_valid.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.purl.is_valid Determine whether or not a given PURL is valid. diff --git a/docs/modules/ROOT/pages/ec_purl_parse.adoc b/docs/modules/ROOT/pages/ec_purl_parse.adoc index cc64368c8..fe882e8cf 100644 --- a/docs/modules/ROOT/pages/ec_purl_parse.adoc +++ b/docs/modules/ROOT/pages/ec_purl_parse.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.purl.parse Parse a valid PURL into an object. diff --git a/docs/modules/ROOT/pages/ec_sigstore.adoc b/docs/modules/ROOT/pages/ec_sigstore.adoc index f8f600a02..420d3a108 100644 --- a/docs/modules/ROOT/pages/ec_sigstore.adoc +++ b/docs/modules/ROOT/pages/ec_sigstore.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec sigstore Perform certain sigstore operations diff --git a/docs/modules/ROOT/pages/ec_sigstore_initialize.adoc b/docs/modules/ROOT/pages/ec_sigstore_initialize.adoc index 44a613a1b..0673e5e22 100644 --- a/docs/modules/ROOT/pages/ec_sigstore_initialize.adoc +++ b/docs/modules/ROOT/pages/ec_sigstore_initialize.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec sigstore initialize Initializes Sigstore root to retrieve trusted certificate and key targets for verification diff --git a/docs/modules/ROOT/pages/ec_sigstore_verify_attestation.adoc b/docs/modules/ROOT/pages/ec_sigstore_verify_attestation.adoc index d7dd5bafa..c8f35a75f 100644 --- a/docs/modules/ROOT/pages/ec_sigstore_verify_attestation.adoc +++ b/docs/modules/ROOT/pages/ec_sigstore_verify_attestation.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.sigstore.verify_attestation Use sigstore to verify the attestation of an image. diff --git a/docs/modules/ROOT/pages/ec_sigstore_verify_image.adoc b/docs/modules/ROOT/pages/ec_sigstore_verify_image.adoc index 22c770333..0aeede7d5 100644 --- a/docs/modules/ROOT/pages/ec_sigstore_verify_image.adoc +++ b/docs/modules/ROOT/pages/ec_sigstore_verify_image.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec.sigstore.verify_image Use sigstore to verify the signature of an image. diff --git a/docs/modules/ROOT/pages/ec_test.adoc b/docs/modules/ROOT/pages/ec_test.adoc index b7803fcea..203d1d222 100644 --- a/docs/modules/ROOT/pages/ec_test.adoc +++ b/docs/modules/ROOT/pages/ec_test.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec test Test your configuration files using Open Policy Agent diff --git a/docs/modules/ROOT/pages/ec_track.adoc b/docs/modules/ROOT/pages/ec_track.adoc index 6f6c702b9..6c8a77ebb 100644 --- a/docs/modules/ROOT/pages/ec_track.adoc +++ b/docs/modules/ROOT/pages/ec_track.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec track Record resource references for tracking purposes diff --git a/docs/modules/ROOT/pages/ec_track_bundle.adoc b/docs/modules/ROOT/pages/ec_track_bundle.adoc index a5f162c2e..98ccf160f 100644 --- a/docs/modules/ROOT/pages/ec_track_bundle.adoc +++ b/docs/modules/ROOT/pages/ec_track_bundle.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec track bundle Record tracking information about Tekton bundles diff --git a/docs/modules/ROOT/pages/ec_validate.adoc b/docs/modules/ROOT/pages/ec_validate.adoc index 689206794..c4efe84f5 100644 --- a/docs/modules/ROOT/pages/ec_validate.adoc +++ b/docs/modules/ROOT/pages/ec_validate.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec validate Validate conformance with the provided policies diff --git a/docs/modules/ROOT/pages/ec_validate_image.adoc b/docs/modules/ROOT/pages/ec_validate_image.adoc index 2eadb4315..c0f656352 100644 --- a/docs/modules/ROOT/pages/ec_validate_image.adoc +++ b/docs/modules/ROOT/pages/ec_validate_image.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec validate image Validate conformance of container images with the provided policies diff --git a/docs/modules/ROOT/pages/ec_validate_input.adoc b/docs/modules/ROOT/pages/ec_validate_input.adoc index 8445f6041..08b7e2954 100644 --- a/docs/modules/ROOT/pages/ec_validate_input.adoc +++ b/docs/modules/ROOT/pages/ec_validate_input.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec validate input Validate arbitrary JSON or yaml file input conformance with the provided policies diff --git a/docs/modules/ROOT/pages/ec_validate_policy.adoc b/docs/modules/ROOT/pages/ec_validate_policy.adoc index 41cc9a79a..ff8cbbf18 100644 --- a/docs/modules/ROOT/pages/ec_validate_policy.adoc +++ b/docs/modules/ROOT/pages/ec_validate_policy.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec validate policy Validate the provided EnterpriseContractPolicy spec diff --git a/docs/modules/ROOT/pages/ec_validate_vsa.adoc b/docs/modules/ROOT/pages/ec_validate_vsa.adoc index 30e8729be..d9c9c0d5e 100644 --- a/docs/modules/ROOT/pages/ec_validate_vsa.adoc +++ b/docs/modules/ROOT/pages/ec_validate_vsa.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec validate vsa Validate VSA (Verification Summary Attestation) diff --git a/docs/modules/ROOT/pages/ec_version.adoc b/docs/modules/ROOT/pages/ec_version.adoc index 0aaeb3515..f5ae80894 100644 --- a/docs/modules/ROOT/pages/ec_version.adoc +++ b/docs/modules/ROOT/pages/ec_version.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec version Print version information diff --git a/docs/modules/ROOT/pages/rego_builtins.adoc b/docs/modules/ROOT/pages/rego_builtins.adoc index 951611584..1c07d04f9 100644 --- a/docs/modules/ROOT/pages/rego_builtins.adoc +++ b/docs/modules/ROOT/pages/rego_builtins.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec rego functions reference documentation The EC CLI provides custom rego builtin functions in addition to the diff --git a/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc b/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc index d2c12019b..dd90b8a28 100644 --- a/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc +++ b/docs/modules/ROOT/pages/verify-conforma-konflux-ta.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = verify-conforma-konflux-ta Version: 0.1 diff --git a/docs/modules/ROOT/pages/verify-enterprise-contract.adoc b/docs/modules/ROOT/pages/verify-enterprise-contract.adoc index 067ba06d7..339e27908 100644 --- a/docs/modules/ROOT/pages/verify-enterprise-contract.adoc +++ b/docs/modules/ROOT/pages/verify-enterprise-contract.adoc @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = verify-enterprise-contract Version: 0.1 diff --git a/internal/documentation/asciidoc/asciidoc.go b/internal/documentation/asciidoc/asciidoc.go index dadca96a8..283a80044 100644 --- a/internal/documentation/asciidoc/asciidoc.go +++ b/internal/documentation/asciidoc/asciidoc.go @@ -17,25 +17,105 @@ package asciidoc import ( - _ "embed" + "bufio" + "fmt" + "os" + "path/filepath" + "strings" "github.com/conforma/cli/internal/documentation/asciidoc/cli" "github.com/conforma/cli/internal/documentation/asciidoc/rego" "github.com/conforma/cli/internal/documentation/asciidoc/tekton" ) +// GeneratedMarker is the comment placed at the top of generated Asciidoc files +// to distinguish them from handwritten documentation. +const GeneratedMarker = "// Generated by conforma CLI documentation tooling. DO NOT EDIT." + func GenerateAsciidoc(module string) error { - if err := cli.GenerateCommandLineDocumentation(module); err != nil { + var generated []string + + cliGenerated, err := cli.GenerateCommandLineDocumentation(module) + if err != nil { + return err + } + generated = append(generated, cliGenerated...) + + regoGenerated, err := rego.GenerateRegoReference(module) + if err != nil { return err } + generated = append(generated, regoGenerated...) - if err := rego.GenerateRegoReference(module); err != nil { + tektonGenerated, err := tekton.GenerateTektonDocumentation(module) + if err != nil { return err } + generated = append(generated, tektonGenerated...) - if err := tekton.GenerateTektonDocumentation(module); err != nil { + if err := removeAbandonedPages(module, generated); err != nil { return err } return nil } + +// removeAbandonedPages removes generated Asciidoc page files that were not +// produced in the current generation run. A file is considered generated if its +// first line matches the GeneratedMarker. Handwritten files are left untouched. +func removeAbandonedPages(module string, generated []string) error { + generatedSet := make(map[string]struct{}, len(generated)) + for _, p := range generated { + generatedSet[p] = struct{}{} + } + + pagesDir := filepath.Join(module, "pages") + entries, err := os.ReadDir(pagesDir) + if err != nil { + return fmt.Errorf("reading pages directory %q: %w", pagesDir, err) + } + + for _, entry := range entries { + if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".adoc") { + continue + } + + path := filepath.Join(pagesDir, entry.Name()) + if _, ok := generatedSet[path]; ok { + // File was just generated, keep it. + continue + } + + isGenerated, err := hasGeneratedMarker(path) + if err != nil { + return fmt.Errorf("checking generated marker in %q: %w", path, err) + } + if !isGenerated { + // Handwritten file, leave it alone. + continue + } + + if err := os.Remove(path); err != nil { + return fmt.Errorf("removing abandoned file %q: %w", path, err) + } + } + + return nil +} + +// hasGeneratedMarker reports whether the first line of the file matches +// GeneratedMarker. +func hasGeneratedMarker(path string) (bool, error) { + f, err := os.Open(path) + if err != nil { + return false, err + } + defer f.Close() + + scanner := bufio.NewScanner(f) + if scanner.Scan() { + return scanner.Text() == GeneratedMarker, nil + } + + return false, scanner.Err() +} diff --git a/internal/documentation/asciidoc/asciidoc_test.go b/internal/documentation/asciidoc/asciidoc_test.go new file mode 100644 index 000000000..a12c3a2d0 --- /dev/null +++ b/internal/documentation/asciidoc/asciidoc_test.go @@ -0,0 +1,149 @@ +// Copyright The Conforma Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// SPDX-License-Identifier: Apache-2.0 + +//go:build unit + +package asciidoc + +import ( + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRemoveAbandonedPages(t *testing.T) { + t.Run("removes stale generated file", func(t *testing.T) { + module := t.TempDir() + pagesDir := filepath.Join(module, "pages") + require.NoError(t, os.MkdirAll(pagesDir, 0755)) + + // Create a stale generated file (has marker but was not regenerated) + stalePath := filepath.Join(pagesDir, "ec_old_command.adoc") + require.NoError(t, os.WriteFile(stalePath, []byte(GeneratedMarker+"\n= ec old command\n"), 0600)) + + // Create a current generated file + currentPath := filepath.Join(pagesDir, "ec_current.adoc") + require.NoError(t, os.WriteFile(currentPath, []byte(GeneratedMarker+"\n= ec current\n"), 0600)) + + err := removeAbandonedPages(module, []string{currentPath}) + require.NoError(t, err) + + assert.NoFileExists(t, stalePath, "stale generated file should be removed") + assert.FileExists(t, currentPath, "current generated file should be kept") + }) + + t.Run("keeps handwritten files", func(t *testing.T) { + module := t.TempDir() + pagesDir := filepath.Join(module, "pages") + require.NoError(t, os.MkdirAll(pagesDir, 0755)) + + // Create a handwritten file (no marker) + handwrittenPath := filepath.Join(pagesDir, "index.adoc") + require.NoError(t, os.WriteFile(handwrittenPath, []byte("= Conforma CLI\n\nSome handwritten content.\n"), 0600)) + + err := removeAbandonedPages(module, []string{}) + require.NoError(t, err) + + assert.FileExists(t, handwrittenPath, "handwritten file should not be removed") + }) + + t.Run("keeps non-adoc files", func(t *testing.T) { + module := t.TempDir() + pagesDir := filepath.Join(module, "pages") + require.NoError(t, os.MkdirAll(pagesDir, 0755)) + + // Create a non-adoc file + otherPath := filepath.Join(pagesDir, "notes.txt") + require.NoError(t, os.WriteFile(otherPath, []byte("some notes"), 0600)) + + err := removeAbandonedPages(module, []string{}) + require.NoError(t, err) + + assert.FileExists(t, otherPath, "non-adoc file should not be removed") + }) + + t.Run("mixed scenario", func(t *testing.T) { + module := t.TempDir() + pagesDir := filepath.Join(module, "pages") + require.NoError(t, os.MkdirAll(pagesDir, 0755)) + + // Handwritten file + handwrittenPath := filepath.Join(pagesDir, "configuration.adoc") + require.NoError(t, os.WriteFile(handwrittenPath, []byte("= Policy Configuration\n\nHandwritten docs.\n"), 0600)) + + // Generated file that still exists + currentGenPath := filepath.Join(pagesDir, "ec_validate.adoc") + require.NoError(t, os.WriteFile(currentGenPath, []byte(GeneratedMarker+"\n= ec validate\n"), 0600)) + + // Stale generated file (command was removed) + stalePath := filepath.Join(pagesDir, "ec_removed_cmd.adoc") + require.NoError(t, os.WriteFile(stalePath, []byte(GeneratedMarker+"\n= ec removed cmd\n"), 0600)) + + // Another stale generated file + stalePath2 := filepath.Join(pagesDir, "ec_old_builtin.adoc") + require.NoError(t, os.WriteFile(stalePath2, []byte(GeneratedMarker+"\n= ec.old.builtin\n"), 0600)) + + generated := []string{currentGenPath} + err := removeAbandonedPages(module, generated) + require.NoError(t, err) + + assert.FileExists(t, handwrittenPath, "handwritten file should be kept") + assert.FileExists(t, currentGenPath, "current generated file should be kept") + assert.NoFileExists(t, stalePath, "stale generated file should be removed") + assert.NoFileExists(t, stalePath2, "stale generated file should be removed") + }) + + t.Run("empty pages directory", func(t *testing.T) { + module := t.TempDir() + pagesDir := filepath.Join(module, "pages") + require.NoError(t, os.MkdirAll(pagesDir, 0755)) + + err := removeAbandonedPages(module, []string{}) + require.NoError(t, err) + }) +} + +func TestHasGeneratedMarker(t *testing.T) { + t.Run("file with marker", func(t *testing.T) { + path := filepath.Join(t.TempDir(), "test.adoc") + require.NoError(t, os.WriteFile(path, []byte(GeneratedMarker+"\n= Some Title\n"), 0600)) + + result, err := hasGeneratedMarker(path) + require.NoError(t, err) + assert.True(t, result) + }) + + t.Run("file without marker", func(t *testing.T) { + path := filepath.Join(t.TempDir(), "test.adoc") + require.NoError(t, os.WriteFile(path, []byte("= Some Title\n\nHandwritten content.\n"), 0600)) + + result, err := hasGeneratedMarker(path) + require.NoError(t, err) + assert.False(t, result) + }) + + t.Run("empty file", func(t *testing.T) { + path := filepath.Join(t.TempDir(), "test.adoc") + require.NoError(t, os.WriteFile(path, []byte(""), 0600)) + + result, err := hasGeneratedMarker(path) + require.NoError(t, err) + assert.False(t, result) + }) +} diff --git a/internal/documentation/asciidoc/cli/cli.go b/internal/documentation/asciidoc/cli/cli.go index 34f344fae..4b73ff0eb 100644 --- a/internal/documentation/asciidoc/cli/cli.go +++ b/internal/documentation/asciidoc/cli/cli.go @@ -59,25 +59,26 @@ func init() { }).Parse(cliNavTemplateText)) } -func GenerateCommandLineDocumentation(module string) error { - if err := generateCommandReference(cmd.RootCmd, module); err != nil { - return err +func GenerateCommandLineDocumentation(module string) ([]string, error) { + var generated []string + if err := generateCommandReference(cmd.RootCmd, module, &generated); err != nil { + return nil, err } if err := generateCommandReferenceNav(cmd.RootCmd, module); err != nil { - return err + return nil, err } - return nil + return generated, nil } -func generateCommandReference(cmd *cobra.Command, module string) error { +func generateCommandReference(cmd *cobra.Command, module string, generated *[]string) error { for _, c := range cmd.Commands() { if !c.IsAvailableCommand() || c.IsAdditionalHelpTopicCommand() { continue } - if err := generateCommandReference(c, module); err != nil { + if err := generateCommandReference(c, module, generated); err != nil { return fmt.Errorf("generating Asciidoc for command %q: %w", c.Name(), err) } } @@ -92,6 +93,8 @@ func generateCommandReference(cmd *cobra.Command, module string) error { } defer f.Close() + *generated = append(*generated, docpath) + return commandTemplate.Execute(f, cmd) } diff --git a/internal/documentation/asciidoc/cli/cli.tmpl b/internal/documentation/asciidoc/cli/cli.tmpl index 5e7408fad..be63815fb 100644 --- a/internal/documentation/asciidoc/cli/cli.tmpl +++ b/internal/documentation/asciidoc/cli/cli.tmpl @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = {{ .CommandPath }} {{ .Short }} diff --git a/internal/documentation/asciidoc/rego/builtins.tmpl b/internal/documentation/asciidoc/rego/builtins.tmpl index 85bc635f0..15c4bb2bc 100644 --- a/internal/documentation/asciidoc/rego/builtins.tmpl +++ b/internal/documentation/asciidoc/rego/builtins.tmpl @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = ec rego functions reference documentation The EC CLI provides custom rego builtin functions in addition to the diff --git a/internal/documentation/asciidoc/rego/rego.go b/internal/documentation/asciidoc/rego/rego.go index 96d6c7203..55cd1a263 100644 --- a/internal/documentation/asciidoc/rego/rego.go +++ b/internal/documentation/asciidoc/rego/rego.go @@ -83,20 +83,23 @@ func init() { builtins = findBuiltins() } -func GenerateRegoReference(module string) error { - if err := generateRegoReference(module); err != nil { - return err +func GenerateRegoReference(module string) ([]string, error) { + generated, err := generateRegoReference(module) + if err != nil { + return nil, err } if err := generateRegoReferenceNav(module); err != nil { - return err + return nil, err } - if err := generateRegoBuiltins(module); err != nil { - return err + builtinsPath, err := generateRegoBuiltins(module) + if err != nil { + return nil, err } + generated = append(generated, builtinsPath) - return nil + return generated, nil } func findBuiltins() []*ast.Builtin { @@ -114,21 +117,23 @@ func findBuiltins() []*ast.Builtin { return builtins } -func generateRegoReference(module string) error { +func generateRegoReference(module string) ([]string, error) { + var generated []string for _, b := range builtins { docpath := filepath.Join(module, "pages", strings.ReplaceAll(b.Name, ".", "_")+".adoc") f, err := os.Create(docpath) if err != nil { - return fmt.Errorf("creating file %q: %w", docpath, err) + return nil, fmt.Errorf("creating file %q: %w", docpath, err) } defer f.Close() if err := regoTemplate.Execute(f, b); err != nil { - return err + return nil, err } + generated = append(generated, docpath) } - return nil + return generated, nil } func generateRegoReferenceNav(module string) error { @@ -142,13 +147,13 @@ func generateRegoReferenceNav(module string) error { return regoNavTemplate.Execute(f, builtins) } -func generateRegoBuiltins(module string) error { +func generateRegoBuiltins(module string) (string, error) { builtinsPath := filepath.Join(module, "pages", "rego_builtins.adoc") f, err := os.Create(builtinsPath) if err != nil { - return fmt.Errorf("creating file %q: %w", builtinsPath, err) + return "", fmt.Errorf("creating file %q: %w", builtinsPath, err) } defer f.Close() - return regoBuiltinsTemplate.Execute(f, builtins) + return builtinsPath, regoBuiltinsTemplate.Execute(f, builtins) } diff --git a/internal/documentation/asciidoc/rego/rego.tmpl b/internal/documentation/asciidoc/rego/rego.tmpl index 02e488b11..f89fc635f 100644 --- a/internal/documentation/asciidoc/rego/rego.tmpl +++ b/internal/documentation/asciidoc/rego/rego.tmpl @@ -39,6 +39,7 @@ {{- end }}{{- /* range */ -}} {{- end -}}{{- /* "properties" */ -}} +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = {{ .Name }} {{ .Description }} diff --git a/internal/documentation/asciidoc/tekton/task.tmpl b/internal/documentation/asciidoc/tekton/task.tmpl index f36151545..d002a9323 100644 --- a/internal/documentation/asciidoc/tekton/task.tmpl +++ b/internal/documentation/asciidoc/tekton/task.tmpl @@ -1,3 +1,4 @@ +// Generated by conforma CLI documentation tooling. DO NOT EDIT. = {{ .Name}} Version: {{ index .Labels "app.kubernetes.io/version" }} diff --git a/internal/documentation/asciidoc/tekton/tekton.go b/internal/documentation/asciidoc/tekton/tekton.go index c9fc54872..97e4e83a5 100644 --- a/internal/documentation/asciidoc/tekton/tekton.go +++ b/internal/documentation/asciidoc/tekton/tekton.go @@ -73,33 +73,36 @@ func init() { } } -func GenerateTektonDocumentation(module string) error { - if err := generateTektonReference(module); err != nil { - return err +func GenerateTektonDocumentation(module string) ([]string, error) { + generated, err := generateTektonReference(module) + if err != nil { + return nil, err } if err := generateTektonNav(module); err != nil { - return err + return nil, err } - return nil + return generated, nil } -func generateTektonReference(module string) error { +func generateTektonReference(module string) ([]string, error) { + var generated []string for _, task := range tasks { docpath := filepath.Join(module, "pages", task.Name+".adoc") f, err := os.Create(docpath) if err != nil { - return fmt.Errorf("creating file %q: %w", docpath, err) + return nil, fmt.Errorf("creating file %q: %w", docpath, err) } defer f.Close() if err := tektonTaskTemplate.Execute(f, task); err != nil { - return err + return nil, err } + generated = append(generated, docpath) } - return nil + return generated, nil } func generateTektonNav(module string) error {