diff --git a/README.md b/README.md index 578cd9a..f8d3e8b 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ commands: run: cmd: ./manage.py runserver test: + description: run unit tests for both backend and frontend cmd: - ./manage.py test - yarn test diff --git a/plz.yaml b/plz.yaml index 6500db9..2a5232f 100644 --- a/plz.yaml +++ b/plz.yaml @@ -1,24 +1,13 @@ commands: - publish: - cmd: - # Confirm we're on the master branch - - bash -c "git rev-parse --abbrev-ref HEAD | xargs -I {} bash -c '[ {} == master ] || (echo Please checkout master branch for publishing && exit 1)'" - # Confirm we're up to date with remote origin - - bash -c "git fetch origin; [ `git rev-list HEAD...origin/master --count` = 0 ] || (echo Please fetch latest commits from origin && exit 1)" - # Confirm there aren not any local, uncommitted changes - - bash -c "git diff-index --name-status --exit-code HEAD || (echo Please revert or PR local changes to origin && exit 1)" - # Confirm all tests are passing - - bash -c "plz test || (echo Please fix the tests and try again && exit 1)" - - poetry publish --build - # Create tag and push to remote origin - - bash -c "poetry version | awk '{print $2}' | xargs -I {} bash -c 'git tag -a {} -m {} && git push origin {}'" - test: + description: run unit tests cmd: - poetry run python -m pytest setup: + description: set up local development cmd: - poetry install - poetry run pre-commit install lint: + description: lint all files in the repo cmd: poetry run pre-commit run --all-files diff --git a/plz/main.py b/plz/main.py index fd63935..ae0978c 100644 --- a/plz/main.py +++ b/plz/main.py @@ -40,8 +40,8 @@ def execute_from_config(cmd, args): data = config["commands"].get(cmd, None) if data: - if "cmd" in data.keys(): - if "dir" in data.keys(): + if data.get("cmd"): + if data.get("dir"): cwd = os.path.join(cwd or "", data["dir"]) kwargs = { "cwd": cwd, @@ -52,9 +52,11 @@ def execute_from_config(cmd, args): ) if env: kwargs["env"] = env + if data.get("description"): + print_info("\n<{}> {}".format(cmd, data["description"])) rc = gather_and_run_commands(data["cmd"], **kwargs) sys.exit(rc) - if cmd and cmd.lower() == "help": + elif cmd and cmd.lower() == "help": if len(args) == 1: data = config["commands"].get(args[0], None) if data: diff --git a/plz/schema/v2.py b/plz/schema/v2.py index 2056c66..070b633 100644 --- a/plz/schema/v2.py +++ b/plz/schema/v2.py @@ -1,6 +1,6 @@ single_word_regex = "^[A-Za-z0-9_-]+$" -env_variable_dict = { +env_variables = { "type": "object", "patternProperties": {single_word_regex: {"type": "string"}}, "additionalProperties": False, @@ -15,7 +15,8 @@ {"type": "array", "items": {"type": "string"}}, ] }, - "env": env_variable_dict, + "env": env_variables, + "description": {"type": "string"}, }, "required": ["cmd"], "additionalProperties": False, @@ -29,7 +30,7 @@ "patternProperties": {single_word_regex: command_schema}, "additionalProperties": False, }, - "global_env": env_variable_dict, + "global_env": env_variables, }, "additionalProperties": False, } diff --git a/tests/main_test.py b/tests/main_test.py index 9cbfa40..5b14454 100644 --- a/tests/main_test.py +++ b/tests/main_test.py @@ -272,6 +272,68 @@ def test_execute_from_config_with_invalid_cmd_calls_list_options( mock_list.assert_called_with(mock_plz_config.return_value[0]) +@patch("sys.exit") +@patch("plz.main.plz_config") +def test_execute_from_config_prints_info_to_stdout(mock_plz_config, mock_exit, capfd): + # Arrange + config = {"commands": {"foo": {"cmd": "echo bar"}}} + mock_plz_config.return_value = (config, None) + + # Act + main.execute_from_config("foo", []) + out, err = capfd.readouterr() + + # Assert + assert ( + out + == textwrap.dedent( + """ + \x1b[36m\x1b[2m + =============================================================================== + Running command: echo bar + =============================================================================== + \x1b[0m + bar + + \x1b[36m\x1b[2m[INFO] Process complete\x1b[0m + """ + ).lstrip() + ) + + +@patch("sys.exit") +@patch("plz.main.plz_config") +def test_execute_from_config_prints_description_if_defined( + mock_plz_config, mock_exit, capfd +): + # Arrange + config = {"commands": {"foo": {"cmd": "echo bar", "description": "a description"}}} + mock_plz_config.return_value = (config, None) + + # Act + main.execute_from_config("foo", []) + out, err = capfd.readouterr() + + # Assert + assert ( + out + == textwrap.dedent( + """ + \x1b[36m + a description\x1b[0m + \x1b[36m\x1b[2m + =============================================================================== + Running command: echo bar + =============================================================================== + \x1b[0m + bar + + \x1b[36m\x1b[2m[INFO] Process complete\x1b[0m + """ + ).lstrip() + ) + + @pytest.mark.parametrize( "os_environ,global_env,cmd_env,expected_result", [ diff --git a/tests/schema_test.py b/tests/schema_test.py index fdcd00e..2b0cfb4 100644 --- a/tests/schema_test.py +++ b/tests/schema_test.py @@ -15,6 +15,7 @@ def get_sample_config(): "commands": { "test": { "cmd": "poetry run python -m pytest", + "description": "run unit tests", }, "setup": { "cmd": "poetry install",