diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml new file mode 100644 index 0000000..e05e17a --- /dev/null +++ b/.github/workflows/build_and_test.yml @@ -0,0 +1,13 @@ +name: Build and Test + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: ./build_and_test diff --git a/.github/workflows/format_and_update_mdsnippets.yml b/.github/workflows/format_and_update_mdsnippets.yml new file mode 100644 index 0000000..0aa73d5 --- /dev/null +++ b/.github/workflows/format_and_update_mdsnippets.yml @@ -0,0 +1,19 @@ +name: Format and Update MDSnippets +on: + push: +jobs: + format_and_snippets: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Run format_and_update_mdsnippets + run: ./format_and_update_mdsnippets + - name: Git Commit and Push + uses: github-actions-x/commit@v2.9 + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" + commit-message: ". d format and update mdsnippets" + rebase: 'true' + push-branch: 'main' + name: GitHub Actions [bot] + email: actions@github.com diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/README.md b/README.md index 750dacc..8b6196d 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,16 @@ Changes that don't impact the code, but do change documentation around the code. The basic intention annotations are comprehensive to describe any kind of change, but it may be useful to extend the notation to your project to provide additional detail that is useful in your context. Read more about [Extension Intensions](Extension%20Intentions.md). +# Compliance validation + +You can validate that a commit message is valid, for example in a Git pre-commit hook, a GitHub Action, or GitLab's [Validate Commit Messages](https://docs.gitlab.com/user/project/repository/push_rules/#validate-commit-messages) by using the following regex: + + +```txt +^[.!^@] [a-zA-Z@]( .*)?$ +``` + + # Provable Refactorings [2]:#provable-refactorings diff --git a/build_and_test b/build_and_test new file mode 100755 index 0000000..3c83ec8 --- /dev/null +++ b/build_and_test @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -euo pipefail + +python3 -m unittest -v diff --git a/format_and_update_mdsnippets b/format_and_update_mdsnippets new file mode 100755 index 0000000..dd84436 --- /dev/null +++ b/format_and_update_mdsnippets @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail + +dotnet tool install --global MarkdownSnippets.Tool +mdsnippets . + +python3 -m pip install black +black . diff --git a/mdsnippets.json b/mdsnippets.json new file mode 100644 index 0000000..1434008 --- /dev/null +++ b/mdsnippets.json @@ -0,0 +1,5 @@ +{ + "Convention": "InPlaceOverwrite", + "WriteHeader": false, + "OmitSnippetLinks": true +} diff --git a/tools/__init__.py b/tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tools/compliance_regex.txt b/tools/compliance_regex.txt new file mode 100644 index 0000000..7d7fbf9 --- /dev/null +++ b/tools/compliance_regex.txt @@ -0,0 +1 @@ +^[.!^@] [a-zA-Z@]( .*)?$ diff --git a/tools/test__compliance_regex.py b/tools/test__compliance_regex.py new file mode 100644 index 0000000..e0a6459 --- /dev/null +++ b/tools/test__compliance_regex.py @@ -0,0 +1,43 @@ +import unittest + +import re +from pathlib import Path + +SCRIPT_DIR = Path(__file__).parent + +COMPLIANCE_REGEX = re.compile((SCRIPT_DIR / "compliance_regex.txt").read_text().strip()) + +MATCHING = [ + ". r rename variable", + "^ r rename variable", + "! r rename variable", + "@ r clean up a bunch of stuff", + "! F Add about page", + "! B Fix crash on startup", + ". a Format with prettier", + ". n No-op commit", + ". t Add missing tests", + "@ @ Checkpoint: work in progress", + ". e capture artifacts in CI", +] + +NONMATCHING_EXAMPLES = [ + "r rename variable", + ". rename variable", + ".r rename variable", + "! B Fix crash on startup", + ". rt rename variable in test", + "- r rename variable", + "Merge branch 'startup-crash'", + "WIP: diagnosing crash on startup", +] + + +class Tess(unittest.TestCase): + def test__matching(self): + for example in MATCHING: + self.assertTrue(COMPLIANCE_REGEX.match(example)) + + def test__nonmatching(self): + for example in NONMATCHING_EXAMPLES: + self.assertFalse(COMPLIANCE_REGEX.match(example))