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
113 changes: 113 additions & 0 deletions .ci/scripts/skip_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!/usr/bin/env python3
"""
skip_tests.py - Check if only documentation files were changed in a git branch

Usage:
./skip_tests.py <git_root> <reference_branch>

Arguments:
git_root: The root directory of the git project
reference_branch: The branch to compare against

Returns:
0: Skip
1: NoSkip
*: Error
"""

import sys
import os
import re
import git
import textwrap
import argparse

DOC_PATTERNS = [
r"^docs/",
r"\.md$",
r"\.txt$",
r"LICENSE.*",
r"CHANGELOG.*",
r"CHANGES.*",
r"CONTRIBUTING.*",
]

# Exit codes
CODE_SKIP = 0
CODE_NO_SKIP = 1
CODE_ERROR = 2


def main() -> int:
git_root, reference_branch = get_args()
changed_files = get_changed_files(git_root, reference_branch)
if not changed_files:
return CODE_SKIP
doc_files = [f for f in changed_files if is_doc_file(f)]
not_doc_files = set(changed_files) - set(doc_files)
print_changes(doc_files, not_doc_files)
if not_doc_files:
return CODE_NO_SKIP
else:
return CODE_SKIP


# Utils


def get_changed_files(git_root: str, reference_branch: str) -> list[str]:
"""Get list of files changed between current branch and reference branch."""
repo = git.Repo(git_root)
diff_index = repo.git.diff("--name-only", reference_branch).strip()
if not diff_index:
return []
return [f.strip() for f in diff_index.split("\n") if f.strip()]


def is_doc_file(file_path: str) -> bool:
"""Check if a file is a documentation file."""
for pattern in DOC_PATTERNS:
if re.search(pattern, file_path):
return True
return False


def print_changes(doc_files: list[str], not_doc_files: list[str]) -> None:
display_doc = " \n".join(doc_files)
print(f"doc_files({len(doc_files)})")
if doc_files:
display_doc = "\n".join(doc_files)
print(textwrap.indent(display_doc, " "))

print(f"non_doc_files({len(not_doc_files)})")
if not_doc_files:
display_non_doc = " \n".join(not_doc_files)
print(textwrap.indent(display_non_doc, " "))


def get_args() -> tuple[str, str]:
"""Parse command line arguments and validate them."""
parser = argparse.ArgumentParser(description="Check if CI can skip tests for a git branch")
parser.add_argument("git_root", help="The root directory of the git project")
parser.add_argument("reference_branch", help="The branch to compare against")
args = parser.parse_args()
git_root = os.path.abspath(args.git_root)
ref_branch = args.reference_branch

if not os.path.exists(git_root):
raise ValueError(f"Git root directory does not exist: {git_root}")
if not os.path.isdir(git_root):
raise ValueError(f"Git root is not a directory: {git_root}")
try:
git.Repo(git_root)
except git.InvalidGitRepositoryError:
raise ValueError(f"Directory is not a git repository: {git_root}")
return git_root, ref_branch


if __name__ == "__main__":
try:
sys.exit(main())
except Exception as e:
print(e)
sys.exit(CODE_ERROR)
51 changes: 49 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,49 @@ jobs:
run: |
.github/workflows/scripts/check_commit.sh

check-changes:
runs-on: ubuntu-latest
outputs:
run_tests: ${{ steps.check.outputs.run_tests }}
steps:
- uses: "actions/checkout@v4"
with:
fetch-depth: 0
path: "pulp_npm"

- uses: "actions/setup-python@v5"
with:
python-version: "3.12"

- name: "Install python dependencies"
run: |
echo ::group::PYDEPS
pip install gitpython
echo ::endgroup::

- name: Analyze changed files
shell: bash
id: check
run: |
set +e
BASE_REF=${{ github.event.pull_request.base.sha }}
echo "Checking against:"
git name-rev $BASE_REF
python3 .ci/scripts/skip_tests.py . $BASE_REF
exit_code=$?
if [ $exit_code -ne 0 ] && [ $exit_code -ne 1 ]; then
echo "Error: skip_tests.py returned unexpected exit code $exit_code"
exit $exit_code
fi
echo "run_tests=$exit_code" >> $GITHUB_OUTPUT

docs:
uses: "./.github/workflows/docs.yml"

lint:
needs:
- "check-changes"
if: needs.check-changes.outputs.run_tests == '1'
uses: "./.github/workflows/lint.yml"

build:
Expand Down Expand Up @@ -84,6 +123,7 @@ jobs:
# This is a dummy dependent task to have a single entry for the branch protection rules.
runs-on: "ubuntu-latest"
needs:
- "check-changes"
- "check-commits"
- "lint"
- "test"
Expand All @@ -93,6 +133,13 @@ jobs:
- name: "Collect needed jobs results"
working-directory: "."
run: |
echo '${{toJson(needs)}}' | jq -r 'to_entries[]|select(.value.result!="success")|.key + ": " + .value.result'
echo '${{toJson(needs)}}' | jq -e 'to_entries|map(select(.value.result!="success"))|length == 0'
if [ ${{ needs.check-changes.outputs.run_tests }} == "1" ]; then
# Full test run - check all jobs
echo '${{toJson(needs)}}' | jq -r 'to_entries[]|select(.value.result!="success")|.key + ": " + .value.result'
echo '${{toJson(needs)}}' | jq -e 'to_entries|map(select(.value.result!="success"))|length == 0'
else
# Docs-only run - check only required jobs (exclude lint and test)
echo '${{toJson(needs)}}' | jq -r 'to_entries[]|select(.key != "lint" and .key != "test")|select(.value.result!="success")|.key + ": " + .value.result'
echo '${{toJson(needs)}}' | jq -e 'to_entries|map(select(.key != "lint" and .key != "test"))|map(select(.value.result!="success"))|length == 0'
fi
echo "CI says: Looks good!"
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ jobs:
with:
python-version: "3.11"

# Click is pinned because of:
# https://github.com/pallets/click/issues/3065
- name: "Install python dependencies"
run: |
echo ::group::PYDEPS
pip install bump-my-version towncrier
pip install bump-my-version towncrier 'click<8.3'
echo ::endgroup::

- name: "Configure Git with pulpbot name and email"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ jobs:
- name: "Install python dependencies"
run: |
echo ::group::PYDEPS
pip install towncrier twine wheel httpie docker netaddr boto3 'ansible~=10.3.0' mkdocs jq jsonpatch bump-my-version
pip install towncrier twine wheel httpie docker netaddr boto3 'ansible~=10.3.0' mkdocs jq jsonpatch bump-my-version 'click<8.3'
echo "HTTPIE_CONFIG_DIR=$GITHUB_WORKSPACE/pulp_npm/.ci/assets/httpie/" >> $GITHUB_ENV
echo ::endgroup::

Expand Down
3 changes: 3 additions & 0 deletions lint_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
# For more info visit https://github.com/pulp/plugin_template

black==24.3.0
# Click is pinned because of:
# https://github.com/pallets/click/issues/3065
click<8.3
bump-my-version
check-manifest
flake8
Expand Down