Computer scienceSystem administration and DevOpsCI/CD processesGitHub Actions

Integration of GitHub Actions and Github PRs

7 minutes read

GitHub Actions and Pull Requests (PRs) are foundational tools that, when integrated, significantly enhance your development process. This integration forms part of the broader practices of Continuous Integration (CI) and Continuous Deployment (CD), which are fundamental for modern software development workflows. By automating these processes, your code changes become more efficient and reliable, ensuring that every update meets your project's quality standards.

Let's dive in and see how this can be accomplished.

Setting up workflows for PRs

GitHub Actions can trigger workflows based on various pull request (PR) events. These events include opening, updating, closing PRs, and many more. When a PR event occurs, GitHub sends a payload containing information about the PR. For example, head.sha represents the latest commit SHA of the branch being merged. This data can be used within workflows to perform specific actions.

You can trigger workflows based on PR types (e.g., opened, closed), branches, and file paths. This allows you to customize workflows based on different conditions. For instance, you can configure a workflow to trigger on PRs that are opened or synchronized to the main or develop branches, and only for changes within the src directory, excluding the docs directory:

on:
  pull_request:
    types: [opened, synchronize]
    branches: [main, develop]
    paths:
      - 'src/**'
      - '!docs/**'

Conditional checks can also be employed to execute steps only when certain conditions are met. For example, you can configure a workflow to deploy the project or send a thank you message when a PR is merged:

- name: Deploy on Merge
  if: github.event.pull_request.merged == true
  run: ./deploy.sh

You can also automate PR reviews. For instance, you can trigger a workflow to request reviews or perform automated code analysis, ensuring that the code adheres to your project's standards before merging:

- name: Request Review
  run: gh pr review ${{ github.event.pull_request.number }} --request

This automation not only saves time but also enhances the reliability of your development process.

Common PR automation tasks

When PR events occur, we can perform many automation tasks depending on the event. These include running various tests—like unit, integration, or end-to-end tests—as well as syntax checkers (linters) and build scripts. These can be set to provide feedback directly on the PR or send alerts or messages to your team's communication platforms, keeping everyone in the loop about the PR's status.

Actions can also be configured to run in different environments or across various operating systems, ensuring compatibility and consistency across different ecosystems. These automated checks serve as your first line of defense, ensuring that only quality code is merged. Multiple jobs in a workflow can run steps that execute different commands or use actions created by the community. For example, an action could be set to run a linter, whereas another might execute a build tool like Gradle or Maven. Look at the example below:

name: CI/CD Pipeline

on:
  pull_request:
    branches:
      - main
jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout the repository
      - uses: actions/checkout@v4

      - name: Set up Node      
      - uses: actions/setup-node@v4
        with:
          node-version: '20.x'

      - name: Test, lint, and build
      - run: npm install
      - run: npm test
      - run: npm run lint
      - run: npm run build

Here, we have a GitHub Actions workflow configuration file for a Node.js project triggered whenever a pull request is made to the main branch. It has steps to install the project's dependencies, run tests, lint the code, and build the project using npm scripts. You can also add a final step to send a notification to a Slack webhook URL, probably one of your team's communication channels:

- name: Send Notification to Slack
  if: always()
  run: |
    STATUS=${{ job.status }}
    curl -X POST -H 'Content-type: application/json' --data "{
      \"text\": \"Build ${STATUS} for ${{ github.repository }}\n
      Commit: ${{ github.sha }}\n
      Actor: ${{ github.actor }}\n
      Build URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\n
      Run Number: ${{ github.run_number }}\"
    }" ${{ secrets.SLACK_WEBHOOK_URL }}

This notification has details about the build status, the repository, the commit, who triggered the workflow, the build URL, and the run number. Integrating these practices into your workflows ensures that code changes are thoroughly tested, reviewed, and meet quality standards before merging.

Integrating AI tools for enhanced code analysis

To further enhance the robustness of your GitHub workflows, consider integrating AI tools. AI can perform complex tasks such as analyzing code changes, predicting potential issues, and generating code or tests. Using AI to review PRs can identify hidden bugs and suggest improvements, offering deeper insights before integration.

You can accomplish this using external actions, tools, or custom-made scripts for specific use cases. For example, you can create a script that sends the PR diff to OpenAI for analysis and adds the response as a comment in the pull request. A valid OpenAI API key, set as a secret in the repo (OPENAI_API_KEY), is needed for this to work. The workflow would trigger this analysis when a pull request is opened or updated:

on:
  pull_request:
    types: [opened, reopened, synchronize]
    branches: [main]

We need to provide write permissions to contents and PRs for the GitHub Token:

permissions:
  contents: write
  pull-requests: write

After checking out the repo, we extract the PR's diff and save it in a text file:

- name: Extract PR Diff
  run: git diff ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }} > pr_diff.txt

Next, we send it to ChatGPT for analysis, passing the necessary keys as environment variables for the script after making it executable:

- name: Make script executable
  run: chmod +x ./scripts/gpt.sh

- name: Analyze and Comment with OpenAI
  env:
    OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    REPO: ${{ github.repository }}
    PR_NUMBER: ${{ github.event.pull_request.number }}
  run: ./scripts/gpt.sh $OPENAI_API_KEY $GITHUB_TOKEN $REPO $PR_NUMBER

Once this workflow runs successfully, a comment from ChatGPT will be added to the PR. This comment has a summary of major insights, potential issues, and areas of improvement that ChatGPT identified:

Screenshot of GitHub comment detailing insights and improvements for a Python Docker container project.

Besides OpenAI, you can also use other cloud-based tools like Amazon CodeGuru Reviewer to analyze PRs. These tools further streamline the integration of AI into DevOps processes but at an additional cost.

Configure branch protection rules

Now that we have some PR automation tasks in place, we can enforce them using branch protection rules. These rules help prevent unverified code from being merged, potentially destabilizing your project. They also ensure consistency and adherence to organizational standards.

You can configure these rules in the repository settings by following these steps:

  • Navigate to the "Settings" tab of your repository;

  • Select "Branches" from the left sidebar;

  • Under "Branch protection rules", click "Add branch protection rule";

  • Enter the branch name pattern, such as main;

  • Enable "Require status checks to pass before merging";

  • Select the required status checks (e.g., the workflows you've defined in GitHub Actions);

  • If desired, you can also require PR reviews before merging.

Screenshot of branch protection settings.

In the example above, analyze-code-with-chatgpt is a GitHub Actions workflow run that was completed successfully in the past week. That workflow has to run successfully before the PR can be merged:

GitHub pull request interface showing all checks have passed and the branch has no conflicts with the base branch.

With these rules in place, code can only be merged into the main branch after all specified checks have passed. This ensures the integrity and stability of your main codebase.

Conclusion

Integrating GitHub Actions with PRs offers a robust method to ensure that only high-quality code makes its way into your main codebase. By automating your development workflow, you can systematically run tests, perform code analysis, and enforce coding standards whenever a pull request is made. This not only catches potential issues early but also maintains the integrity and reliability of your software, fostering a culture of excellence and precision in your development process. Go on and delve further to harness its full potential

How did you like the theory?
Report a typo