Posted on
Artificial Intelligence

Artificial Intelligence GitHub Actions

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Automate Your Repo With Artificial Intelligence GitHub Actions (Linux + Bash Friendly)

What if your CI could read pull requests, write helpful review notes, triage issues, and draft release notes while you sleep—all using plain Bash and a few YAML files? That’s exactly what Artificial Intelligence GitHub Actions bring to your workflow: consistency, speed, and fewer manual chores.

In this guide, you’ll learn why AI in CI/CD is useful, what to watch out for, and how to add 3–4 practical AI-powered workflows to your repository using nothing more than GitHub Actions, curl, jq, and an AI provider API.

Why AI + GitHub Actions is worth your time

  • Consistency: Reviews and summaries follow the same structure every time.

  • Speed: Get instant triage and reviewer context on every PR/issue.

  • Signal over noise: Summaries and labels help reviewers focus on what matters.

  • Fits your stack: Runs on Linux, controlled by Bash, YAML, and open tooling.

Common caveats (and fixes):

  • Cost and rate limits: Throttle prompts, cap diff size, and run only on relevant events.

  • Determinism: Use low temperature and fixed prompts; keep output formats strict (JSON where possible).

  • Security: Store keys as GitHub Encrypted Secrets; never echo secrets; redact sensitive logs.

What you’ll build

1) AI PR summary comments
2) AI Issue triage and labeling
3) AI Release notes from commits
4) (Optional) AI code review hints

All examples use:

  • GitHub Actions on ubuntu-latest

  • Bash + curl + jq

  • Secrets: OPENAI_API_KEY (or your LLM provider of choice)

You can adapt the API calls to any LLM that supports a Chat Completions–style HTTP API.


Prerequisites and installation (Linux)

You’ll need git, curl, jq, and (optionally for convenience) GitHub CLI (gh). On GitHub-hosted runners these are typically present, but for self-hosted runners install them as below.

Debian/Ubuntu (apt):

sudo apt update
sudo apt install -y git curl jq
# Install GitHub CLI (gh)
type -p curl >/dev/null || sudo apt install -y curl
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
  | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
  | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt update
sudo apt install -y gh

Fedora/RHEL/CentOS (dnf):

sudo dnf install -y git curl jq dnf-plugins-core
sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
sudo dnf install -y gh

openSUSE (zypper):

sudo zypper refresh
sudo zypper install -y git curl jq
sudo zypper addrepo https://cli.github.com/packages/rpm/gh-cli.repo gh-cli
sudo zypper refresh
sudo zypper install -y gh

Log in gh (optional but recommended for local operations):

gh auth login

Add your AI provider key as a GitHub secret (replace YOUR_KEY):

gh secret set OPENAI_API_KEY -b"YOUR_KEY"

Alternatively, set it via the GitHub UI under Settings > Secrets and variables > Actions.


1) AI PR Summary Comments

Goal: Every PR gets a concise, reviewer-friendly summary with risks, tests touched, and breaking changes.

Create .github/workflows/ai-pr-summary.yml:

name: AI PR Summary
on:
  pull_request:
    types: [opened, synchronize, reopened]
jobs:
  summarize:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      contents: read
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      GH_TOKEN: ${{ github.token }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Compute diff (bounded)
        shell: bash
        run: |
          BASE="${{ github.event.pull_request.base.sha }}"
          HEAD="${{ github.event.pull_request.head.sha }}"
          # Keep context bounded (first ~60KB of patch) to control cost
          git diff --unified=0 --no-color "$BASE" "$HEAD" | head -c 60000 > diff.patch
          echo "Patch bytes: $(wc -c < diff.patch)"

      - name: Build prompt and call LLM
        shell: bash
        run: |
          cat > sys.txt <<'SYS'
You are a senior reviewer. Produce a concise, actionable PR summary with:

- What changed and why (bullet points).

- Risk areas and files with notable changes.

- Suggested tests or edge cases.

- Note if any breaking changes are likely.
Keep it under 250 words.
SYS
          # The user prompt includes the PR title, body, and diff
          TITLE="${{ github.event.pull_request.title }}"
          BODY="$(printf '%s' "${{ github.event.pull_request.body }}" | sed 's/[[:cntrl:]]//g')"
          printf "PR: %s\n\n%s\n\nDiff:\n" "$TITLE" "$BODY" > user.txt
          cat diff.patch >> user.txt

          jq -n \
            --arg sys "$(cat sys.txt)" \
            --arg user "$(cat user.txt)" \
            '{
              model: "gpt-4o-mini",
              temperature: 0.2,
              messages: [
                {role:"system", content:$sys},
                {role:"user", content:$user}
              ]
            }' > body.json

          curl -sS https://api.openai.com/v1/chat/completions \
            -H "Authorization: Bearer ${OPENAI_API_KEY}" \
            -H "Content-Type: application/json" \
            -d @body.json | jq -r '.choices[0].message.content' > summary.md

      - name: Comment summary to PR
        shell: bash
        run: |
          gh pr comment ${{ github.event.pull_request.number }} --body-file summary.md

Notes:

  • Costs: The diff is truncated via head -c to cap tokens.

  • Determinism: temperature: 0.2 keeps things stable.

  • Security: The key is pulled from GitHub Secrets; do not echo it.


2) AI Issue Triage and Labeling

Goal: Label issues based on content (bug, enhancement, documentation, question) to speed up routing.

Create .github/workflows/ai-issue-triage.yml:

name: AI Issue Triage
on:
  issues:
    types: [opened, edited]
jobs:
  triage:
    runs-on: ubuntu-latest
    permissions:
      issues: write
      contents: read
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      GH_TOKEN: ${{ github.token }}
    steps:
      - name: Extract issue text
        id: extract
        shell: bash
        run: |
          TEXT=$(jq -r '.issue.title + "\n\n" + (.issue.body // "")' "$GITHUB_EVENT_PATH")
          printf "%s" "$TEXT" > issue.txt
          echo "body_path=issue.txt" >> "$GITHUB_OUTPUT"

      - name: Ask LLM for labels (JSON only)
        id: llm
        shell: bash
        run: |
          cat > sys.txt <<'SYS'
You classify GitHub issues. Output ONLY a compact JSON array of labels from:
["bug","enhancement","documentation","question","performance","security","test"]
Do not add any other text.
SYS
          USER=$(cat issue.txt | head -c 8000)
          jq -n \
            --arg sys "$(cat sys.txt)" \
            --arg user "$USER" \
            '{
              model: "gpt-4o-mini",
              temperature: 0,
              messages: [
                {role:"system", content:$sys},
                {role:"user", content:$user}
              ]
            }' > body.json

          RAW=$(curl -sS https://api.openai.com/v1/chat/completions \
            -H "Authorization: Bearer ${OPENAI_API_KEY}" \
            -H "Content-Type: application/json" \
            -d @body.json | jq -r '.choices[0].message.content')
          # Enforce allowlist and JSON format; ignore malformed cases safely
          echo "$RAW" | jq -c '
            map(select(. == "bug" or . == "enhancement" or . == "documentation" or . == "question" or . == "performance" or . == "security" or . == "test"))
            | unique
          ' > labels.json || echo '[]' > labels.json
          echo "labels=$(cat labels.json)" >> "$GITHUB_OUTPUT"

      - name: Apply labels
        shell: bash
        run: |
          mapfile -t LABELS < <(jq -r '.[]' labels.json)
          for L in "${LABELS[@]}"; do
            gh issue edit ${{ github.event.issue.number }} --add-label "$L"
          done

Notes:

  • The model must output pure JSON. We hard-validate with jq and discard anything else.

  • The allowlist prevents unknown labels.


3) AI Release Notes from Commits

Goal: Generate human-friendly release notes from commit messages when a tag is pushed.

Create .github/workflows/ai-release-notes.yml:

name: AI Release Notes
on:
  push:
    tags:
      - "v*"
jobs:
  notes:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      GH_TOKEN: ${{ github.token }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Gather commits since previous tag
        shell: bash
        run: |
          git fetch --tags --force
          TAG="${GITHUB_REF_NAME}"
          PREV="$(git describe --tags --abbrev=0 "${TAG}^" 2>/dev/null || true)"
          if [ -n "$PREV" ]; then
            RANGE="${PREV}..${TAG}"
          else
            # Fallback for first release: last 200 commits
            RANGE="$(git rev-list --max-count=200 HEAD | tail -n1)..${TAG}"
          fi
          git log --pretty=format:'- %s (%h) by %an' "$RANGE" > changes.txt
          echo "Previous tag: ${PREV:-none}"
          echo "Entries: $(wc -l < changes.txt)"

      - name: Ask LLM to draft notes
        shell: bash
        run: |
          cat > sys.txt <<'SYS'
You are a release manager. Turn the commit list into concise, user-facing release notes with:

- Highlights (features, fixes, perf, security)

- Breaking changes (if any)

- Upgrade notes (brief)
Keep it clear and scannable.
SYS
          USER=$(cat changes.txt | head -c 20000)
          jq -n \
            --arg sys "$(cat sys.txt)" \
            --arg user "$USER" \
            '{
              model: "gpt-4o-mini",
              temperature: 0.2,
              messages: [
                {role:"system", content:$sys},
                {role:"user", content:$user}
              ]
            }' > body.json

          curl -sS https://api.openai.com/v1/chat/completions \
            -H "Authorization: Bearer ${OPENAI_API_KEY}" \
            -H "Content-Type: application/json" \
            -d @body.json | jq -r '.choices[0].message.content' > NOTES.md

      - name: Create or update GitHub Release
        shell: bash
        run: |
          gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1 && \
            gh release edit "$GITHUB_REF_NAME" -F NOTES.md || \
            gh release create "$GITHUB_REF_NAME" -F NOTES.md -t "$GITHUB_REF_NAME"

Notes:

  • Works on tag push (vX.Y.Z).

  • Keeps prompts concise to control costs.


4) (Optional) AI Code Review Hints

Add lightweight, non-blocking review suggestions on each PR. This encourages better tests and catches footguns early.

Create .github/workflows/ai-review-hints.yml:

name: AI Review Hints
on:
  pull_request:
    types: [opened, synchronize]
jobs:
  hints:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      contents: read
    env:
      OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
      GH_TOKEN: ${{ github.token }}
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Gather small diff slice
        shell: bash
        run: |
          BASE="${{ github.event.pull_request.base.sha }}"
          HEAD="${{ github.event.pull_request.head.sha }}"
          git diff --unified=0 --no-color "$BASE" "$HEAD" | head -c 40000 > diff.patch
      - name: LLM suggestions
        shell: bash
        run: |
          cat > sys.txt <<'SYS'
Act as a meticulous code reviewer. Output:

- 3–7 concrete suggestions to improve correctness, tests, readability, or performance.

- Keep each suggestion brief with filename references where possible.
Avoid nitpicks; prioritize impactful feedback.
SYS
          USER=$(cat diff.patch)
          jq -n \
            --arg sys "$(cat sys.txt)" \
            --arg user "$USER" \
            '{
              model: "gpt-4o-mini",
              temperature: 0.2,
              messages: [
                {role:"system", content:$sys},
                {role:"user", content:$user}
              ]
            }' > body.json

          curl -sS https://api.openai.com/v1/chat/completions \
            -H "Authorization: Bearer ${OPENAI_API_KEY}" \
            -H "Content-Type: application/json" \
            -d @body.json | jq -r '.choices[0].message.content' > hints.md
      - name: Post hints
        shell: bash
        run: gh pr comment ${{ github.event.pull_request.number }} --body-file hints.md

Operational tips and guardrails

  • Cost control:

    • Truncate diffs and bodies (head -c N).
    • Trigger on opened/synchronize only, not on every push.
    • Consider skipping large PRs: if wc -c diff.patch > threshold, post a note and skip LLM.
  • Reliability:

    • Use temperature ≤ 0.2 for stable output.
    • Validate/parse model output with jq; maintain allowlists.
  • Security:

    • Keep API keys in GitHub Secrets; never echo secrets to logs.
    • Redact payloads if they may contain sensitive data.
  • Observability:

    • Log payload sizes and token estimates.
    • Add retry/backoff for transient HTTP failures.

Conclusion and next steps (CTA)

With a few YAML files and standard Linux tools, you’ve added real, immediate value to your CI:

  • PR summaries that save reviewer time

  • Automatic issue triage

  • Release notes on demand

  • Optional code review hints

Next: 1) Drop these workflow files into .github/workflows in a test repository.
2) Create OPENAI_API_KEY in GitHub Actions Secrets.
3) Open a PR and watch AI do the boring parts.

Iterate on prompts, thresholds, and events until the signal-to-noise ratio feels right for your team. When you’re ready, roll it out to more repos and enforce consistent, AI-augmented delivery across your org.