diff --git a/.github/scripts/validate_commit_message.py b/.github/scripts/validate_commit_message.py new file mode 100644 index 0000000..9d9b56a --- /dev/null +++ b/.github/scripts/validate_commit_message.py @@ -0,0 +1,73 @@ +import os +import re +import subprocess +import sys +from pathlib import Path + +import toml +from github import Github + +KEYWORDS = ["fixes", "closes"] +BLOCKING_REGEX = [ + "DRAFT", + "WIP", + "NOMERGE", + r"DO\s*NOT\s*MERGE", + "EXPERIMENT", +] +NO_ISSUE = "[noissue]" +CHANGELOG_EXTS = [ + f".{item['directory']}" for item in toml.load("pyproject.toml")["tool"]["towncrier"]["type"] +] + +sha = sys.argv[1] +message = subprocess.check_output(["git", "log", "--format=%B", "-n 1", sha]).decode("utf-8") + +if any((re.match(pattern, message) for pattern in BLOCKING_REGEX)): + sys.exit("This PR is not ready for consumption.") + +g = Github(os.environ.get("GITHUB_TOKEN")) +repo = g.get_repo("pulp/pulp-cli") + + +def check_status(issue): + gi = repo.get_issue(int(issue)) + if gi.pull_request: + sys.exit(f"Error: issue #{issue} is a pull request.") + if gi.closed_at: + sys.exit(f"Error: issue #{issue} is closed.") + + +def check_changelog(issue): + matches = list(Path("CHANGES").rglob(f"{issue}.*")) + + if len(matches) < 1: + sys.exit(f"Could not find changelog entry in CHANGES/ for {issue}.") + for match in matches: + if match.suffix not in CHANGELOG_EXTS: + sys.exit(f"Invalid extension for changelog entry '{match}'.") + + +print("Checking commit message for {sha}.".format(sha=sha[0:7])) + +# validate the issue attached to the commit +issue_regex = r"(?:{keywords})[\s:]+#(\d+)".format(keywords=("|").join(KEYWORDS)) +issues = re.findall(issue_regex, message, re.IGNORECASE) +cherry_pick_regex = r"^\s*\(cherry picked from commit [0-9a-f]*\)\s*$" +cherry_pick = re.search(cherry_pick_regex, message, re.MULTILINE) + +if issues: + for issue in issues: + if not cherry_pick: + check_status(issue) + check_changelog(issue) +else: + if NO_ISSUE in message: + print("Commit {sha} has no issues but is tagged {tag}.".format(sha=sha[0:7], tag=NO_ISSUE)) + else: + sys.exit( + "Error: no attached issues found for {sha}. If this was intentional, add " + " '{tag}' to the commit message.".format(sha=sha[0:7], tag=NO_ISSUE) + ) + +print("Commit message for {sha} passed.".format(sha=sha[0:7])) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..d91eced --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,35 @@ +name: "Build" + +on: + workflow_call: + +jobs: + build: + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v4" + # - uses: "actions/cache@v4" + # with: + # path: "~/.cache/pip" + # key: "${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/*constraints.lock', '**/setup.py', '**/pyproject.toml') }}" + # restore-keys: | + # ${{ runner.os }}-pip- + + - name: "Set up Python" + uses: "actions/setup-python@v5" + with: + python-version: "3.11" + - name: "Install python dependencies" + run: | + pip install build setuptools wheel + - name: "Build wheels" + run: | + make build + - name: "Upload wheels" + uses: "actions/upload-artifact@v4" + with: + name: "pulp_docs_package" + path: | + dist/ + if-no-files-found: "error" + # retention-days: 5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 91117e2..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,25 +0,0 @@ -# workflow from: https://squidfunk.github.io/mkdocs-material/publishing-your-site/ - -name: ci -on: - push: - branches: - - master - - main - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - name: - run: | - pip install build - python -m build - pip install dist/*.whl - pulp-docs build - tree site diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..73c959a --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,25 @@ +name: "Docs" + +on: + workflow_call: + +jobs: + test: + runs-on: "ubuntu-20.04" + steps: + - uses: "actions/checkout@v4" + # - uses: "actions/cache@v4" + # with: + # path: "~/.cache/pip" + # key: "${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/*constraints.lock', '**/setup.py', '**/pyproject.toml') }}" + # restore-keys: | + # ${{ runner.os }}-pip- + - name: "Set up Python" + uses: "actions/setup-python@v5" + with: + python-version: "3.11" + - name: "Install Test Dependencies" + run: | + pip install -r doc_requirements.txt + - name: Build docs + run: make docs diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000..515c1f2 --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,71 @@ +name: "pulp-docs CI" + +on: + pull_request: + +concurrency: + group: "main-${{ github.ref_name }}-${{ github.workflow }}" + cancel-in-progress: true + +jobs: + build: + uses: "./.github/workflows/build.yml" + docs: + needs: + - "build" + uses: "./.github/workflows/docs.yml" + # lint: + # needs: + # - "build" + # uses: "./.github/workflows/lint.yml" + # test: + # needs: + # - "lint" + # uses: "./.github/workflows/test.yml" + # codeql: + # needs: + # - "lint" + # uses: "./.github/workflows/codeql.yml" + # check-commits: + # runs-on: "ubuntu-latest" + # steps: + # - uses: "actions/checkout@v4" + # with: + # fetch-depth: 0 + # - name: "Set up Python" + # uses: "actions/setup-python@v5" + # with: + # python-version: "3.11" + # - name: "Install python dependencies" + # run: | + # pip install toml pygithub + # - name: "Check commit message" + # env: + # GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + # GITHUB_CONTEXT: "${{ github.event.pull_request.commits_url }}" + # run: | + # for SHA in $(curl -H "Authorization: token $GITHUB_TOKEN" "$GITHUB_CONTEXT" | jq -r '.[].sha') + # do + # python .github/scripts/validate_commit_message.py "$SHA" + # VALUE=$? + # if [ "$VALUE" -gt 0 ]; then + # exit "$VALUE" + # fi + # done + # shell: "bash" + ready-to-ship: + # This is a dummy dependent task to have a single entry for the branch protection rules. + runs-on: "ubuntu-latest" + needs: + - "docs" + # - "check-commits" + # - "lint" + # - "test" + # - "codeql" + if: "always()" + steps: + - name: "Collect needed jobs results" + 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' + echo "CI says: Looks good!" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..da24910 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +build: + pyproject-build -n + +docs: + pulp-docs build + +.PHONY: build docs diff --git a/doc_requirements.txt b/doc_requirements.txt new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/doc_requirements.txt @@ -0,0 +1 @@ +. diff --git a/tests/fixtures/new_repo1 b/tests/fixtures/new_repo1 deleted file mode 160000 index 1a090a3..0000000 --- a/tests/fixtures/new_repo1 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 1a090a3bab4964898c05a972756092ae8afb6a25