-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from aj3sh/github-actions
feat: added support for github actions
- Loading branch information
Showing
5 changed files
with
307 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: Commitlint | ||
|
||
on: | ||
push: | ||
branches: ["main"] | ||
pull_request: | ||
|
||
jobs: | ||
commitlint: | ||
runs-on: ubuntu-latest | ||
name: Check commit messages | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Run commitlint | ||
uses: ./ # Uses an action in the root directory | ||
# or use a released GitHub Action | ||
# uses: opensource-nepal/[email protected] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,67 @@ | ||
# commitlint | ||
|
||
commitlint is is a pre-commit hook designed to lint your commit messages according to the [Conventional Commits](https://www.conventionalcommits.org/) standard. | ||
commitlint is a tool designed to lint your commit messages according to the [Conventional Commits](https://www.conventionalcommits.org/) standard for your pre-commit hook and GitHub Actions. | ||
|
||
## How to use | ||
|
||
### For pre-commit | ||
|
||
1. Add the following configuration on `.pre-commit-config.yaml`. | ||
|
||
```yaml | ||
repos: | ||
... | ||
```yaml | ||
repos: | ||
... | ||
|
||
- repo: https://github.com/opensource-nepal/commitlint | ||
rev: 0.1.0 | ||
hooks: | ||
- id: commitlint | ||
- repo: https://github.com/opensource-nepal/commitlint | ||
rev: 0.1.0 | ||
hooks: | ||
- id: commitlint | ||
|
||
... | ||
``` | ||
... | ||
``` | ||
|
||
2. Install the `commit-msg` hook in your project repo: | ||
|
||
```bash | ||
pre-commit install --hook-type commit-msg | ||
``` | ||
```bash | ||
pre-commit install --hook-type commit-msg | ||
``` | ||
|
||
> **_NOTE:_** Installing using only `pre-commit install` will not work. | ||
|
||
### For github-actions | ||
|
||
If you have any existing workflows, add the following steps: | ||
|
||
```yaml | ||
steps: | ||
... | ||
- name: Run commitlint | ||
uses: opensource-nepal/[email protected] | ||
... | ||
``` | ||
|
||
If you don't have any workflows, create a new GitHub workflow, e.g. `.github/workflows/commitlint.yaml`. | ||
|
||
```yaml | ||
name: Commitlint | ||
on: | ||
push: | ||
branches: ['main'] | ||
pull_request: | ||
jobs: | ||
commitlint: | ||
runs-on: ubuntu-latest | ||
name: Check commit messages | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Run commitlint | ||
uses: opensource-nepal/[email protected] | ||
``` | ||
|
||
> **_NOTE:_** Installing just using `pre-commit install` will not work. | ||
> **_NOTE:_** commitlint GitHub Actions will only be triggered by "push" or "pull_request" events. | ||
|
||
## Contribution | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
name: "commitlint" | ||
description: "A GitHub Action to check conventional commit message" | ||
runs: | ||
using: "composite" | ||
steps: | ||
- name: Install Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: "3.8" | ||
|
||
- name: Install Commitlint | ||
run: python -m pip install -e ${{ github.action_path }} | ||
shell: bash | ||
|
||
# checkout to the source code | ||
# for push event | ||
- name: Get pushed commit count | ||
if: github.event_name == 'push' | ||
id: push_commit_count | ||
run: | | ||
echo "count=$(echo '${{ toJson(github.event.commits) }}' | jq '. | length')" \ | ||
>> $GITHUB_OUTPUT | ||
shell: bash | ||
- name: Checkout to pushed commits | ||
if: github.event_name == 'push' | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.sha }} | ||
fetch-depth: ${{ steps.push_commit_count.outputs.count }} | ||
|
||
# for pull_request event | ||
- name: Checkout to PR source branch | ||
if: github.event_name == 'pull_request' | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.event.pull_request.head.sha }} | ||
fetch-depth: ${{ github.event.pull_request.commits }} | ||
|
||
# checking the commits (for both push and pull_request) | ||
- name: Check the commits | ||
id: commitlint | ||
run: python ${{ github.action_path }}/github_actions/run.py | ||
shell: bash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
""" | ||
This module defines the `GithubEvent` class for handling GitHub event details. | ||
Note: | ||
This module relies on the presence of specific environment variables | ||
set by GitHub Actions. | ||
""" | ||
import json | ||
import os | ||
from typing import Any, Dict | ||
|
||
|
||
# pylint: disable=R0902; Too many instance attributes | ||
class GithubEvent: | ||
"""Class representing GitHub events. | ||
This class provides methods for loading and accessing various details of | ||
GitHub events. | ||
Attributes: | ||
event_name (str): The name of the GitHub event. | ||
sha (str): The commit SHA associated with the event. | ||
ref (str): The Git reference (branch or tag) for the event. | ||
workflow (str): The name of the GitHub workflow. | ||
action (str): The action that triggered the event. | ||
actor (str): The GitHub username of the user or app that triggered the event. | ||
job (str): The name of the job associated with the event. | ||
run_attempt (str): The current attempt number for the job run. | ||
run_number (str): The unique number assigned to the run by GitHub. | ||
run_id (str): The unique identifier for the run. | ||
event_path (str): The path to the file containing the GitHub event payload. | ||
payload (dict): The GitHub event payload. | ||
Raises: | ||
EnvironmentError: If the required environment variable 'GITHUB_EVENT_PATH' | ||
is not found. | ||
Example: | ||
```python | ||
github_event = GithubEvent() | ||
print(github_event.event_name) | ||
print(github_event.sha) | ||
print(github_event.payload) | ||
``` | ||
""" | ||
|
||
def __init__(self) -> None: | ||
"""Initialize a new instance of the GithubEvent class.""" | ||
self.__load_details() | ||
|
||
def __load_details(self) -> None: | ||
""" | ||
Load GitHub event details from environment variables and event payload file. | ||
This method initializes the instance attributes by reading values from | ||
environment variables set by GitHub Actions and loading the event payload | ||
from a file. | ||
""" | ||
self.event_name = os.environ.get("GITHUB_EVENT_NAME") | ||
self.sha = os.environ.get("GITHUB_SHA") | ||
self.ref = os.environ.get("GITHUB_REF") | ||
self.workflow = os.environ.get("GITHUB_WORKFLOW") | ||
self.action = os.environ.get("GITHUB_ACTION") | ||
self.actor = os.environ.get("GITHUB_ACTOR") | ||
self.job = os.environ.get("GITHUB_JOB") | ||
self.run_attempt = os.environ.get("GITHUB_RUN_ATTEMPT") | ||
self.run_number = os.environ.get("GITHUB_RUN_NUMBER") | ||
self.run_id = os.environ.get("GITHUB_RUN_ID") | ||
|
||
if "GITHUB_EVENT_PATH" not in os.environ: | ||
raise EnvironmentError("GITHUB_EVENT_PATH not found on the environment.") | ||
|
||
self.event_path = os.environ["GITHUB_EVENT_PATH"] | ||
with open(self.event_path, encoding="utf-8") as file: | ||
self.payload = json.load(file) | ||
|
||
def to_dict(self) -> Dict[str, Any]: | ||
""" | ||
Convert the GithubEvent instance to a dictionary. | ||
Returns: | ||
dict: A dictionary containing the attributes of the GithubEvent instance. | ||
""" | ||
return { | ||
attr: getattr(self, attr) | ||
for attr in dir(self) | ||
if not callable(getattr(self, attr)) and not attr.startswith("__") | ||
} | ||
|
||
def __str__(self) -> str: | ||
""" | ||
Returns string representation of the github event data. | ||
Returns: | ||
str: Github event data. | ||
""" | ||
return str(self.to_dict()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
""" | ||
This script contains actions to be taken based on GitHub events, | ||
specifically for push and pull_request events. | ||
""" | ||
import subprocess | ||
import sys | ||
|
||
from event import GithubEvent | ||
|
||
EVENT_PUSH = "push" | ||
EVENT_PULL_REQUEST = "pull_request" | ||
|
||
|
||
def _handle_pr_event(event: GithubEvent) -> None: | ||
""" | ||
Handle pull_request GitHub event. | ||
Args: | ||
event (GithubEvent): An instance of the GithubEvent class representing | ||
the GitHub event. | ||
Raises: | ||
EnvironmentError: If the base SHA and head SHA cannot be retrieved from | ||
the event payload. | ||
""" | ||
try: | ||
to_commit = event.payload["pull_request"]["head"]["sha"] | ||
|
||
# getting from_commit using the total commits count | ||
_total_commits = event.payload["pull_request"]["commits"] | ||
from_commit = f"{to_commit}~{_total_commits-1}" | ||
_check_commits(from_commit, to_commit) | ||
except KeyError: | ||
raise EnvironmentError("Unable to retrieve Base SHA and Head SHA") from None | ||
|
||
|
||
def _handle_push_event(event: GithubEvent) -> None: | ||
""" | ||
Handle push GitHub event. | ||
Args: | ||
event (GithubEvent): An instance of the GithubEvent class representing | ||
the GitHub event. | ||
Raises: | ||
EnvironmentError: If the from hash and to hash cannot be retrieved from | ||
the event payload. | ||
""" | ||
try: | ||
commits = event.payload["commits"] | ||
from_commit = commits[0]["id"] | ||
to_commit = commits[-1]["id"] | ||
_check_commits(from_commit, to_commit) | ||
except KeyError: | ||
raise EnvironmentError("Unable to retrieve From hash and To hash") from None | ||
|
||
|
||
def _check_commits(from_hash: str, to_hash: str) -> None: | ||
"""Check commits using commitlint. | ||
Args: | ||
from_hash (str): The hash of the starting commit. | ||
to_hash (str): The hash of the ending commit. | ||
""" | ||
sys.stdout.write(f"Commit from {from_hash} to {to_hash}\n") | ||
try: | ||
output = subprocess.check_output( | ||
[ | ||
"commitlint", | ||
"--from-hash", | ||
from_hash, | ||
"--to-hash", | ||
to_hash, | ||
], | ||
text=True, | ||
).strip() | ||
sys.stdout.write(f"{output}\n") | ||
except subprocess.CalledProcessError: | ||
sys.exit(1) | ||
|
||
|
||
def main() -> None: | ||
"""Main entry point for the GitHub Actions workflow.""" | ||
event = GithubEvent() | ||
|
||
if event.event_name == EVENT_PUSH: | ||
_handle_push_event(event) | ||
elif event.event_name == EVENT_PULL_REQUEST: | ||
_handle_pr_event(event) | ||
elif event.event_name is None: | ||
sys.stdout.write("No any events, skipping\n") | ||
else: | ||
sys.stdout.write(f"Skipping for event {event.event_name}\n") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |