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
8 changes: 1 addition & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1 @@
{
"conventionalCommits.scopes": [
"conventional-commits",
"deps",
"CI-CD"
]
}
{}
142 changes: 22 additions & 120 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,138 +1,40 @@
# AGENTS.md - GitHub Actions
# AGENTS.md — action

## ⛔ CRITICAL RESTRICTIONS

- **NEVER execute `git push`** - The user will push manually after review
- **NEVER use GPT models** - Use Claude models only (claude-sonnet-4, Claude Opus 4.5)
- **Everything in English** - Code, comments, commits, documentation, logs, PR descriptions

## Organization Context

**helpers4** is a collection of open-source utilities across 5 repos: `typescript`, `devcontainer`, `action` (this repo), `website`, `.github`. All licensed LGPL-3.0.

## Commit Messages

Follow [Conventional Commits](https://www.conventionalcommits.org/) with a gitmoji between the scope and the description.

**Format:** `<type>(<scope>): <emoji> <description>`

**Scopes:** conventional-commits, CI-CD

| Type | Primary | Alternatives (gitmoji.dev) | When to use |
|------|---------|---------------------------|-------------|
| feat | ✨ | 🚸 UX, ♿️ a11y, 🌐 i18n, 💬 text/literals | New feature |
| fix | 🐛 | 🚑️ hotfix, 🔒️ security, 🩹 trivial, 🥅 errors, 🚨 warnings, ✏️ typo | Bug fix |
| docs | 📝 | 💡 source comments, 📄 license | Documentation |
| refactor | ♻️ | 🎨 structure, 🔥 remove code, ⚰️ dead code, 🚚 move/rename | Code refactoring |
| test | ✅ | 🧪 failing test, 💚 fix CI test | Tests |
| chore | 🔧 | 🙈 gitignore, 🔖 tag/release, 📌 pin deps, 🩺 healthcheck | Maintenance |
| perf | ⚡️ | — | Performance |
| style | 💄 | 🎨 code style | Code style / UI |
| ci | 👷 | 💚 fix CI | CI/CD |
| build | 📦️ | ➕ add dep, ➖ remove dep, ⬆️ upgrade dep, ⬇️ downgrade dep | Build system |
| revert | ⏪️ | — | Revert |

> Pick the **most specific** gitmoji that matches the change. The primary is the safe default; reach for an alternative when it adds real signal. Full list: https://gitmoji.dev

**Examples:**
- `feat(conventional-commits): ✨ add PR title validation`
- `fix(CI-CD): 🐛 fix checkout depth`
- `docs: 📝 update usage examples`

---
→ [Org-wide rules](https://github.com/helpers4/.dev/blob/main/AGENTS.md): restrictions · commit format · license headers

## This Repository

**Purpose:** Reusable GitHub Actions for the helpers4 organization and external users.

### Project Structure
**Purpose:** Reusable GitHub Actions published at `helpers4/action/<name>@v1`.

```
```text
action/
├── conventional-commits/
│ ├── action.yml # Action metadata and inputs
│ ├── README.md # Usage documentation
│ └── scripts/
│ └── validate.sh # Main validation logic
├── AGENTS.md # This file
├── LICENSE # LGPL-3.0
└── README.md
└── conventional-commits/
├── action.yml # composite action — inputs, outputs
├── README.md
└── scripts/
└── validate.sh # set -euo pipefail · inputs via INPUT_* env vars
```

### Conventional Commits Action
**conventional-commits action — key inputs:**

**Type:** Composite action (Bash)
| Input | Default | Notes |
| ----- | ------- | ----- |
| `base-sha` / `head-sha` | — | commit range to validate |
| `types` | `feat\|fix\|docs\|...` | pipe-separated regex |
| `scopes` | — | pipe-separated regex |
| `require-scope` | `false` | |
| `validate-pr-title` | `false` | |
| `pr-comment` | `none` | `none\|error\|success\|both` |

**Inputs:**
| Input | Default | Description |
|-------|---------|-------------|
| `checkout` | `true` | Run actions/checkout |
| `base-sha` | — | Base commit SHA |
| `head-sha` | — | Head commit SHA |
| `types` | `feat\|fix\|docs\|...` | Allowed commit types (pipe-separated regex) |
| `scopes` | — | Allowed scopes (pipe-separated regex) |
| `require-scope` | `false` | Require scope in every message |
| `ignore-commits` | — | Patterns to ignore (regex, newline-separated) |
| `validate-pr-title` | `false` | Also validate PR title |
| `pr-comment` | `none` | When to PR comment: none, error, success, both |
Output: `status` → `success` or `failure`.
SHA fallback chain: `GITHUB_BASE_REF` → `remotes/origin/$GITHUB_BASE_REF` → `main` → `master`.

**Output:** `status` — `success` or `failure`
**Adding a new action:** `<name>/action.yml` + `scripts/` + `README.md` + update root `README.md` + add shellcheck/test jobs to `pr-validation.yml` + add scope to `.vscode/settings.json`.

### Script Conventions

- Bash strict mode: `set -euo pipefail`
- Inputs via environment: `INPUT_BASE_SHA`, `INPUT_HEAD_SHA`, etc.
- Fallback logic: `GITHUB_BASE_REF` → `remotes/origin/$GITHUB_BASE_REF` → `main` → `master`
- Commits via `git rev-list`, each message validated individually
- Scope validation uses regex patterns

### Usage Example

```yaml
- name: Validate conventional commits
uses: helpers4/action/conventional-commits@v1
with:
base-sha: ${{ github.event.pull_request.base.sha }}
head-sha: ${{ github.event.pull_request.head.sha }}
types: 'feat|fix|refactor'
require-scope: true
```

### CI/CD Workflows

| Workflow | Trigger | Jobs |
|----------|---------|------|
| `pr-validation.yml` | Pull request → main | conventional-commits, shellcheck, test-action, pr-comment |

- **conventional-commits** — Validates PR commit messages against conventional commit format
- **shellcheck** — Lints `validate.sh` with ShellCheck
- **test-action** — Syntax check and basic validation of the action script
- **pr-comment** — Posts/updates a status summary comment on the PR

### Adding a New Action

1. Create `<action-name>/action.yml`
2. Create `<action-name>/scripts/` with implementation
3. Create `<action-name>/README.md`
4. Update root `README.md`
5. **Update `.github/workflows/pr-validation.yml`** — Add shellcheck/test jobs for the new action
6. Update this `AGENTS.md` (scopes + structure)

### License Header (required on all scripts)
**License header (all scripts):**

```bash
# This file is part of helpers4.
# Copyright (C) 2025 baxyz
# SPDX-License-Identifier: LGPL-3.0-or-later
```
## Repository Links

- TypeScript: https://github.com/helpers4/typescript
- DevContainer: https://github.com/helpers4/devcontainer
- Actions: https://github.com/helpers4/action
- Website: https://github.com/helpers4/website
- Organization: https://github.com/helpers4

## Questions?

If you need clarification on any aspect, open an issue or comment on the PR. We're here to help!
7 changes: 6 additions & 1 deletion conventional-commits/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ inputs:
description: "Allowed scopes (regex patterns, pipe-separated) - empty means all scopes allowed"
required: false
default: ""
scopes-file:
description: "Path to agnostic scopes JSON file (array) to auto-read when scopes input is empty — takes priority over vscode-settings"
required: false
default: "scopes.json"
vscode-settings:
description: "Path to VS Code settings.json to auto-read conventionalCommits.scopes when scopes input is empty"
description: "Path to VS Code settings.json to auto-read conventionalCommits.scopes when scopes input and scopes-file are both absent"
required: false
default: ".vscode/settings.json"
require-scope:
Expand Down Expand Up @@ -77,6 +81,7 @@ runs:
INPUT_HEAD_SHA: ${{ inputs.head-sha }}
INPUT_TYPES: ${{ inputs.types }}
INPUT_SCOPES: ${{ inputs.scopes }}
INPUT_SCOPES_FILE: ${{ inputs.scopes-file }}
INPUT_VSCODE_SETTINGS: ${{ inputs.vscode-settings }}
INPUT_REQUIRE_SCOPE: ${{ inputs.require-scope }}
INPUT_IGNORE_COMMITS: ${{ inputs.ignore-commits }}
Expand Down
11 changes: 10 additions & 1 deletion conventional-commits/scripts/validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ BASE_SHA="${INPUT_BASE_SHA:-}"
HEAD_SHA="${INPUT_HEAD_SHA:-}"
TYPES="${INPUT_TYPES:-feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert}"
SCOPES="${INPUT_SCOPES:-}"
SCOPES_FILE="${INPUT_SCOPES_FILE:-scopes.json}"
VSCODE_SETTINGS="${INPUT_VSCODE_SETTINGS:-.vscode/settings.json}"
REQUIRE_SCOPE="${INPUT_REQUIRE_SCOPE:-false}"
IGNORE_COMMITS="${INPUT_IGNORE_COMMITS:-}"
VALIDATE_PR_TITLE="${INPUT_VALIDATE_PR_TITLE:-false}"
PR_COMMENT="${INPUT_PR_COMMENT:-error}"

# Auto-read scopes from VS Code settings if not explicitly provided
# Priority: scopes (explicit) > scopes-file > vscode-settings
if [[ -z "$SCOPES" && -f "$SCOPES_FILE" ]]; then
FILE_SCOPES=$(jq -r '.[]' "$SCOPES_FILE" | paste -sd '|' || echo "")
if [[ -n "$FILE_SCOPES" ]]; then
echo "Auto-detected scopes from $SCOPES_FILE: $FILE_SCOPES"
SCOPES="$FILE_SCOPES"
fi
fi

if [[ -z "$SCOPES" && -f "$VSCODE_SETTINGS" ]]; then
# Strip JSONC line comments (// ...) and trailing commas before parsing with jq
VSCODE_SCOPES=$(sed 's|//[^"]*$||g; s|,\s*\([}\]]\)|\1|g' "$VSCODE_SETTINGS" \
Expand Down
5 changes: 5 additions & 0 deletions scopes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[
"conventional-commits",
"deps",
"CI-CD"
]