Skip to content

feat(groq): GitHub Action that validates pull request titles against a configurable regex pattern and fails the workflow if they do not conform.#4256

Open
polsala wants to merge 1 commit intomainfrom
ai/groq-20260418-1859
Open

feat(groq): GitHub Action that validates pull request titles against a configurable regex pattern and fails the workflow if they do not conform.#4256
polsala wants to merge 1 commit intomainfrom
ai/groq-20260418-1859

Conversation

@polsala
Copy link
Copy Markdown
Owner

@polsala polsala commented Apr 18, 2026

Implementation Summary

  • Utility: nightly-pr-title-linter
  • Provider: groq
  • Location: github-actions/nightly-nightly-pr-title-linter
  • Files Created: 4
  • Description: GitHub Action that validates pull request titles against a configurable regex pattern and fails the workflow if they do not conform.

Rationale

  • Automated proposal from the Groq generator delivering a fresh community utility.
  • This utility was generated using the groq AI provider.

Why safe to merge

  • Utility is isolated to github-actions/nightly-nightly-pr-title-linter.
  • README + tests ship together (see folder contents).
  • No secrets or credentials touched.
  • All changes are additive and self-contained.

Test Plan

  • Follow the instructions in the generated README at github-actions/nightly-nightly-pr-title-linter/README.md
  • Run tests located in github-actions/nightly-nightly-pr-title-linter/tests/

Links

  • Generated docs and examples committed alongside this change.

Mock Justification

  • Not applicable; generator did not introduce new mocks.

…a configurable regex pattern and fails the workflow if they do not conform.
@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Apr 18, 2026

🤖 Review by GROQ Agent

✅ What's solid

  • Isolation & Scope – The action lives in its own directory (github-actions/nightly‑nightly‑pr‑title‑linter) and does not touch any existing code‑base.
  • Composite Action – Using a composite action keeps the runtime lightweight (no Docker, no extra dependencies beyond the runner‑provided bash and jq).
  • Error handling – The script checks for the presence of GITHUB_EVENT_PATH and jq, and fails with a clear ::error:: annotation when something is missing or the title cannot be extracted.
  • Fail‑fast semanticsset -euo pipefail guarantees that any unexpected command failure aborts the step, which is exactly what you want in a CI lint.
  • Test coverage – The test suite validates both a matching and a non‑matching title, exercising the two primary code paths.
  • Documentation – The README explains the purpose, usage, inputs, and how to run the tests locally.

🧪 Tests

Observation Recommendation
Tests cover the happy‑path and the failure‑path for title matching. Add a few more edge‑case tests to make the suite more robust:
Missing GITHUB_EVENT_PATH – ensure the script exits with the expected error message.
jq not installed – simulate the missing binary (e.g., PATH="") and verify the proper error.
Malformed JSON payload – feed an invalid JSON file and assert that the script fails gracefully.
Invalid regex pattern – pass a pattern that Bash cannot compile (e.g., an unbalanced bracket) and confirm the script reports a useful error rather than a cryptic Bash message.
Pattern with spaces or special characters – verify that patterns like ^feat:\s.+$ work as intended.
Cross‑platform sed -i – the current test uses GNU sed. Consider using sed -i '' on macOS or rely on perl -pe for portability, or simply write the JSON file directly without sed.
Test runner – wrap the test script in a CI job (e.g., runs-on: ubuntu-latest) to guarantee the environment matches the action’s runtime.
Assertions – instead of relying on exit codes alone, capture the script’s stdout/stderr and assert that the expected ::error:: annotation appears for failing cases.

🔒 Security

  • No secret handling – The action does not read or write any secrets, which is good.

  • Pattern injection – The regex pattern comes from an input (INPUT_PATTERN). Bash’s [[ … =~ … ]] treats the right‑hand side as a regular expression, not as code, so there’s no command injection risk. Still, a malformed pattern can cause the script to error out. Consider validating the pattern before use, e.g.:

    if ! [[ "$pattern" =~ ^[[:print:]]+$ ]]; then
      echo "::error::Provided pattern contains non‑printable characters"
      exit 1
    fi
  • Dependency on jqjq is part of the default GitHub runner, but if a self‑hosted runner uses a custom image, make sure jq is installed or document the requirement.

  • File handling – Temporary files created by the test suite are removed at the end of the script, preventing leftover data on the runner.

🧩 Docs / Developer Experience

  • Usage snippet typo – The README shows uses: ./nightly-pr-title-linter while the actual directory is nightly-nightly-pr-title-linter. Align the path to avoid confusion.
  • Regex flavour description – The README claims the pattern follows “ECMAScript syntax”. Bash’s [[ … =~ … ]] uses POSIX extended regular expressions, which differ (e.g., no look‑behinds). Update the docs to reflect the actual flavour or, if you truly need ECMAScript, switch to node -e or grep -P.
  • Versioning / Release – Consider adding a vX.Y.Z tag and a CHANGELOG.md entry so downstream users can pin a stable version.
  • License – Adding an open‑source license file (e.g., MIT) clarifies reuse rights.
  • Contribution guidelines – Even for a tiny utility, a short CONTRIBUTING.md (or a note in the README) helps external contributors know how to run tests and submit improvements.
  • Output documentation – The README mentions “no explicit outputs”, which is fine, but you could still expose a boolean output (matched: true/false) for downstream steps that might want to react programmatically.

🧱 Mocks / Fakes

  • The test suite already creates mock GITHUB_EVENT_PATH JSON files on‑the‑fly, which is a clean approach.
  • For more complex scenarios (e.g., testing the action as a whole within a workflow), you could add a workflow‑level integration test that uses the actions/github-script or act to simulate a PR event and verify that the step fails/succeeds as expected. This would give confidence that the composite action wiring (action.ymlsrc/lint.sh) works on a real runner.

Overall, the implementation is solid and functional. The suggestions above focus on tightening edge‑case handling, improving documentation accuracy, and expanding test coverage to make the utility more resilient and easier for others to adopt.

@polsala
Copy link
Copy Markdown
Owner Author

polsala commented Apr 18, 2026

🤖 Review by GEMINI Agent

✅ What's solid

  • The action's core functionality is well-defined and addresses a common need for PR title consistency.
  • The implementation as a composite action running a Bash script (src/lint.sh) is lightweight and efficient.
  • Robust shell scripting practices are employed in lint.sh, including set -euo pipefail for error handling and early exit.
  • The action correctly handles the absence of GITHUB_EVENT_PATH and the jq utility, providing clear error messages.
  • The use of jq for extracting the PR title from the event payload is standard and reliable.

🧪 Tests

  • The test_lint.sh script provides good coverage for both matching and non-matching PR titles against a given pattern.
  • The approach of creating temporary mock GITHUB_EVENT_PATH JSON files for testing is effective for isolating the action's logic.
  • Actionable feedback:
    • The test script currently relies on PWD to locate src/lint.sh. For improved robustness and portability, consider using $(dirname "$0")/../src/lint.sh to reference the script relative to the test file itself.
    • The sed -i command used within create_event for escaping the title might have portability issues across different sed implementations (e.g., macOS sed requires a backup extension). A more portable way to inject the title into the JSON could involve jq directly, for example:
      create_event() {
        local title="$1"
        local file="$2"
        jq --arg title "$title" '.pull_request.title = $title' <<<'{ "pull_request": { "title": "" } }' > "$file"
      }
    • Add a test case to explicitly verify the action's behavior when the default pattern (.*) is used, ensuring it always passes.
    • Include a test case for an empty or null PR title to confirm the error handling in lint.sh functions as expected.

🔒 Security

  • The action is self-contained, additive, and does not interact with secrets or credentials, minimizing its attack surface.
  • The lint.sh script's use of set -euo pipefail contributes to a more secure execution environment by preventing unexpected behavior.
  • The pattern input is used directly in Bash's =~ operator, which treats the input as a regular expression pattern rather than executable code, mitigating direct command injection risks.
  • Actionable feedback:
    • While Bash's =~ is generally safe, user-supplied regular expressions, especially complex ones, can potentially lead to Regular Expression Denial of Service (ReDoS) if the pattern is pathologically inefficient. Consider adding a note in the documentation about this potential risk and advising users to use well-formed and efficient regex patterns.

🧩 Docs/DX

  • The README.md is comprehensive, clearly explaining the action's purpose, usage, and development guidelines.
  • The usage example in the README.md is clear and practical, demonstrating how to configure the pattern input.
  • The action.yml is well-structured and provides clear descriptions for the action and its inputs.
  • Actionable feedback:
    • The README.md states that the pattern input uses "ECMAScript syntax." Bash's =~ operator uses Extended Regular Expressions (ERE), which are largely compatible but not strictly identical to ECMAScript regex. To avoid potential confusion, it would be more accurate to specify "Extended Regular Expression (ERE) syntax" or "Bash ERE syntax."
    • In the README.md usage example, consider pinning actions/checkout to a specific commit SHA (e.g., actions/checkout@b4ffde65f46336ab88eb5afa53ea30b89885a96) instead of a major version (@v3) for enhanced security and reproducibility, which is a common GitHub Actions best practice.
    • The naming convention nightly-nightly-pr-title-linter in the path is a bit redundant. While generated, consider if nightly-pr-title-linter or simply pr-title-linter would be clearer for users.

🧱 Mocks/Fakes

  • The PR body states "Not applicable; generator did not introduce new mocks."
  • Actionable feedback:
    • The test_lint.sh script explicitly creates mock GITHUB_EVENT_PATH JSON files to simulate the GitHub Actions environment. This constitutes effective mocking for testing purposes. It would be more accurate to acknowledge these test-specific mocks in the PR's "Mock Justification" section, clarifying that while no new application-level mocks were introduced, the test suite does utilize environmental mocks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant