Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/komizo-action-source.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": 1,
"platform_revision": "1b740f28682948a2d5eb4613744bb262d2056e6c",
"action_revision": "2ca94e2fd4bb05f41bb228e9c366e5cc733c75e6"
}
9 changes: 9 additions & 0 deletions .github/readme-source.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"version": 1,
"sha256": "b0008a20f0336bdc0cade112310947098eadf2e3ce51e9f65fc07d0be8c8c47d",
"history": {
"forbidden_commits": [
"0eb77f25b1b2c0df30fb7a80abb435bf5bd65724"
]
}
}
87 changes: 87 additions & 0 deletions .github/scripts/check-documentation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python3
"""Check tracked documentation layout and the reviewed usage README digest."""
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import subprocess
import sys

MARKDOWN = {'.md', '.markdown', '.mdown', '.mkd', '.mkdn', '.mdwn', '.mdx', '.rmd', '.qmd'}
OTHER_DOCS = {'.rst', '.adoc', '.asciidoc'}


def check(root, include_history=True, history_required=False):
raw = subprocess.check_output(['git', 'ls-files', '--stage', '-z'], cwd=root)
entries = {}
errors = []
for record in raw.split(b'\0'):
if not record:
continue
metadata, encoded = record.split(b'\t', 1)
mode, _oid, stage = metadata.decode().split()
name = encoded.decode('utf-8', 'surrogateescape')
if stage != '0':
errors.append('unmerged index entry: ' + name)
entries[name] = mode
path = PurePosixPath(name)
if name != 'README.md' and (path.suffix.lower() in MARKDOWN | OTHER_DOCS
or path.name.lower().startswith('readme.')):
errors.append('documentation must live in the private docs repository: ' + name)
if entries.get('README.md') != '100644' and entries.get('README.md') != '100755':
errors.append('a regular, tracked root README.md is required')
else:
readme = root / 'README.md'
if readme.is_symlink() or not readme.is_file():
errors.append('root README.md must be a regular file')
else:
try:
body = readme.read_bytes()
if not any(line.startswith('# ') for line in body.decode('utf-8').splitlines()):
errors.append('root README.md needs a product heading')
policy_path = root / '.github/readme-source.json'
if policy_path.is_symlink():
raise ValueError('README source policy cannot be a symlink')
policy = json.loads(policy_path.read_text())
if policy.get('version') != 1:
raise ValueError('unsupported README source policy')
if hashlib.sha256(body).hexdigest() != policy.get('sha256'):
errors.append('README differs from its reviewed publication; update the private source first')
history = policy.get('history')
if history_required and history is None:
raise ValueError('public repositories require a history boundary')
if include_history and history is not None:
if set(history) != {'forbidden_commits'} or not isinstance(history['forbidden_commits'], list) or not history['forbidden_commits']:
raise ValueError('invalid public history boundary')
forbidden = set(history['forbidden_commits'])
if any(not isinstance(oid, str) or len(oid) != 40 or any(c not in '0123456789abcdef' for c in oid) for oid in forbidden):
raise ValueError('invalid original history identity')
shallow = subprocess.check_output(['git', 'rev-parse', '--is-shallow-repository'], cwd=root, text=True).strip()
if shallow != 'false':
raise ValueError('public history verification requires fetch-depth: 0')
ancestors = set(subprocess.check_output(['git', 'rev-list', 'HEAD'], cwd=root, text=True).splitlines())
if ancestors & forbidden:
errors.append('original history was reintroduced; transplant changes onto the cleaned main history')
patterns = [':(icase)*'+suffix for suffix in sorted(MARKDOWN)]
past = subprocess.check_output(['git', 'log', '--format=', '--name-only', '-z', 'HEAD', '--', *patterns], cwd=root)
extra = {name.decode('utf-8', 'surrogateescape') for name in past.split(b'\0') if name and name != b'README.md'}
errors.extend('historical Markdown must remain in private docs: '+name for name in sorted(extra))

except (OSError, ValueError, UnicodeError) as error:
errors.append('invalid README source policy or README: ' + str(error))
return errors


def main():
root = Path(subprocess.check_output(['git', 'rev-parse', '--show-toplevel'], text=True).strip())
errors = check(root, history_required=os.environ.get('REQUIRE_CLEAN_HISTORY') == 'true')
for error in errors:
print(error, file=sys.stderr)
if errors:
return 1
print('Documentation policy passed: one root README.md, reviewed source digest matches.')
return 0


if __name__ == '__main__':
sys.exit(main())
2 changes: 1 addition & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up locked komizo
uses: nicodes/komizo/setup@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
uses: nicodes/komizo/setup@2ca94e2fd4bb05f41bb228e9c366e5cc733c75e6
env:
GH_TOKEN: ${{ github.token }}
- name: Validate and build the redirect
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
with:
persist-credentials: false
- name: Set up locked komizo
uses: nicodes/komizo/setup@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
uses: nicodes/komizo/setup@2ca94e2fd4bb05f41bb228e9c366e5cc733c75e6
env:
GH_TOKEN: ${{ github.token }}
timeout-minutes: 5
Expand All @@ -52,7 +52,7 @@ jobs:
retention-days: 7
include-hidden-files: true
- name: Check project
uses: nicodes/komizo/run@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
uses: nicodes/komizo/run@2ca94e2fd4bb05f41bb228e9c366e5cc733c75e6
with:
target: check
- name: Upload artifacts
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
ref: main
timeout-minutes: 3
- name: Set up locked komizo
uses: nicodes/komizo/setup@40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9
uses: nicodes/komizo/setup@2ca94e2fd4bb05f41bb228e9c366e5cc733c75e6
env:
GH_TOKEN: ${{ github.token }}
timeout-minutes: 5
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/documentation-policy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Documentation policy
on:
push:
pull_request:
merge_group:
workflow_dispatch:
permissions:
contents: read
jobs:
documentation-policy:
name: Documentation policy
runs-on: ubuntu-24.04
timeout-minutes: 3
steps:
- name: Check out source
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false
fetch-depth: ${{ github.event.repository.private && 1 || 0 }}
- name: Check documentation boundary
env:
REQUIRE_CLEAN_HISTORY: ${{ !github.event.repository.private }}
run: python3 .github/scripts/check-documentation.py
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<!-- Generated from private documentation source. Do not edit directly. Source SHA256: f9e57e7ccb79e8911a4fdc009f1b3f2c892868f526b2d41ebddb77c6e7018a2f -->

# aviorstudio.github.io

For current client installation and usage, see https://github.com/aviorstudio/aviorstudio.github.io#readme.
Static redirect to [Avior Studio](https://www.avior.studio/).

Install the [komizo release](https://github.com/nicodes/komizo#install) matching `komizo.lock`, then run `komizo check`. Use `komizo describe` to inspect the applicable stages.
6 changes: 3 additions & 3 deletions komizo.lock
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"version": 1,
"platform": "0.2.4",
"platform_revision": "40086036977a5fc0119d6c4c1d5eb6ae3ab3b4b9",
"platform": "0.2.7",
"platform_revision": "1b740f28682948a2d5eb4613744bb262d2056e6c",
"manifest_sha256": "f605f9b8126a0fdab262650c7812be90cbba5c472cdb335c8ef527dc2407888e",
"runtime_sha256": "000c1991c455b7e1269646e40c05ebf4a1b0717197c34838d2b7669430b3e862",
"runtime_sha256": "e85ed5057a15b6432600b5596aacbc967179122757378b61dc4247a101db8f9b",
"recipe_sha256": "33ac62cab7dbea38c303cabc99c60ac1adf33ef21bd0b2b5c62bcb22fcac2235"
}