ci(azure): verify Bicep template synchronization

This commit is contained in:
Hugo P.Brito committed 2026-08-24 15:13:50 +01:00
1 parent bb2a0031d0
commit cc58a2709c
6 files changed
+103 -15

No files matched your search

@@ -0,0 +1,69 @@
name: 'Docs: Azure ARM Template'
on:
push:
branches:
- 'master'
- 'v5.*'
paths:
- '.github/workflows/docs-check-azure-arm-template.yml'
- 'docs/assets/templates/azure/prowler-scan.json'
- 'docs/snippets/azure-prowler-scan-template.mdx'
- 'permissions/templates/azure/bicep/Makefile'
- 'permissions/templates/azure/bicep/prowler-scan.bicep'
- 'permissions/templates/azure/bicep/prowler-scan.json'
- 'permissions/templates/azure/bicep/sync_docs_template.py'
- 'permissions/templates/azure/bicep/sync_docs_template_test.py'
pull_request:
branches:
- 'master'
- 'v5.*'
paths:
- '.github/workflows/docs-check-azure-arm-template.yml'
- 'docs/assets/templates/azure/prowler-scan.json'
- 'docs/snippets/azure-prowler-scan-template.mdx'
- 'permissions/templates/azure/bicep/Makefile'
- 'permissions/templates/azure/bicep/prowler-scan.bicep'
- 'permissions/templates/azure/bicep/prowler-scan.json'
- 'permissions/templates/azure/bicep/sync_docs_template.py'
- 'permissions/templates/azure/bicep/sync_docs_template_test.py'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
jobs:
azure-arm-template:
if: github.repository == 'prowler-cloud/prowler'
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: block
allowed-endpoints: >
api.github.com:443
github.com:443
release-assets.githubusercontent.com:443
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Bicep
uses: anthony-c-martin/setup-bicep@faf8170f496c10a2ea75977d2e77024131331404 # v1
with:
version: v0.46.1
- name: Test Azure ARM documentation synchronization
run: python3 -m unittest permissions/templates/azure/bicep/sync_docs_template_test.py
- name: Check Azure ARM template synchronization
run: make --directory permissions/templates/azure/bicep check
-3
View File
@@ -62,6 +62,3 @@ jobs:
env:
pnpm_config_ignore_scripts: 'true'
run: git ls-files -z '*.md' | xargs -0 -r pnpm dlx markdownlint-cli@0.45.0 --
- name: Check Azure ARM documentation assets
run: python3 permissions/templates/azure/bicep/sync_docs_template.py --check
@@ -101,5 +101,4 @@
}
}
}
```
+6 -3
View File
@@ -26,10 +26,13 @@ sync-docs: prowler-scan.json
# CI hook: fail if the JSON is out of sync with the Bicep source. Run
# `make build` locally and commit both files before opening the PR.
check: prowler-scan.bicep
$(BICEP_BUILD) prowler-scan.bicep --outfile /tmp/prowler-scan.check.json
diff -q prowler-scan.json /tmp/prowler-scan.check.json
@set -eu; \
tmp=$$(mktemp); \
trap 'rm -f "$$tmp"' EXIT; \
$(BICEP_BUILD) prowler-scan.bicep --outfile "$$tmp"; \
python3 -c 'from pathlib import Path; import sys; path = Path(sys.argv[1]); path.write_bytes(path.read_bytes().rstrip(b"\r\n") + b"\n")' "$$tmp"; \
diff -q prowler-scan.json "$$tmp"; \
python3 sync_docs_template.py --check
rm /tmp/prowler-scan.check.json
clean:
rm -f prowler-scan.json
@@ -11,7 +11,7 @@ SNIPPET_PREFIX = (
b"{/* AUTO-GENERATED from permissions/templates/azure/bicep/"
b"prowler-scan.json. Do not edit manually. */}\n\n```json\n"
)
SNIPPET_SUFFIX = b"\n```\n"
SNIPPET_SUFFIX = b"```\n"
def parse_args():
@@ -33,18 +33,22 @@ def expected_snippet(source):
def main():
args = parse_args()
source = args.source.read_bytes()
source_bytes = args.source.read_bytes()
source = source_bytes.rstrip(b"\r\n") + b"\n"
json.loads(source)
snippet = expected_snippet(source)
if args.sync:
args.asset.parent.mkdir(parents=True, exist_ok=True)
args.snippet.parent.mkdir(parents=True, exist_ok=True)
args.source.write_bytes(source)
args.asset.write_bytes(source)
args.snippet.write_bytes(snippet)
return 0
drifted = []
if source_bytes != source:
drifted.append(args.source)
if not args.asset.exists() or args.asset.read_bytes() != source:
drifted.append(args.asset)
if not args.snippet.exists() or args.snippet.read_bytes() != snippet:
@@ -39,13 +39,29 @@ class SyncDocsTemplateTest(unittest.TestCase):
check=False,
)
def test_sync_copies_asset_and_embeds_exact_canonical_bytes(self):
result = self.run_script("--sync")
def test_sync_normalizes_canonical_and_asset_to_one_trailing_lf(self):
for terminal_newlines in (b"", b"\n", b"\n\n", b"\r\n\r\n"):
with self.subTest(terminal_newlines=terminal_newlines):
self.source.write_bytes(self.canonical + terminal_newlines)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(self.asset.read_bytes(), self.canonical)
snippet = self.snippet.read_bytes()
self.assertIn(b"```json\n" + self.canonical + b"\n```", snippet)
result = self.run_script("--sync")
self.assertEqual(result.returncode, 0, result.stderr)
expected = self.canonical + b"\n"
self.assertEqual(self.source.read_bytes(), expected)
self.assertEqual(self.asset.read_bytes(), expected)
def test_sync_normalizes_snippet_fence_and_final_lf(self):
for terminal_newlines in (b"", b"\n", b"\n\n", b"\r\n\r\n"):
with self.subTest(terminal_newlines=terminal_newlines):
self.source.write_bytes(self.canonical + terminal_newlines)
result = self.run_script("--sync")
self.assertEqual(result.returncode, 0, result.stderr)
self.assertTrue(
self.snippet.read_bytes().endswith(self.canonical + b"\n```\n")
)
def test_check_fails_when_generated_output_drifts(self):
self.assertEqual(self.run_script("--sync").returncode, 0)