diff --git a/.copier-answers.yml b/.copier-answers.yml index 8b129e3..f80c135 100644 --- a/.copier-answers.yml +++ b/.copier-answers.yml @@ -1,5 +1,5 @@ # Changes here will be overwritten by Copier -_commit: v1.6.1 +_commit: v1.6.3 _src_path: https://github.com/DeveloperC286/template project_name: conventional_commits_next_version uses_git: true diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml index 73b4fb6..178e4a7 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration.yml @@ -6,6 +6,19 @@ permissions: contents: read jobs: + permissions: + name: Permissions + runs-on: ${{ matrix.architecture }} + strategy: + matrix: + architecture: [ubuntu-24.04, ubuntu-24.04-arm] + language: [shell] + steps: + - name: Checkout code. + uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + - name: Check permissions. + run: make check-${{ matrix.language }}-permissions + formatting: name: Formatting runs-on: ${{ matrix.architecture }} @@ -27,7 +40,7 @@ jobs: strategy: matrix: architecture: [ubuntu-24.04, ubuntu-24.04-arm] - language: [rust, shell] + language: [rust, shell, python] steps: - name: Checkout code. uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 @@ -36,17 +49,20 @@ jobs: - name: Check linting. run: nix develop -c make check-${{ matrix.language }}-linting - scripts-permissions: - name: Scripts Permissions + dependencies: + name: Dependencies runs-on: ${{ matrix.architecture }} strategy: matrix: architecture: [ubuntu-24.04, ubuntu-24.04-arm] + language: [rust] steps: - name: Checkout code. uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - name: Check scripts permissions. - run: make check-scripts-permissions + - name: Setup Nix. + uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31.9.0 + - name: Check dependencies. + run: nix develop -c make check-${{ matrix.language }}-dependencies compile: name: Compile diff --git a/.github/workflows/conventional-commits.yml b/.github/workflows/conventional-commits.yml index 56eb9a6..9e43c89 100644 --- a/.github/workflows/conventional-commits.yml +++ b/.github/workflows/conventional-commits.yml @@ -10,7 +10,7 @@ jobs: name: Linting runs-on: ubuntu-24.04 container: - image: ghcr.io/developerc286/conventional_commits_linter:0.17.0@sha256:d6fb0dfd79c2e06897692bc3f0dc62bcb7ce90a92030c81a3137935516d525d7 + image: ghcr.io/developerc286/conventional_commits_linter:0.17.1@sha256:f1b947937ee884ba7f886d04939cd4858f9aeafb50dcf94925a516c50e43021b steps: - name: Checkout code. uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 diff --git a/.github/workflows/git-history.yml b/.github/workflows/git-history.yml index 476fc11..1b18abe 100644 --- a/.github/workflows/git-history.yml +++ b/.github/workflows/git-history.yml @@ -10,7 +10,7 @@ jobs: name: Clean runs-on: ubuntu-24.04 container: - image: ghcr.io/developerc286/clean_git_history:1.1.5@sha256:b1374591d48393f6b5fcc888f6bc7da05f7d218961f7850112130b1cad78186a + image: ghcr.io/developerc286/clean_git_history:1.1.6@sha256:93fd9c692f6e629956921b8d068ccad33760882b6e0c6d4d32cd963380aec25f steps: - name: Checkout code. uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 diff --git a/Cargo.toml b/Cargo.toml index f07e54b..05879ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,3 +40,6 @@ anyhow = "1.0.89" [dev-dependencies] # For parameterized testing. rstest = "=0.26.1" + +[package.metadata.cargo-machete] +ignored = ["strum"] diff --git a/Makefile b/Makefile index 9792a52..b2c0abb 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,10 @@ # Auto-detect musl target for static binaries (Linux only) +# Only set MUSL_TARGET on supported architectures; targets that need it will check MUSL_TARGET := $(shell uname -m | sed 's/^x86_64$$/x86_64-unknown-linux-musl/;s/^aarch64$$/aarch64-unknown-linux-musl/') -ifeq ($(filter %unknown-linux-musl,$(MUSL_TARGET)),) - $(error Unsupported architecture: $(shell uname -m). Static musl builds only supported on Linux x86_64 and aarch64) -endif + +define check-musl-target +$(if $(filter %unknown-linux-musl,$(MUSL_TARGET)),,$(error Unsupported architecture: $(shell uname -m). Static musl builds only supported on Linux x86_64 and aarch64)) +endef # Use --locked in CI to ensure reproducible builds CARGO_LOCKED := $(if $(CI),--locked,) @@ -10,34 +12,38 @@ CARGO_LOCKED := $(if $(CI),--locked,) .PHONY: default default: compile +.PHONY: check-shell-permissions +check-shell-permissions: + ./ci/check-scripts-permissions.sh + .PHONY: check-rust-formatting check-rust-formatting: cargo fmt --all -- --check --config=group_imports=StdExternalCrate -.PHONY: check-shell-formatting -check-shell-formatting: - shfmt --simplify --diff ci/* - -.PHONY: check-python-formatting -check-python-formatting: - autopep8 --exit-code --diff --aggressive --aggressive --max-line-length 120 --recursive end-to-end-tests/ - -.PHONY: check-yaml-formatting -check-yaml-formatting: - yamlfmt -verbose -lint -dstar .github/workflows/* - .PHONY: fix-rust-formatting fix-rust-formatting: cargo fmt --all -- --config=group_imports=StdExternalCrate +.PHONY: check-shell-formatting +check-shell-formatting: + shfmt --simplify --diff ci/* + .PHONY: fix-shell-formatting fix-shell-formatting: shfmt --simplify --write ci/* +.PHONY: check-python-formatting +check-python-formatting: + autopep8 --exit-code --diff --aggressive --aggressive --max-line-length 120 --recursive end-to-end-tests/ + .PHONY: fix-python-formatting fix-python-formatting: autopep8 --in-place --aggressive --aggressive --max-line-length 120 --recursive end-to-end-tests/ +.PHONY: check-yaml-formatting +check-yaml-formatting: + yamlfmt -verbose -lint -dstar .github/workflows/* + .PHONY: fix-yaml-formatting fix-yaml-formatting: yamlfmt -verbose -dstar .github/workflows/* @@ -50,13 +56,21 @@ check-rust-linting: check-shell-linting: shellcheck ci/*.sh +.PHONY: check-python-linting +check-python-linting: + ruff check --line-length 120 end-to-end-tests/ + +.PHONY: fix-python-linting +fix-python-linting: + ruff check --fix --line-length 120 end-to-end-tests/ + .PHONY: check-github-actions-workflows-linting check-github-actions-workflows-linting: actionlint -verbose -color -.PHONY: check-scripts-permissions -check-scripts-permissions: - ./ci/check-scripts-permissions.sh +.PHONY: check-rust-dependencies +check-rust-dependencies: + cargo machete .PHONY: compile compile: @@ -72,6 +86,7 @@ end-to-end-test: compile .PHONY: release release: + $(call check-musl-target) cargo build --release --target=$(MUSL_TARGET) --locked --verbose .PHONY: publish-binary diff --git a/end-to-end-tests/features/steps/assertions.py b/end-to-end-tests/features/steps/assertions.py index 344600a..baf7e6c 100644 --- a/end-to-end-tests/features/steps/assertions.py +++ b/end-to-end-tests/features/steps/assertions.py @@ -31,7 +31,7 @@ def assert_error_contains(result, error): def assert_error_matches_regex(result, regex): - assert regex.match(result.stderr) is not None, f"Expected standard error to match the regex.\n" + \ + assert regex.match(result.stderr) is not None, "Expected standard error to match the regex.\n" + \ f"Standard error = {result.stderr.encode()}.\n" + \ f"Regex = {regex.pattern.encode()}.\n" @@ -43,6 +43,6 @@ def assert_error_is_one_of(result, errors): def assert_next_version(result, expected_next_version): - assert result.stdout == expected_next_version, f"The next version was not what was expected.\n" + \ + assert result.stdout == expected_next_version, "The next version was not what was expected.\n" + \ f"Expected = {expected_next_version}.\n" + \ f"Actual = {result.stdout}\n" diff --git a/end-to-end-tests/features/steps/then.py b/end-to-end-tests/features/steps/then.py index 6b225ce..7e09c89 100644 --- a/end-to-end-tests/features/steps/then.py +++ b/end-to-end-tests/features/steps/then.py @@ -2,7 +2,16 @@ from behave import then from utilities import execute_conventional_commits_next_version -from assertions import * +from assertions import ( + assert_command_successful, + assert_command_unsuccessful, + assert_error_contains, + assert_error_equals, + assert_error_matches_regex, + assert_next_version, + assert_no_errors, + assert_no_output, +) @then('the returned version should be "{expected_next_version}".') diff --git a/flake.nix b/flake.nix index 9fcad95..5140649 100644 --- a/flake.nix +++ b/flake.nix @@ -40,15 +40,22 @@ buildInputs = [ # Rust with cross-compilation targets built-in. rustWithTargets - # Shell scripts. + # Shell formatting. pkgs.shfmt - pkgs.shellcheck - # GitHub Action Workflows. + # Python formatting. + pkgs.python313Packages.autopep8 + # YAML formatting. pkgs.yamlfmt + # Shell linting. + pkgs.shellcheck + # Python linting. + pkgs.ruff + # GitHub Actions workflows linting. pkgs.actionlint + # Rust dependencies check. + pkgs.cargo-machete # End to end tests. pkgs.python313 - pkgs.python313Packages.autopep8 pkgs.python313Packages.behave pkgs.git # Deploying.