The process of retrieving and validating commit messages within a Continuous Integration and Continuous Deployment (CI/CD) pipeline is a critical component of maintaining repository health and a legible project history. In a professional software engineering environment, the commit message is not merely a note to self but a permanent piece of documentation that explains the evolution of the codebase. When developers utilize GitHub Actions to automate the retrieval of these messages, they transition from manual oversight to systemic enforcement of quality standards. This automation ensures that every change introduced into the main branch is accompanied by a description that adheres to specific organizational or community standards, thereby reducing the cognitive load for future maintainers and streamlining the auditing process during security or stability reviews.
The technical challenge of getting a commit message within a GitHub Action often stems from the context of the event triggering the workflow. For instance, a push event provides a direct reference to the commit SHA, whereas a pull_request event provides a complex payload containing the head and base shafts. The ability to programmatically extract the commit message allows teams to implement sophisticated gates, such as ensuring that a commit message references a specific ticket number or follows a strict grammatical mood, before allowing a merge to proceed.
Mechanical Methods for Retrieving Commit Messages
Depending on the specific requirements of the workflow—whether it is a simple notification or a rigorous validation check—different technical approaches are utilized to extract the commit message from the Git history.
Direct Shell Execution via Git Log
One of the most straightforward methods for extracting the most recent commit message is the use of the git log command within a runner's shell environment. This approach is typically used when the workflow needs to capture the message of the most recent commit associated with a specific reference.
The implementation involves the following sequence of operations:
- Execution of the command
MSG=$(git log --format=%B -n 1 ${{github.event.after}})to capture the raw body of the commit message. - The
--format=%Bflag is critical as it ensures the entire raw commit message, including the subject and the body, is retrieved without metadata. - The
-n 1flag restricts the output to only the most recent commit, preventing the pollution of the variable with previous history. - The resulting string is then mapped to a GitHub environment variable using the command
echo "::set-env name=COMMIT_MESSAGE::${MSG}".
This method is highly effective for simple notifications. For example, a workflow can be configured to echo the commit SHA and the extracted message using echo "Commit SHA: ${{github.event.after}}, commit message: ${{env.COMMIT_MESSAGE}} (or ${COMMIT_MESSAGE})".
API-Driven Extraction via GitHub Script
For more complex scenarios, particularly those involving Pull Requests and Merge Groups, relying on the local Git clone may be insufficient or inefficient. The actions/github-script action provides a more robust, JavaScript-based interface to the GitHub REST API, allowing for precise extraction of commit data without needing to perform a full git checkout of the repository.
The logic for this extraction follows a hierarchical fallback mechanism to ensure the correct commit is targeted regardless of the event type:
- The script first attempts to retrieve the SHA from
context.payload.pull_request?.head?.sha, which is the primary target forpull_requestevents. - If the first check fails, it looks for
context.payload.merge_group?.head_sha, catering to merge group events. - As a final fallback, it utilizes
context.sha, which covers standardpush,workflow_dispatch, or other direct event contexts.
Once the reference is identified, the script calls the GitHub API via github.rest.repos.getCommit using the owner and repository names from the context. The extracted message is then passed to the workflow as an output:
javascript
const { data } = await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: context.payload.pull_request?.head?.sha
?? context.payload.merge_group?.head_sha
?? context.sha,
});
core.setOutput('value', data?.commit?.message);
Specialized Actions for Commit Message Validation
Beyond simply retrieving the message, there are dedicated GitHub Actions designed to enforce specific stylistic guidelines. These tools transform the extracted commit message into a pass/fail gate for the pipeline.
The Opinionated Commit Message Framework
The mristin/opinionated-commit-message action is designed to enforce a high-standard, professional style inspired by the guidelines of Chris Beams. This action does not just check for the presence of a message but validates its structural and linguistic integrity.
The enforced style guidelines include:
- Separation of the subject line from the body using a mandatory blank line.
- A strict limit of 50 characters for the subject line to ensure readability in git logs.
- Mandatory capitalization of the first letter of the subject line.
- A prohibition against ending the subject line with a period.
- The use of the imperative mood in the subject line (e.g., "Fix bug" instead of "Fixed bug").
- Wrapping the commit body at 72 characters to maintain compatibility with various git viewers.
- Focusing the body content on "what" and "why" rather than "how," as the "how" is already evident in the code diff.
To implement this, a workflow file such as .github/workflows/check-commit-message.yml is created. The action is invoked as follows:
yaml
- name: Check
uses: mristin/[email protected]
A significant technical hurdle in validating the imperative mood is the variety of the English language. To address this, the action utilizes a pre-compiled whitelist of frequent English verbs and common commit-related verbs. However, because no list can be exhaustive, some legitimate verbs may still trigger a failure, requiring manual override or list expansion.
Comparative Analysis of Validation Tools
While mristin/opinionated-commit-message focuses on linguistic style, other tools like commit-message-checker (by GsActions) and commit-check-action provide different levels of flexibility.
| Feature | Opinionated Commit Message | Commit Message Checker (GsActions) | Commit Check Action (v2) |
|---|---|---|---|
| Primary Focus | Linguistic/Style Guidelines | Regular Expression Matching | Conventional Commits/Branching |
| Imperative Mood Check | Yes (via whitelist) | No (too complex for RegEx) | Configurable via TOML |
| Branch Naming Check | No | No | Yes |
| Author Validation | No | No | Yes (Name and Email) |
| PR Integration | Yes (Title and Body) | Limited | Yes (Comments and Summary) |
| Configuration Method | Action Inputs | Regular Expressions | commit-check.toml or orcchk.toml |
Advanced Configuration and Implementation Strategies
Implementing commit message checks requires careful consideration of the workflow triggers and the permissions granted to the GitHub Actions runner.
Workflow Trigger Optimization
The behavior of commit message validation changes based on the trigger event. For the opinionated-commit-message action, the following triggers are recommended:
- Pull Request events:
opened,edited,reopened, andsynchronize. In this context, only the title and body of the pull request are checked. - Push events: Specified branches such as
masterordev/*. On push, every single commit message in the pushed set is verified.
To ensure that every commit within a pull request is checked—rather than just the PR title—the validate-pull-request-commits option must be set to true.
yaml
- name: Check
uses: mristin/[email protected]
with:
validate-pull-request-commits: 'true'
github-token: ${{ secrets.GITHUB_TOKEN }}
Permission and Security Requirements
When utilizing actions that interact with the GitHub API to retrieve commit messages, especially in private repositories, specific permissions are required. The default GITHUB_TOKEN is usually sufficient, but if the workflow has customized permissions, the contents: read scope must be explicitly defined.
In the case of the commit-check-action, additional permissions are required if the action is configured to post comments back to the pull request:
yaml
permissions:
contents: read
pull-requests: write
Technical Deep Dive into Commit-Check-Action v2
The commit-check/commit-check-action@v2 introduces a paradigm shift by moving configuration from YAML inputs to dedicated configuration files like commit-check.toml or orcchk.toml.
Breaking Changes in Version 2
The transition to v2 included several critical updates that developers must account for:
- Removal of direct inputs for
commit-signoff,merge-base, andimperative. These are now exclusively handled via the TOML configuration files. - Deprecation of
.commit-check.ymlin favor of the TOML format. - The default values for
author-nameandauthor-emailchecks were changed tofalseto align with the corecommit-checkdependency v2.0.0.
Comprehensive Input Reference
The commit-check-action offers a wide array of optional inputs to customize the validation process:
message: Checks if the commit message follows Conventional Commits (Default:true).branch: Validates the branch name against Conventional Branching standards (Default:true).author-name: Verifies the committer's name (Default:false).author-email: Verifies the committer's email (Default:false).job-summary: Generates a summary of the check results in the workflow run (Default:true).pr-comments: Posts the results directly to the PR comments (Default:false, experimental).
Integration with Local Tooling
While GitHub Actions provide server-side validation, the experience for the developer can be improved by using local tools. For users of GitHub Desktop, it is possible to implement a local check by saving a specific configuration (such as the one found in ffflorian/71de2e72a3788fbc63fa5ead8e3b5fde) to the local machine. This allows the developer to validate the message before it is ever pushed to the remote server, reducing the number of failed CI builds and the need for "fix commit message" commits.
Conclusion
The automation of commit message retrieval and validation represents a significant maturity milestone for any software project. By utilizing a combination of raw Git commands, API-driven scripts via actions/github-script, and specialized validators like mristin/opinionated-commit-message and commit-check-action, teams can ensure that their project history is a reliable, searchable, and professional record. The shift from simple regular expressions to complex linguistic analysis and TOML-based configurations allows for a highly granular control over the contribution process. Ultimately, the integration of these tools prevents the degradation of documentation quality and ensures that the "why" behind every code change is preserved for the lifetime of the software.