Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ set -euo pipefail

repo_root="$(git rev-parse --show-toplevel)"

"$repo_root/scripts/pre-commit.sh"
"$repo_root/contrib/dev-tools/git/hooks/pre-commit.sh"
4 changes: 2 additions & 2 deletions .github/agents/committer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ Treat every commit request as a review-and-verify workflow, not as a blind reque

- Follow `AGENTS.md` for repository-wide behaviour and
`.github/skills/dev/git-workflow/commit-changes/SKILL.md` for commit-specific reference details.
- The pre-commit validation command is `./scripts/pre-commit.sh`.
- The pre-commit validation command is `./contrib/dev-tools/git/hooks/pre-commit.sh`.
- Create GPG-signed Conventional Commits (`git commit -S`).

## Required Workflow

1. Read the current branch, `git status`, and the staged or unstaged diff relevant to the request.
2. Summarize the intended commit scope before taking action.
3. Ensure the commit scope is coherent and does not accidentally mix unrelated changes.
4. Run `./scripts/pre-commit.sh` when feasible and fix issues that are directly related to the
4. Run `./contrib/dev-tools/git/hooks/pre-commit.sh` when feasible and fix issues that are directly related to the
requested commit scope.
5. Propose a precise Conventional Commit message.
6. Create the commit with `git commit -S` only after the scope is clear and blockers are resolved.
Expand Down
4 changes: 2 additions & 2 deletions .github/agents/implementer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Reference: [Beck Design Rules](https://martinfowler.com/bliki/BeckDesignRules.ht
## Repository Rules

- Follow `AGENTS.md` for repository-wide conventions.
- The pre-commit validation command is `./scripts/pre-commit.sh`.
- The pre-commit validation command is `./contrib/dev-tools/git/hooks/pre-commit.sh`.
- Relevant skills to load when needed:
- `.github/skills/dev/testing/write-unit-test/SKILL.md` — test naming and Arrange/Act/Assert pattern.
- `.github/skills/dev/rust-code-quality/handle-errors-in-code/SKILL.md` — error handling.
Expand Down Expand Up @@ -82,5 +82,5 @@ description of what was implemented. Do not commit directly — always delegate
- Do not implement more than was asked — scope creep is a defect.
- Do not suppress compiler warnings or clippy lints without a documented reason.
- Do not add dependencies without running `cargo machete` afterward.
- Do not commit code that fails `./scripts/pre-commit.sh`.
- Do not commit code that fails `./contrib/dev-tools/git/hooks/pre-commit.sh`.
- Do not skip the audit step, even for small changes.
10 changes: 5 additions & 5 deletions .github/skills/dev/git-workflow/commit-changes/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ This skill guides you through the complete commit process for the Torrust Tracke

```bash
# One-time setup: install the pre-commit Git hook
./scripts/install-git-hooks.sh
./contrib/dev-tools/git/install-git-hooks.sh

# Stage changes
git add <files>

# Commit with conventional format and GPG signature (MANDATORY)
# The pre-commit hook runs ./scripts/pre-commit.sh automatically
# The pre-commit hook runs ./contrib/dev-tools/git/hooks/pre-commit.sh automatically
git commit -S -m "<type>[(<scope>)]: <description>"
```

Expand Down Expand Up @@ -66,11 +66,11 @@ git commit -S -m "your commit message"

### Git Hook

The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh`
The repository ships a `pre-commit` Git hook that runs `./contrib/dev-tools/git/hooks/pre-commit.sh`
automatically on every `git commit`. Install it once after cloning:

```bash
./scripts/install-git-hooks.sh
./contrib/dev-tools/git/install-git-hooks.sh
```

Once installed, the hook fires on every commit and you do not need to run the script manually.
Expand All @@ -84,7 +84,7 @@ If the hook is not installed, run the script explicitly before committing.
> command timeout of **at least 5 minutes** before invoking this script.

```bash
./scripts/pre-commit.sh
./contrib/dev-tools/git/hooks/pre-commit.sh
```

The script runs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ metadata:

## Git Hook (Recommended Setup)

The repository ships a `pre-commit` Git hook that runs `./scripts/pre-commit.sh`
The repository ships a `pre-commit` Git hook that runs `./contrib/dev-tools/git/hooks/pre-commit.sh`
automatically on every `git commit`. Install it once after cloning:

```bash
./scripts/install-git-hooks.sh
./contrib/dev-tools/git/install-git-hooks.sh
```

After installation the hook fires automatically; you do not need to invoke the script
Expand All @@ -23,14 +23,14 @@ manually before each commit.
## Automated Checks

> **⏱️ Expected runtime: ~3 minutes** on a modern developer machine. AI agents must set a
> command timeout of **at least 5 minutes** before invoking `./scripts/pre-commit.sh`. Agents
> command timeout of **at least 5 minutes** before invoking `./contrib/dev-tools/git/hooks/pre-commit.sh`. Agents
> with a default per-command timeout below 5 minutes will likely time out and report a false
> failure.

Run the pre-commit script. **It must exit with code `0` before every commit.**

```bash
./scripts/pre-commit.sh
./contrib/dev-tools/git/hooks/pre-commit.sh
```

The script runs these steps in order:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ cargo install cargo-machete # Unused dependency checker
Install the project pre-commit hook (one-time, re-run after hook changes):

```bash
./scripts/install-git-hooks.sh
./contrib/dev-tools/git/install-git-hooks.sh
```

The hook runs `./scripts/pre-commit.sh` automatically on every `git commit`.
The hook runs `./contrib/dev-tools/git/hooks/pre-commit.sh` automatically on every `git commit`.

## Step 8: Smoke Test

Expand Down
4 changes: 2 additions & 2 deletions .github/skills/dev/maintenance/update-dependencies/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ cargo update 2>&1 | tee /tmp/cargo-update.txt
# If Cargo.lock has no changes, nothing to do — stop here.

# Verify
./scripts/pre-commit.sh
./contrib/dev-tools/git/hooks/pre-commit.sh

# Commit and push
git add Cargo.lock
Expand Down Expand Up @@ -92,7 +92,7 @@ cargo update --precise {old-version} {crate-name}

```bash
cargo machete
./scripts/pre-commit.sh
./contrib/dev-tools/git/hooks/pre-commit.sh
```

Fix any failures before proceeding.
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ on:
push:
paths:
- .github/workflows/copilot-setup-steps.yml
- scripts/install-git-hooks.sh
- scripts/pre-commit.sh
- contrib/dev-tools/git/install-git-hooks.sh
- contrib/dev-tools/git/hooks/pre-commit.sh
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml
- scripts/install-git-hooks.sh
- scripts/pre-commit.sh
- contrib/dev-tools/git/install-git-hooks.sh
- contrib/dev-tools/git/hooks/pre-commit.sh

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up
Expand Down Expand Up @@ -47,7 +47,7 @@ jobs:
run: cargo install cargo-machete

- name: Install Git pre-commit hooks
run: ./scripts/install-git-hooks.sh
run: ./contrib/dev-tools/git/install-git-hooks.sh

- name: Smoke-check — run all linters
run: linter all
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ native IPv4/IPv6 support, private/whitelisted mode, and a management REST API.
- `packages/` — Cargo workspace packages (all domain logic lives here; see package catalog below)
- `console/` — Console tools (e.g., `tracker-client`)
- `contrib/` — Community-contributed utilities (`bencode`) and developer tooling
- `contrib/dev-tools/` — Developer tools: git hooks (`pre-commit.sh`, `pre-push.sh`),
- `contrib/dev-tools/` — Developer tools: git hooks (`pre-commit.sh`, `pre-push.sh`, `install-git-hooks.sh`),
container scripts, and init scripts
- `tests/` — Integration tests (`integration.rs`, `servers/`)
- `docs/` — Project documentation, ADRs, issue specs, and benchmarking guides
Expand Down Expand Up @@ -127,7 +127,7 @@ All packages live under `packages/`. The workspace version is `3.0.0-develop`.
```sh
rustup show # Check active toolchain
rustup update # Update toolchain
rustup toolchain install nightly # Optional: only needed for manual cargo +nightly doc; the repo hook runs ./scripts/pre-commit.sh
rustup toolchain install nightly # Optional: needed for manual cargo +nightly commands and the repo pre-push checks (fmt/check/doc)
```

### Build
Expand Down
93 changes: 83 additions & 10 deletions contrib/dev-tools/git/hooks/pre-commit.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,83 @@
#!/bin/bash

cargo +nightly fmt --check &&
cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features &&
cargo +nightly doc --no-deps --bins --examples --workspace --all-features &&
cargo +nightly machete &&
cargo +stable build &&
CARGO_INCREMENTAL=0 cargo +stable clippy --no-deps --tests --benches --examples --workspace --all-targets --all-features -- -D clippy::correctness -D clippy::suspicious -D clippy::complexity -D clippy::perf -D clippy::style -D clippy::pedantic &&
cargo +stable test --doc --workspace &&
cargo +stable test --tests --benches --examples --workspace --all-targets --all-features
#!/usr/bin/env bash
# Pre-commit verification script
# Run all mandatory checks before committing changes.
#
# Usage:
# ./contrib/dev-tools/git/hooks/pre-commit.sh
#
# Expected runtime: ~3 minutes on a modern developer machine.
# AI agents: set a per-command timeout of at least 5 minutes before invoking this script.
#
# All steps must pass (exit 0) before committing.

set -euo pipefail

# ============================================================================
# STEPS
# ============================================================================
# Each step: "description|success_message|command"

declare -a STEPS=(
"Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo machete"
"Running all linters|All linters passed|linter all"
"Running documentation tests|Documentation tests passed|cargo test --doc --workspace"
"Running all tests|All tests passed|cargo test --tests --benches --examples --workspace --all-targets --all-features"
)

# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

format_time() {
local total_seconds=$1
local minutes=$((total_seconds / 60))
local seconds=$((total_seconds % 60))
if [ "$minutes" -gt 0 ]; then
echo "${minutes}m ${seconds}s"
else
echo "${seconds}s"
fi
}

run_step() {
local step_number=$1
local total_steps=$2
local description=$3
local success_message=$4
local command=$5

echo "[Step ${step_number}/${total_steps}] ${description}..."

local step_start=$SECONDS
local -a cmd_array
read -ra cmd_array <<< "${command}"
"${cmd_array[@]}"
local step_elapsed=$((SECONDS - step_start))

echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))"
echo
}

trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-commit checks failed!"; echo "Fix the errors above before committing."; echo "=========================================="; exit 1' ERR

# ============================================================================
# MAIN
# ============================================================================

TOTAL_START=$SECONDS
TOTAL_STEPS=${#STEPS[@]}

echo "Running pre-commit checks..."
echo

for i in "${!STEPS[@]}"; do
IFS='|' read -r description success_message command <<< "${STEPS[$i]}"
run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}"
done

TOTAL_ELAPSED=$((SECONDS - TOTAL_START))
echo "=========================================="
echo "SUCCESS: All pre-commit checks passed! ($(format_time "${TOTAL_ELAPSED}"))"
echo "=========================================="
echo
echo "You can now safely stage and commit your changes."
99 changes: 88 additions & 11 deletions contrib/dev-tools/git/hooks/pre-push.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,88 @@
#!/bin/bash

cargo +nightly fmt --check &&
cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features &&
cargo +nightly doc --no-deps --bins --examples --workspace --all-features &&
cargo +nightly machete &&
cargo +stable build &&
CARGO_INCREMENTAL=0 cargo +stable clippy --no-deps --tests --benches --examples --workspace --all-targets --all-features -- -D clippy::correctness -D clippy::suspicious -D clippy::complexity -D clippy::perf -D clippy::style -D clippy::pedantic &&
cargo +stable test --doc --workspace &&
cargo +stable test --tests --benches --examples --workspace --all-targets --all-features &&
cargo +stable run --bin e2e_tests_runner -- --config-toml-path "./share/default/config/tracker.e2e.container.sqlite3.toml"
#!/usr/bin/env bash
# Pre-push verification script
# Run comprehensive checks before pushing changes, including nightly toolchain
# validation and end-to-end tests.
#
# Usage:
# ./contrib/dev-tools/git/hooks/pre-push.sh
#
# Expected runtime: ~15 minutes on a modern developer machine.
# AI agents: set a per-command timeout of at least 30 minutes before invoking this script.
#
# All steps must pass (exit 0) before pushing.

set -euo pipefail

# ============================================================================
# STEPS
# ============================================================================
# Each step: "description|success_message|command"

declare -a STEPS=(
"Checking for unused dependencies (cargo machete)|No unused dependencies found|cargo +stable machete"
"Running all linters|All linters passed|linter all"
"Checking format with nightly toolchain|Nightly format check passed|cargo +nightly fmt --check"
"Checking workspace with nightly toolchain|Nightly check passed|cargo +nightly check --tests --benches --examples --workspace --all-targets --all-features"
"Building documentation with nightly toolchain|Nightly documentation built|cargo +nightly doc --no-deps --bins --examples --workspace --all-features"
"Running documentation tests|Documentation tests passed|cargo +stable test --doc --workspace"
"Running all tests|All tests passed|cargo +stable test --tests --benches --examples --workspace --all-targets --all-features"
"Running E2E tests|E2E tests passed|cargo +stable run --bin e2e_tests_runner -- --config-toml-path ./share/default/config/tracker.e2e.container.sqlite3.toml"
)

# ============================================================================
# HELPER FUNCTIONS
# ============================================================================

format_time() {
local total_seconds=$1
local minutes=$((total_seconds / 60))
local seconds=$((total_seconds % 60))
if [ "$minutes" -gt 0 ]; then
echo "${minutes}m ${seconds}s"
else
echo "${seconds}s"
fi
}

run_step() {
local step_number=$1
local total_steps=$2
local description=$3
local success_message=$4
local command=$5

echo "[Step ${step_number}/${total_steps}] ${description}..."

local step_start=$SECONDS
local -a cmd_array
read -ra cmd_array <<< "${command}"
"${cmd_array[@]}"
local step_elapsed=$((SECONDS - step_start))

echo "PASSED: ${success_message} ($(format_time "${step_elapsed}"))"
echo
}

trap 'echo ""; echo "=========================================="; echo "FAILED: Pre-push checks failed!"; echo "Fix the errors above before pushing."; echo "=========================================="; exit 1' ERR

# ============================================================================
# MAIN
# ============================================================================

TOTAL_START=$SECONDS
TOTAL_STEPS=${#STEPS[@]}

echo "Running pre-push checks..."
echo

for i in "${!STEPS[@]}"; do
IFS='|' read -r description success_message command <<< "${STEPS[$i]}"
run_step $((i + 1)) "${TOTAL_STEPS}" "${description}" "${success_message}" "${command}"
done

TOTAL_ELAPSED=$((SECONDS - TOTAL_START))
echo "=========================================="
echo "SUCCESS: All pre-push checks passed! ($(format_time "${TOTAL_ELAPSED}"))"
echo "=========================================="
echo
echo "You can now safely push your changes."
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Install project Git hooks from .githooks/ into .git/hooks/.
#
# Usage:
# ./scripts/install-git-hooks.sh
# ./contrib/dev-tools/git/install-git-hooks.sh
#
# Run once after cloning the repository. Re-run to update hooks after
# they change.
Expand Down
Loading