diff --git a/.github/workflows/commit-check.yml b/.github/workflows/commit-check.yml new file mode 100644 index 0000000..a3400d0 --- /dev/null +++ b/.github/workflows/commit-check.yml @@ -0,0 +1,34 @@ +name: Conventional Commit Check for PR Title + +on: + workflow_call: + +jobs: + commit-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install commitlint + run: | + bun i -g @commitlint/cli + bun i -D @commitlint/config-conventional + + - name: Create commitlint config if missing + run: | + if [ ! -f .commitlintrc.json ] && [ ! -f .commitlintrc.js ] && [ ! -f .commitlintrc.yml ] && [ ! -f .commitlintrc.yaml ] && ! grep -q '"commitlint"' "package.json" 2>/dev/null; then + echo "extends:" > .commitlintrc.yml + echo " - '@commitlint/config-conventional'" >> .commitlintrc.yml + fi + + - name: Check PR title + if: github.event_name == 'pull_request' + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + echo "$PR_TITLE" | commitlint diff --git a/.github/workflows/markdown-check.yml b/.github/workflows/markdown-check.yml new file mode 100644 index 0000000..95f2147 --- /dev/null +++ b/.github/workflows/markdown-check.yml @@ -0,0 +1,23 @@ +name: Markdown Lint + +on: + workflow_call: + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install rumdl pre-compiled binary + # EXPECTED_SHA256 is obtained from `curl -sL $DOWNLOAD_URL | sha256sum` + run: | + DOWNLOAD_URL="https://github.com/rvben/rumdl/releases/download/v0.0.185/rumdl-v0.0.185-x86_64-unknown-linux-gnu.tar.gz" + EXPECTED_SHA256="5e6f28fa4935fb7d022c4f2d64f82b12206038d17e6570466afe7d7a3b135fba" + curl -sL $DOWNLOAD_URL -o /tmp/rumdl.tar.gz + echo "$EXPECTED_SHA256 /tmp/rumdl.tar.gz" | sha256sum -c - + tar -xzf /tmp/rumdl.tar.gz -C /usr/local/bin/ + chmod +x /usr/local/bin/rumdl + + - name: Lint Markdown + run: rumdl check --output-format github . diff --git a/.github/workflows/pr-checks-self.yml b/.github/workflows/pr-checks-self.yml new file mode 100644 index 0000000..af7576b --- /dev/null +++ b/.github/workflows/pr-checks-self.yml @@ -0,0 +1,9 @@ +name: PR Checks + +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + +jobs: + checks: + uses: ./.github/workflows/pr-checks.yml diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml new file mode 100644 index 0000000..1646fb4 --- /dev/null +++ b/.github/workflows/pr-checks.yml @@ -0,0 +1,55 @@ +name: PR Checks + +on: + workflow_call: + inputs: + run-prettier: + description: "Run Prettier check" + required: false + type: boolean + default: true + run-markdown: + description: "Run Markdown check" + required: false + type: boolean + default: true + run-commits: + description: "Run Commit check" + required: false + type: boolean + default: true + +jobs: + check-draft: + runs-on: ubuntu-latest + outputs: + should-run: ${{ steps.check.outputs.should-run }} + steps: + - id: check + run: | + if [ "${{ github.event_name }}" != "pull_request" ] || [ "${{ github.event.pull_request.draft }}" != "true" ]; then + echo "should-run=true" >> $GITHUB_OUTPUT + else + echo "should-run=false" >> $GITHUB_OUTPUT + fi + + prettier: + needs: check-draft + if: + needs.check-draft.outputs.should-run == 'true' && inputs.run-prettier != + false + uses: ./.github/workflows/prettier.yml + + markdown: + needs: check-draft + if: + needs.check-draft.outputs.should-run == 'true' && inputs.run-markdown != + false + uses: ./.github/workflows/markdown-check.yml + + commits: + needs: check-draft + if: + needs.check-draft.outputs.should-run == 'true' && inputs.run-commits != + false + uses: ./.github/workflows/commit-check.yml diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml new file mode 100644 index 0000000..fc9ca3f --- /dev/null +++ b/.github/workflows/prettier.yml @@ -0,0 +1,41 @@ +name: Prettier Check + +on: + workflow_call: + +jobs: + prettier: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check for Prettier config + run: | + CONFIG_FILES=".prettierrc .prettierrc.json .prettierrc.js .prettierrc.yaml .prettierrc.yml .prettierrc.toml prettier.config.js prettier.config.mjs" + HAS_CONFIG=false + + for file in $CONFIG_FILES; do + if [ -f "$file" ]; then + HAS_CONFIG=true + break + fi + done + + if [ "$HAS_CONFIG" = false ] && ! grep -q '"prettier"' "package.json" 2>/dev/null; then + echo "::error file=.prettierrc::No Prettier configuration file found." + echo "A Prettier config file is required to ensure consistent formatting across all developers." + echo "Without a shared config, each developer's local Prettier settings will differ, causing unnecessary formatting changes in commits." + echo "Please create a .prettierrc file in your repository root." + exit 1 + fi + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install Prettier + run: bun i -g prettier + + - name: Check formatting + run: prettier --check . diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..bd5535a --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..574245f --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "printWidth": 80, + "proseWrap": "always", + "singleQuote": false +} diff --git a/README.md b/README.md index 61ad4e5..56c8286 100644 --- a/README.md +++ b/README.md @@ -1 +1,157 @@ -# Github Actions +# GitHub Actions + +Shared GitHub Actions workflows for consistent code quality checks across +repositories. + +## Available Workflows + +This repository provides reusable workflows for: + +- **Prettier Check** - Validates code formatting with Prettier +- **Markdown Lint** - Lints Markdown files using rumdl +- **Conventional Commit Check for PR Title** - Validates PR titles follow + conventional commit format +- **PR Checks** - Combined workflow that runs all checks (or selected ones) with + draft PR handling + +## Usage + +### Option 1: Combined Workflow (Recommended for Simple Setup) + +Use the combined `pr-checks.yml` workflow to run all checks at once. This +workflow automatically handles draft PRs and runs all checks by default. + +#### Basic Usage + +Create `.github/workflows/pr-checks.yml` in your repository: + +```yaml +name: PR Checks + +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + +jobs: + checks: + uses: holdex/github-actions/.github/workflows/pr-checks.yml@main +``` + +#### Selective Checks + +To run only specific checks, pass input flags: + +```yaml +name: PR Checks + +on: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + +jobs: + checks: + uses: holdex/github-actions/.github/workflows/pr-checks.yml@main + with: + run-prettier: true + run-markdown: false # Skip markdown check + run-commits: true +``` + +### Option 2: Individual Workflows + +Use individual workflows for granular control over when each check runs. + +#### Prettier Check + +```yaml +name: Prettier Check + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + prettier: + uses: holdex/github-actions/.github/workflows/prettier.yml@main +``` + +**Requirements:** + +- Prettier configuration file (`.prettierrc`, `.prettierrc.json`, etc.) or + `prettier` config in `package.json` + +#### Markdown Lint + +```yaml +name: Markdown Lint + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + markdown: + uses: holdex/github-actions/.github/workflows/markdown-check.yml@main +``` + +#### Conventional Commit Check + +```yaml +name: Commit Check + +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + commits: + uses: holdex/github-actions/.github/workflows/commit-check.yml@main +``` + +**Requirements:** + +- Commitlint configuration file (`.commitlintrc.json`, etc.) or `commitlint` + config in `package.json` +- If no config exists, the workflow will create a default `.commitlintrc.json` + file + +## Workflow Details + +### PR Checks (`pr-checks.yml`) + +The combined workflow includes: + +- **Draft PR handling** - Automatically skips checks for draft PRs +- **Selective execution** - Control which checks run via inputs +- **Default behavior** - Runs all checks if no inputs specified + +**Inputs:** + +- `run-prettier` (boolean, default: `true`) - Run Prettier check +- `run-markdown` (boolean, default: `true`) - Run Markdown lint +- `run-commits` (boolean, default: `true`) - Run commit check + +### Prettier Check (`prettier.yml`) + +- Validates that a Prettier configuration exists +- Checks code formatting using Prettier +- Supports all Prettier-supported file types +- Uses Bun for package management + +### Markdown Lint (`markdown-check.yml`) + +- Uses `rumdl` v0.0.185 for fast Markdown linting +- Checks all Markdown files in the repository +- Reports issues with GitHub annotations + +### Conventional Commit Check (`commit-check.yml`) + +- Validates PR titles follow conventional commit format +- Creates default commitlint config if missing (requires `package.json`) +- Uses Bun for package management + +## Requirements + +- Node.js 22+ +- Bun (installed automatically in workflows) + - Uses the latest version of Bun diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..77405a7 --- /dev/null +++ b/bun.lock @@ -0,0 +1,15 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "github-actions", + "devDependencies": { + "prettier": "^3.7.4", + }, + }, + }, + "packages": { + "prettier": ["prettier@3.7.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA=="], + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..a34bd1e --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "github-actions", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "format": "prettier --write ." + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "prettier": "^3.7.4" + } +}