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
7 changes: 6 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ set -euo pipefail

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

"$repo_root/contrib/dev-tools/git/hooks/pre-commit.sh"
# Use human-friendly text format when stdout is a terminal; JSON for non-interactive / agent runs.
if [[ -t 1 ]]; then
"$repo_root/contrib/dev-tools/git/hooks/pre-commit.sh" --format=text
else
"$repo_root/contrib/dev-tools/git/hooks/pre-commit.sh" --format=json
fi
12 changes: 12 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

set -euo pipefail

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

# Use human-friendly text format when stdout is a terminal; JSON for non-interactive / agent runs.
if [[ -t 1 ]]; then
"$repo_root/contrib/dev-tools/git/hooks/pre-push.sh" --format=text
else
"$repo_root/contrib/dev-tools/git/hooks/pre-push.sh" --format=json
fi
22 changes: 16 additions & 6 deletions .github/agents/committer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,22 @@ Treat every commit request as a review-and-verify workflow, not as a blind reque
5. Check for obvious repository-policy violations in the diff (for example missing required spec
progress updates, missing documented rationale where required, or similar policy blockers).
If found, stop and return to the Implementer/Reviewer before committing.
6. Run `./contrib/dev-tools/git/hooks/pre-commit.sh` when feasible. For AI execution, use
`--format=json` first and retry with `--format=text --verbosity=verbose` if needed. If it fails:
- **You may fix**: formatting, linting, spell-check, import organization, and similar
metadata-only issues that are direct artifacts of the commit scope.
- **You must not fix**: build failures, test failures, logic errors, or runtime issues.
These are implementation defects; stop and return them to the **Implementer** to resolve.
6. **Check if the pre-commit git hook is already installed** before running checks manually:

```bash
[[ -x "$(git rev-parse --git-path hooks)/pre-commit" ]] && echo "installed" || echo "not installed"
```

- **If installed**: do NOT run the script manually — `git commit -S` will trigger it
automatically. Running it first would execute every check twice.
- **If not installed**: run `./contrib/dev-tools/git/hooks/pre-commit.sh` manually.
For AI execution, use `--format=json` first and retry with
`--format=text --verbosity=verbose` if needed. If it fails:
- **You may fix**: formatting, linting, spell-check, import organization, and similar
metadata-only issues that are direct artifacts of the commit scope.
- **You must not fix**: build failures, test failures, logic errors, or runtime issues.
These are implementation defects; stop and return them to the **Implementer** to resolve.

7. Propose a precise Conventional Commit message.
8. Create the commit with `git commit -S` only after the scope is clear and blockers are resolved.
9. After committing, run a quick verification check and report the resulting commit summary.
Expand Down
13 changes: 11 additions & 2 deletions .github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ automatically on every `git commit`. Install it once after cloning:
After installation the hook fires automatically; you do not need to invoke the script
manually before each commit.

> **For AI agents**: before invoking the script manually, check whether the hook is installed:
>
> ```bash
> [[ -x "$(git rev-parse --git-path hooks)/pre-commit" ]] && echo "installed" || echo "not installed"
> ```
>
> If installed, skip the manual run — `git commit` will trigger it automatically.
> Running both would execute every check twice.

## Automated Checks

> **⏱️ Expected runtime: ~1 minute** on a modern developer machine with warm caches.
Expand Down Expand Up @@ -68,12 +77,12 @@ Flag behavior:
- Duplicate `--format`/`--verbosity` flags: last value wins
- Invalid values or unknown flags exit with code `2` and print usage guidance to stderr
- In `--format=json`, structured output remains JSON regardless of verbosity value
- Per-step logs are written to `PRE_COMMIT_LOG_DIR` (default: `/tmp`)
- Per-step logs are written to `TORRUST_GIT_HOOKS_LOG_DIR` (default: `/tmp`)

For restricted agent environments that cannot write outside the workspace, run with:

```bash
PRE_COMMIT_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh
TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-commit.sh
```

The `.tmp/` directory is git-ignored.
Expand Down
113 changes: 113 additions & 0 deletions .github/skills/dev/git-workflow/run-pre-push-checks/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
name: run-pre-push-checks
description: Run all mandatory pre-push verification steps for the torrust-tracker project. Covers the pre-push script (automated checks), output modes, and log-directory configuration. Use before pushing or when running the comprehensive developer gate including nightly checks and E2E tests. Triggers on "pre-push checks", "run pre-push", "verify before push", or "push checks".
metadata:
author: torrust
version: "1.0"
---

# Run Pre-push Checks

## Git Hook (Recommended Setup)

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

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

After installation the hook fires automatically; you do not need to invoke the script
manually before each push.

> **For AI agents**: before invoking the script manually, check whether the hook is installed:
>
> ```bash
> [[ -x "$(git rev-parse --git-path hooks)/pre-push" ]] && echo "installed" || echo "not installed"
> ```
>
> If installed, skip the manual run — `git push` will trigger it automatically.
> Running both would execute every check twice.

## Automated Checks

> **⏱️ Expected runtime: ~15 minutes** on a modern developer machine with warm caches.
> AI agents should set a command timeout of **at least 30 minutes** before invoking
> `./contrib/dev-tools/git/hooks/pre-push.sh`.

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

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

The script runs these steps in order:

1. `cargo +stable machete` - unused dependency check
2. `linter all` - all linters (markdown, YAML, TOML, clippy, rustfmt, shellcheck, cspell)
3. `cargo +nightly fmt --check` - nightly format check
4. `cargo +nightly check ...` - nightly workspace check
5. `cargo +nightly doc ...` - nightly documentation build
6. `cargo +stable test --doc --workspace` - documentation tests
7. `cargo +stable test --tests --benches --examples --workspace --all-targets --all-features` - all tests
8. `cargo +stable run --bin e2e_tests_runner ...` - end-to-end tests

## Output Modes

The pre-push script supports concise human output, verbose human output, and JSON output for
automation.

```bash
# Default: text + concise
./contrib/dev-tools/git/hooks/pre-push.sh

# Explicit text + concise
./contrib/dev-tools/git/hooks/pre-push.sh --format=text --verbosity=concise

# Text + verbose streaming command output
./contrib/dev-tools/git/hooks/pre-push.sh --format=text --verbosity=verbose

# Compatibility alias
./contrib/dev-tools/git/hooks/pre-push.sh --format=text --verbose

# Structured output (single JSON document to stdout)
./contrib/dev-tools/git/hooks/pre-push.sh --format=json
```

Flag behavior:

- `--format=<text|json>` defaults to `text`
- `--verbosity=<concise|verbose>` defaults to `concise`
- `--verbose` is an alias for `--verbosity=verbose`
- Duplicate `--format`/`--verbosity` flags: last value wins
- Invalid values or unknown flags exit with code `2` and print usage guidance to stderr
- In `--format=json`, structured output remains JSON regardless of verbosity value
- Per-step logs are written to `TORRUST_GIT_HOOKS_LOG_DIR` (default: `/tmp`)

For restricted agent environments that cannot write outside the workspace, run with:

```bash
TORRUST_GIT_HOOKS_LOG_DIR=.tmp ./contrib/dev-tools/git/hooks/pre-push.sh
```

The `.tmp/` directory is git-ignored.
Because `.tmp/` is workspace-local, clean stale `pre-push-*.log` files periodically.
Comment thread
josecelano marked this conversation as resolved.

## Check Tier Ownership

Check ownership is intentionally split by gate:

- Pre-commit: fast local gate (`cargo machete`, `linter all`, `cargo test --doc --workspace`)
- Pre-push: comprehensive developer gate (nightly format/check/doc + stable tests + E2E)
- CI: merge authority with full validation and E2E matrix jobs

E2E is intentionally excluded from pre-commit and remains a pre-push/CI responsibility.

## Troubleshooting Output Modes

- Concise mode shows high-signal per-step summaries only. On failure, it prints the log path and
a short failure tail.
- Verbose mode streams full command output to the terminal. Use this for deep local debugging.
- JSON mode emits one structured document to stdout; diagnostics and usage errors go to stderr.
- If concise output is too short for debugging, re-run the same command with
`--format=text --verbosity=verbose`.
11 changes: 6 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,11 @@ Pre-commit defaults to concise text output and runs the fast local profile:
Use `--format=text --verbosity=verbose` for full streaming output, or `--format=json` for a
single structured JSON payload.

Pre-commit per-step logs are written to `PRE_COMMIT_LOG_DIR` (default: `/tmp`).
In restricted AI-agent sandboxes, set `PRE_COMMIT_LOG_DIR=.tmp` to keep temporary logs inside the
workspace (`.tmp/` is git-ignored).
When using `.tmp`, periodically clean old logs (for example, remove stale `pre-commit-*.log`
files) because OS-managed `/tmp` cleanup does not apply.
Both hooks write per-step logs to `TORRUST_GIT_HOOKS_LOG_DIR` (default: `/tmp`).
In restricted AI-agent sandboxes, set `TORRUST_GIT_HOOKS_LOG_DIR=.tmp` to keep temporary logs
inside the workspace for both hooks (`.tmp/` is git-ignored).
When using `.tmp`, periodically clean old logs (for example, remove stale `pre-commit-*.log` and
`pre-push-*.log` files) because OS-managed `/tmp` cleanup does not apply.

Gate ownership:

Expand All @@ -175,6 +175,7 @@ Primary skill references:

- `run-linters`: `.github/skills/dev/git-workflow/run-linters/SKILL.md`
- `run-pre-commit-checks`: `.github/skills/dev/git-workflow/run-pre-commit-checks/SKILL.md`
- `run-pre-push-checks`: `.github/skills/dev/git-workflow/run-pre-push-checks/SKILL.md`
- `setup-dev-environment`: `.github/skills/dev/maintenance/setup-dev-environment/SKILL.md`

Supporting docs:
Expand Down
10 changes: 6 additions & 4 deletions contrib/dev-tools/git/hooks/pre-commit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare -a STEPS=(
FORMAT="text"
VERBOSITY="concise"
FAILURE_TAIL_LINES=10
LOG_DIR="${PRE_COMMIT_LOG_DIR:-/tmp}"
LOG_DIR="${TORRUST_GIT_HOOKS_LOG_DIR:-/tmp}"

declare -a STEP_NAMES=()
Comment thread
josecelano marked this conversation as resolved.
declare -a STEP_COMMANDS=()
Expand Down Expand Up @@ -60,7 +60,7 @@ Options:
-h, --help Show this help

Environment:
PRE_COMMIT_LOG_DIR Directory for per-step log files. Default: /tmp
TORRUST_GIT_HOOKS_LOG_DIR Directory for per-step log files (shared by all git hooks). Default: /tmp
EOF
}

Expand Down Expand Up @@ -165,11 +165,13 @@ run_step() {

local safe_name
safe_name=$(sanitize_name_for_log "${description}")
local log_path
if ! log_path=$(mktemp "${LOG_DIR%/}/pre-commit-${safe_name}-XXXXXX"); then
local _tmp log_path
if ! _tmp=$(mktemp "${LOG_DIR%/}/pre-commit-${safe_name}-XXXXXX"); then
echo "Error: failed to create a temporary log file in '${LOG_DIR}'." >&2
return 2
fi
Comment thread
josecelano marked this conversation as resolved.
log_path="${_tmp}.log"
mv "$_tmp" "$log_path"

run_command "${command}" "${log_path}"
local command_exit_code=$?
Expand Down
Loading
Loading