-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add github presubmit workflow to prevent /docs edits
The content of /docs should be generated and not manually generated. We add a script to check for edits and also allow for tags to override the check.
- Loading branch information
Showing
4 changed files
with
173 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -77,9 +77,20 @@ jobs: | |
run: | | ||
cd build/web && printf "y" | ./build.sh presubmit | ||
validate-docs: | ||
name: validate-docs | ||
runs-on: ubuntu-22.04-4core | ||
steps: | ||
- uses: actions/[email protected] | ||
with: | ||
fetch-depth: 0 | ||
- name: Check unpermitted edits to /docs | ||
run: | | ||
bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }} | ||
test-renderdiff: | ||
name: test-renderdiff | ||
runs-on: ubuntu-22.04-32core | ||
runs-on: ubuntu-22.04-16core | ||
|
||
steps: | ||
- uses: actions/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
# Copyright (C) 2025 The Android Open Source Project | ||
# | ||
# 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. | ||
|
||
# This script contains several checks on the current commit, each corresponds to `possible_conditions` | ||
# in the main function below | ||
# - Direct (non-filamentbot) edits of /docs | ||
# - Edits to sources of READMEs that are duplicated to /docs | ||
# or edits to /docs_src sources | ||
# - Commit message has DOCS_BYPASS | ||
# - Commit message has DOCS_FORCE | ||
# - Commit message has DOCS_ALLOW_DIRECT_EDITS | ||
|
||
import json | ||
import sys | ||
import os | ||
|
||
from utils import execute, ArgParseImpl | ||
|
||
CUR_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
ROOT_DIR = os.path.join(CUR_DIR, '../../') | ||
|
||
def get_last_commit_hash(): | ||
res, ret = execute('git rev-parse HEAD', cwd=ROOT_DIR) | ||
assert res == 0, 'Failed to get the last commit hash' | ||
return ret.strip() | ||
|
||
def get_edited_files(commit_hash): | ||
INSERT = '#####?????' | ||
res, ret = execute(f'git show --name-only --pretty=%b{INSERT} {commit_hash}') | ||
assert res == 0, 'Failed to get edited filed' | ||
files = [] | ||
_, after = ret.split(INSERT) | ||
for r in filter(lambda a: len(a) > 0, after.split('\n')): | ||
if r.startswith('commit'): | ||
break | ||
files.append(r) | ||
return files | ||
|
||
# Returns True if there were no direct edits to '/docs' | ||
def check_no_direct_edits(commit_hash, printing=True): | ||
bad = [f'\t{f}' for f in get_edited_files(commit_hash) if f.startswith('docs/')] | ||
if printing and len(bad) > 0: | ||
print(f'Found direct edits to /docs:\n' + '\n'.join(bad)) | ||
return len(bad) == 0 | ||
|
||
# Returns True if docs sources have been modified | ||
def check_has_source_edits(commit_hash, printing=True): | ||
config = {} | ||
with open(f'{CUR_DIR}/duplicates.json') as config_txt: | ||
config = json.loads(config_txt.read()) | ||
source_files = set(config.keys()) | ||
edited_files = set(get_edited_files(commit_hash)) | ||
overlap = [f'\t{f}' for f in list(source_files & edited_files)] | ||
if printing and len(overlap) > 0: | ||
print(f'Found edited source files:\n' + '\n'.join(overlap)) | ||
return len(overlap) > 0 | ||
|
||
# Returns true in a given TAG is found in the commit msg | ||
def commit_msg_has_tag(commit_hash, tag, printing=True): | ||
res, ret = execute(f'git log --pretty=%B {commit_hash}', cwd=ROOT_DIR) | ||
for l in ret.split('\n'): | ||
if tag == l.strip(): | ||
if printing: | ||
print(f'Found tag={tag} in commit message') | ||
return True | ||
return False | ||
|
||
if __name__ == "__main__": | ||
parser = ArgParseImpl() | ||
|
||
TAG_DOCS_BYPASS = 'DOCS_BYPASS' | ||
TAG_DOCS_FORCE = 'DOCS_FORCE' | ||
TAG_DOCS_ALLOW_DIRECT_EDITS = 'DOCS_ALLOW_DIRECT_EDITS' | ||
|
||
possible_conditions = { | ||
'no_direct_edits': | ||
check_no_direct_edits, | ||
'source_edits': | ||
check_has_source_edits, | ||
'commit_docs_bypass': | ||
lambda h: commit_msg_has_tag(h, TAG_DOCS_BYPASS), | ||
'commit_docs_force': | ||
lambda h: commit_msg_has_tag(h, TAG_DOCS_FORCE), | ||
'commit_docs_allow_direct_edits': | ||
lambda h: commit_msg_has_tag(h, TAG_DOCS_ALLOW_DIRECT_EDITS), | ||
} | ||
|
||
possible_str = ', '.join(list(possible_conditions.keys())) | ||
parser.add_argument( | ||
'--do-and', | ||
type=str, | ||
help=( | ||
f'A conjunction of boolean conditions. Possible values are={possible_str}. ' | ||
'Negation is done with `-`' | ||
) | ||
) | ||
parser.add_argument( | ||
'--do-or', | ||
type=str, | ||
help=( | ||
f'A disjunction of boolean conditions. Possible values are={possible_str}. ' | ||
'Negation is done with `-`' | ||
) | ||
) | ||
|
||
args, _ = parser.parse_known_args(sys.argv[1:len(sys.argv) - 1]) | ||
commit_hash = sys.argv[-1] | ||
|
||
assert not (args.do_and and args.do_or), "Must not supply both '--do-and' and '--do-or'" | ||
assert args.do_and or args.do_or, "Must supply argument '--do-and' or '--do-or'" | ||
conds = args.do_and.split(',') if args.do_and else args.do_or.split(',') | ||
conds = [c.strip() for c in conds] | ||
assert all( | ||
[c in possible_conditions.keys() for c in | ||
[(c.replace('-', '') if c.startswith('-') else c) for c in conds]]),\ | ||
f"Not all conditions are valid names. Only {possible_str} are accepted" | ||
|
||
res = [] | ||
for cond in conds: | ||
if cond.startswith('-'): | ||
f = lambda: not possible_conditions[cond.replace('-', '')]() | ||
else: | ||
f = possible_conditions[cond] | ||
res.append(f(commit_hash)) | ||
|
||
if args.do_and: | ||
exit(0 if all(res) else 1) | ||
else: | ||
exit(0 if any(res) else 1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/usr/bin/bash | ||
|
||
# Copyright (C) 2025 The Android Open Source Project | ||
# | ||
# 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. | ||
|
||
COMMIT_HASH=$1 | ||
python3 docs_src/build/checks.py --do-or="no_direct_edits,commit_docs_allow_direct_edits" $COMMIT_HASH ||\ | ||
(echo "There are direct edits to /docs. Please see /docs_src/README.md if you need to bypass this check" && exit 1) |