DEV Community

Cover image for 7 GitHub Actions That Automate the Boring Parts of Agency Work
Sanjay M.
Sanjay M.

Posted on

7 GitHub Actions That Automate the Boring Parts of Agency Work

Every developer knows the drill. You open a PR, manually slap on some labels, ping someone in Slack for a review, then spend 10 minutes writing release notes that nobody reads. Multiply that by 50 PRs a week across three client projects, and suddenly you've lost half a day to busywork.

GitHub Actions can handle most of this automatically. Here are 7 free actions that eliminate the repetitive tasks eating into your actual development time.


1. Auto-Label PRs by Files Changed

Action: actions/labeler

Instead of manually tagging every PR as "frontend" or "api" or "docs," this action reads what files changed and applies labels automatically.

The setup:

name: "Pull Request Labeler"
on:
  pull_request_target:

jobs:
  labeler:
    permissions:
      contents: read
      pull-requests: write
    runs-on: ubuntu-latest
    steps:
      - uses: actions/labeler@v5
Enter fullscreen mode Exit fullscreen mode

Then create .github/labeler.yml:

frontend:
  - changed-files:
    - any-glob-to-any-file: 'src/frontend/**/*'

api:
  - changed-files:
    - any-glob-to-any-file: 'src/api/**'

documentation:
  - changed-files:
    - any-glob-to-any-file: '**/*.md'
Enter fullscreen mode Exit fullscreen mode

Now every PR touching frontend code gets labeled frontend automatically. Filter your PR list by label and instantly see all API changes across the week.

Watch out for: This uses pull_request_target for security reasons. If you're accepting PRs from forks, be careful about what the workflow can access.


2. Flag Oversized PRs Before They Become a Problem

Action: codelytv/pr-size-labeler

Large PRs kill velocity. They take forever to review, they're more likely to have bugs, and reviewers start skimming instead of reading. This action labels PRs by size (XS through XL) so you can spot trouble early.

The setup:

name: PR Size Labeler
on: [pull_request]

jobs:
  labeler:
    permissions:
      pull-requests: write
      contents: read
    runs-on: ubuntu-latest
    steps:
      - uses: codelytv/pr-size-labeler@v1
        with:
          xs_max_size: '10'
          s_max_size: '100'
          m_max_size: '500'
          l_max_size: '1000'
          fail_if_xl: 'false'
          message_if_xl: >
            This PR exceeds 1000 lines. Consider breaking it into smaller chunks for easier review.
          files_to_ignore: |
            package-lock.json
            yarn.lock
            pnpm-lock.yaml
Enter fullscreen mode Exit fullscreen mode

When someone opens a 1,500-line PR, they get a gentle nudge to split it up. When you're planning reviews for the day, size/xl tells you that one needs an hour, not 15 minutes.

Watch out for: Lock files inflate the count. Always add them to files_to_ignore.


3. Auto-Close Stale PRs and Issues

Action: actions/stale

Every repo accumulates zombie PRs. Someone started a feature, got pulled to another project, and now there's a 6-month-old PR rotting in the queue. This action warns authors after a period of inactivity, then closes the PR if nothing happens.

The setup:

name: 'Close Stale PRs'
on:
  schedule:
    - cron: '30 9 * * *'

jobs:
  stale:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      pull-requests: write
    steps:
      - uses: actions/stale@v9
        with:
          stale-pr-message: |
            This PR has been inactive for 14 days. 
            If you're still working on it, drop a comment and I'll leave it alone.
          stale-pr-label: 'stale'
          days-before-pr-stale: 14
          days-before-pr-close: 7
          exempt-pr-labels: 'work-in-progress,blocked,waiting-on-external'
          exempt-draft-pr: true
Enter fullscreen mode Exit fullscreen mode

The action runs daily at 9:30 AM. After 14 days of no activity, it adds a stale label and posts a comment. Seven days later, if still no response, it closes the PR. Draft PRs and anything labeled work-in-progress are exempt.

Watch out for: The default operations-per-run is 30. If you have a backlog of stale items, bump this to 100+ or it'll take multiple days to process everything.


4. Enforce Commit Message Conventions

Action: amannn/action-semantic-pull-request

Commit messages like "fix stuff" or "WIP" make git history useless. This action enforces conventional commit format (feat:, fix:, docs:, etc.) on PR titles, which matters if you squash-merge.

The setup:

name: 'Validate PR Title'
on:
  pull_request_target:
    types: [opened, edited, synchronize]

jobs:
  main:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: read
    steps:
      - uses: amannn/action-semantic-pull-request@v5
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          types: |
            feat
            fix
            docs
            style
            refactor
            test
            chore
          requireScope: false
          wip: true
Enter fullscreen mode Exit fullscreen mode

Now PRs must be titled like feat: add user authentication or fix: resolve memory leak in dashboard. The wip: true setting lets people bypass this with "WIP:" prefix while they're still working.

This is used by Electron, Vite, and Vercel. Once you have consistent PR titles, automatic changelog generation becomes possible (see #6).

Watch out for: This validates PR titles, not individual commits. Works best when your repo uses GitHub's squash-merge setting.


5. Lint Everything With One Action

Action: super-linter/super-linter

If your team touches JavaScript, Python, YAML, Markdown, Dockerfiles, and Terraform across different projects, maintaining separate linters is a nightmare. Super-Linter runs 50+ linters in a single action.

The setup:

name: Lint Code Base
on:
  push:
  pull_request:

jobs:
  lint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      statuses: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: super-linter/super-linter@v6
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          VALIDATE_ALL_CODEBASE: false
          DEFAULT_BRANCH: main
Enter fullscreen mode Exit fullscreen mode

Setting VALIDATE_ALL_CODEBASE: false means it only lints changed files, which keeps PR checks fast. It auto-detects languages and applies appropriate linters—ESLint for JS, Pylint for Python, markdownlint for docs.

Watch out for: The Docker image is around 2GB. First run takes a while, but subsequent runs use cache. You can also disable specific linters with environment variables like VALIDATE_PYTHON: false.


6. Generate Release Notes Automatically

Action: mikepenz/release-changelog-builder-action

Writing release notes by hand means scrolling through every merged PR, categorizing changes, and formatting markdown. This action generates changelogs automatically from your PR labels and titles.

The setup:

name: Release
on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Build Changelog
        id: changelog
        uses: mikepenz/release-changelog-builder-action@v4
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          body: ${{ steps.changelog.outputs.changelog }}
Enter fullscreen mode Exit fullscreen mode

When you push a tag like v1.2.0, this action:

  1. Finds all PRs merged since the last tag
  2. Groups them by label (features, fixes, docs)
  3. Generates formatted release notes
  4. Creates a GitHub release with that content

This is where the earlier actions pay off. If you've been auto-labeling PRs and enforcing commit conventions, your release notes practically write themselves.

Watch out for: Requires consistent PR labeling. Combine with actions/labeler for best results.


7. Send Slack Notifications for Key Events

Action: rtCamp/action-slack-notify

Instead of checking GitHub Actions status manually and posting updates to Slack, let the workflow do it.

The setup:

name: Deploy Notification
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      # Your deploy steps here...

      - name: Notify Success
        if: success()
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
          SLACK_CHANNEL: deployments
          SLACK_COLOR: 'good'
          SLACK_TITLE: 'Deploy Complete'
          SLACK_MESSAGE: 'Production deploy successful :rocket:'

      - name: Notify Failure
        if: failure()
        uses: rtCamp/action-slack-notify@v2
        env:
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
          SLACK_CHANNEL: deployments
          SLACK_COLOR: 'danger'
          SLACK_TITLE: 'Deploy Failed'
          SLACK_MESSAGE: 'Production deploy failed. Check GitHub Actions.'
Enter fullscreen mode Exit fullscreen mode

Deploys, test failures, and build completions show up in Slack where the team already lives. No more "did the deploy go through?" questions in standup.

Watch out for: You'll need a Slack Incoming Webhook (free, takes 2 minutes to set up). Be selective about what triggers notifications—too many and people start ignoring them.


Putting It Together

These actions work best in combination. Here's what a typical workflow looks like:

  1. Developer opens a PR
  2. actions/labeler tags it by files changed
  3. codelytv/pr-size-labeler flags if it's too large
  4. amannn/action-semantic-pull-request validates the PR title
  5. super-linter/super-linter checks code quality
  6. After merge, actions/stale keeps the backlog clean
  7. On release, mikepenz/release-changelog-builder-action generates notes
  8. rtCamp/action-slack-notify tells the team it's done

Each action takes 5-10 minutes to set up. Combined, they eliminate hours of weekly busywork—time better spent actually building things.


What GitHub Actions have saved your team the most time? Always looking for more to add to our workflows.


If you're tired of juggling GitHub, Slack, spreadsheets, and three other tools to manage agency projects, Teamcamp puts it all in one place. Project management, time tracking, client collaboration, and invoicing.

Top comments (0)