A CLI tool to validate changeset approvals.
Project description
Approval Validator
A CLI to validate that sufficient approvals have been received for a changeset in the context of a project.
Table of Contents
Installation
The quickest way to use the tool in anger is to install it using pip
:
pip install approvals-validator
.
Alternatively, run the executable from the project root. Install dependencies
with bin/setup
.
Usage
% validate_approvals --help Usage: validate_approvals REQUIRED_FLAGS Validate that the correct approvals have been received to approve changes to the given files. Note: Multiple approvers and/or changed files can be passed as CSV strings. Example: validate_approvals --approvers alovelace,eclarke --changed-files src/com/twitter/follow/Follow.java Options: -a, --approvers USERNAMES Username(s) of approvals. [required] -c, --changed-files FILE_PATHS File paths. [required] -h, --help Show this message and exit.
Requirements
- Python >= 3.8.0 (for
functools.cached_property
)
A .tool-versions
file is included for asdf users.
Dependencies
The test-runner script (./test
) will attempt to install dependencies in a
virtualenv at project root named ./env
.
For reference, bin/setup
usage instructions:
Usage: ./bin/setup [OPTIONS] ENV Install dependencies for `validate_approvals` in a virtualenv at project root. Available environments: dev Install all dependencies prod Install minimal dependencies for running `validate_approvals` test Install minimal and test dependencies Available options: --silent Run without verbose output
Tests
A test runner script is included to run the entire test suite and display code
coverage metrics. Pass the --docker
flag to (re-)build a Docker image and
run tests with Docker.
Acceptances tests are written in Bash script, unit and integration tests in Python with pytest.
% ./test Running acceptance tests... ./validate_approvals -c data/minimal/y/file -a B ./validate_approvals -c data/minimal/y/file -a A,C ./validate_approvals -c data/minimal/y/file -a D ./validate_approvals --approvers alovelace,ghopper --changed-files data/repo/src/com/twitter/follow/Follow.java,data/repo/src/com/twitter/user/User.java ./validate_approvals --approvers alovelace --changed-files data/repo/src/com/twitter/follow/Follow.java ./validate_approvals --approvers eclarke --changed-files data/repo/src/com/twitter/follow/Follow.java ./validate_approvals --approvers alovelace,eclarke --changed-files data/repo/src/com/twitter/follow/Follow.java ./validate_approvals --approvers mfox --changed-files data/repo/src/com/twitter/tweet/Tweet.java Running pytest tests... Running mypy on 11 files... done with status 0 Success: no issues found in 11 source files ............................... [100%] ---------- coverage: platform darwin, python 3.8.0-final-0 ----------- Name Stmts Miss Cover ------------------------------------------------------------------------ approval_validator/__init__.py 3 0 100% approval_validator/change_set.py 14 14 0% approval_validator/changed_directory.py 30 0 100% approval_validator/cli_utils.py 14 14 0% approval_validator/exceptions.py 9 2 78% approval_validator/file_utils.py 74 0 100% approval_validator/tests/__init__.py 0 0 100% approval_validator/tests/changed_directory_test.py 37 0 100% approval_validator/tests/file_utils_test.py 59 4 93% ------------------------------------------------------------------------ TOTAL 240 34 86%
Design Notes
The script entrypoint is the CLI function in the executable
validate_approvals
.
The approval_validator.cli_utils
module defines how arguments are parsed.
ChangeSet
, ChangedDirectory
The main classes are ChangeSet
and ChangedDirectory
.
The former models an entire changeset (i.e., all the files passed via the
--changed-files
flag), the latter each individual entry in the list of files
passed to --changed_files
.
# approval_validator/changed_directory.py L24-37 @cached_property def affected_directories(self) -> Tuple[Path, ...]: return util.find_dependent_dirs(self.directory) @cached_property def approved(self) -> bool: """ Return true if sufficient approval has been received for this ChangedDirectory. """ for impacted_dir in self.impacted_directories: if not self.__change_approved(impacted_dir): return False return True
file_utils
File-parsing and directory-traversal logic is housed in the file_utils
module.
exceptions
Defines ApprovalValidatorError
, the base class for library-specific
exceptions, and ProjectRootNotFoundError
, which is raised when a project root
can't be found.
# approval_validator/exceptions.py L8-20 class ProjectRootNotFoundError(ApprovalValidatorError): """Raised when a project root can't be found.""" def __init__(self, start_dir): self.start_dir = start_dir def __str__(self): message = f""" Project root search failed. Started from: {self.start_dir} Note: We detect the presence of a project root using the entries of PROJECT_ROOT_FILES. (see: approval_validator/file_utils.py) """ return f"\n\n{cleandoc(message)}"
Performance
Caching improved running time by ~20%. The following facilities are used:
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size approvals_validator-0.2.1-py3-none-any.whl (11.5 kB) | File type Wheel | Python version py3 | Upload date | Hashes View |
Filename, size approvals_validator-0.2.1.tar.gz (10.0 kB) | File type Source | Python version None | Upload date | Hashes View |
Hashes for approvals_validator-0.2.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 82e5877ec7db08613bb90a441e4fe7de40c06ddf65b5bafa892810554a2d15ed |
|
MD5 | dfd749877262b3de4a41dc49b7f7d0b5 |
|
BLAKE2-256 | e20da15de8757cd4f94db3d2dec131e20940092ef9607f78842428394b85096e |
Hashes for approvals_validator-0.2.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | a586d140fc494f12bcdc6b4c7797d00d6afd908cd22bfacda7f9f3d630f9f81d |
|
MD5 | a0c67faf7fc7004c5abd1015f2632664 |
|
BLAKE2-256 | 4af7b8de50124ab74bd3aea7654a02ca81dc2a2be6c922ffb927d9283ea72a72 |