<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Muhammad Usman Shabir</title>
    <description>The latest articles on Forem by Muhammad Usman Shabir (@muhammad_usmanshabir_19e).</description>
    <link>https://forem.com/muhammad_usmanshabir_19e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3842297%2F5e0d71b2-8dca-49bb-b7a7-5b895aa3366f.jpg</url>
      <title>Forem: Muhammad Usman Shabir</title>
      <link>https://forem.com/muhammad_usmanshabir_19e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/muhammad_usmanshabir_19e"/>
    <language>en</language>
    <item>
      <title>How to set up automated code quality gates in GitHub Actions in under 5 minutes</title>
      <dc:creator>Muhammad Usman Shabir</dc:creator>
      <pubDate>Mon, 06 Apr 2026 05:48:15 +0000</pubDate>
      <link>https://forem.com/muhammad_usmanshabir_19e/how-to-set-up-automated-code-quality-gates-in-github-actions-in-under-5-minutes-5gkj</link>
      <guid>https://forem.com/muhammad_usmanshabir_19e/how-to-set-up-automated-code-quality-gates-in-github-actions-in-under-5-minutes-5gkj</guid>
      <description>&lt;p&gt;Every developer has shipped code they knew wasn't ready. Maybe it was a Friday afternoon merge, maybe the reviewer was in a rush. Either way, that shortcut cost the team hours — or worse, a production incident.&lt;/p&gt;

&lt;p&gt;What if your CI pipeline could catch that before it ever reaches &lt;code&gt;main&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;That's exactly what a code quality gate does. And you can set one up in under five minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Quality Gate?
&lt;/h2&gt;

&lt;p&gt;A quality gate is a minimum quality score your code must pass before it's allowed to merge. Think of it as a bouncer for your codebase — if a pull request doesn't meet the threshold, the merge is blocked automatically.&lt;/p&gt;

&lt;p&gt;It evaluates things like code complexity, readability, maintainability, and potential bugs, then returns a score. If the score falls below your configured minimum, the GitHub check fails and the PR can't be merged until the issues are fixed. No human gatekeeper needed. No bad code slipping through during a busy sprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why You Need One
&lt;/h2&gt;

&lt;p&gt;Bugs are cheap to fix when you catch them early. A logic error spotted during code review might take ten minutes to resolve. That same bug in production? It could mean rollback deployments, customer complaints, incident postmortems, and hours of debugging under pressure.&lt;/p&gt;

&lt;p&gt;IBM's Systems Sciences Institute found that fixing a defect in production costs roughly &lt;strong&gt;six times more&lt;/strong&gt; than fixing it during implementation. Other industry research puts the multiplier even higher.&lt;/p&gt;

&lt;p&gt;The problem isn't that teams don't review code — it's that manual reviews are inconsistent. Reviewers get fatigued, context gets lost, and standards drift over time. An automated quality gate removes that variability. Every PR gets evaluated against the same criteria, every time.&lt;/p&gt;

&lt;p&gt;It also takes pressure off senior developers who often end up as the bottleneck in review cycles. Instead of manually gatekeeping every merge, they can focus on architecture and mentorship while the gate handles the baseline checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Setup
&lt;/h2&gt;

&lt;p&gt;Here's how to get automated quality gates running on your repo using GetCodeReviews and GitHub Actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Sign Up and Get Your API Key&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Head to getcodereviews.com and create an account. Once you're in, navigate to your dashboard and grab your API key. You'll need this to authenticate the GitHub Action with the service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Add Your API Key to GitHub Secrets&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Go to your GitHub repository, then &lt;strong&gt;Settings → Secrets and variables → Actions → New repository secret&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;CODESCAN_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: Paste your API key from Step 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This keeps your key secure and out of your codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add the Workflow File&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create a new file at &lt;code&gt;.github/workflows/code-quality-gate.yml&lt;/code&gt; and paste the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Code Quality Gate&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;develop&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;quality-check&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Code Quality Review&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get changed files&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changed&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD -- '*.js' '*.ts' '*.jsx' '*.tsx' '*.py' '*.go' '*.rb' | head -20)&lt;/span&gt;
          &lt;span class="s"&gt;echo "files=$FILES" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run GetCodeReviews Quality Scan&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;review&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;RESPONSE=$(curl -s -X POST https://getcodereviews.com/api/review \&lt;/span&gt;
            &lt;span class="s"&gt;-H "Authorization: Bearer ${{ secrets.CODESCAN_API_KEY }}" \&lt;/span&gt;
            &lt;span class="s"&gt;-H "Content-Type: application/json" \&lt;/span&gt;
            &lt;span class="s"&gt;-d "{&lt;/span&gt;
              &lt;span class="s"&gt;\"repo\": \"${{ github.repository }}\",&lt;/span&gt;
              &lt;span class="s"&gt;\"pr_number\": ${{ github.event.pull_request.number }},&lt;/span&gt;
              &lt;span class="s"&gt;\"files\": \"${{ steps.changed.outputs.files }}\"&lt;/span&gt;
            &lt;span class="s"&gt;}")&lt;/span&gt;
          &lt;span class="s"&gt;SCORE=$(echo $RESPONSE | jq -r '.score')&lt;/span&gt;
          &lt;span class="s"&gt;echo "score=$SCORE" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;
          &lt;span class="s"&gt;echo "## Code Quality Report" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;
          &lt;span class="s"&gt;echo "**Score: $SCORE / 100**" &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;
          &lt;span class="s"&gt;echo "$RESPONSE" | jq -r '.summary' &amp;gt;&amp;gt; $GITHUB_STEP_SUMMARY&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Enforce Quality Gate&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;SCORE=${{ steps.review.outputs.score }}&lt;/span&gt;
          &lt;span class="s"&gt;MINIMUM=70&lt;/span&gt;
          &lt;span class="s"&gt;if [ "$SCORE" -lt "$MINIMUM" ]; then&lt;/span&gt;
            &lt;span class="s"&gt;echo "❌ Quality gate failed. Score: $SCORE (minimum: $MINIMUM)"&lt;/span&gt;
            &lt;span class="s"&gt;exit 1&lt;/span&gt;
          &lt;span class="s"&gt;else&lt;/span&gt;
            &lt;span class="s"&gt;echo "✅ Quality gate passed. Score: $SCORE"&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Set Your Minimum Score&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the workflow above, the &lt;code&gt;MINIMUM&lt;/code&gt; variable is set to &lt;code&gt;70&lt;/code&gt;. This is a good starting point — strict enough to catch genuinely problematic code but forgiving enough that it won't block every minor style issue.&lt;/p&gt;

&lt;p&gt;As your team gets comfortable, you can raise it to 80 or even 85. You can also make it configurable per-branch if you want stricter enforcement on &lt;code&gt;main&lt;/code&gt; than on &lt;code&gt;develop&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Test It With a Bad PR&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Push a branch with some intentionally sloppy code — deeply nested logic, no error handling, duplicated blocks. Open a pull request against main and watch the action run. You should see the check fail with a score below your threshold, along with a summary of what needs fixing.&lt;/p&gt;

&lt;p&gt;This confirms the gate is working before your team relies on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happens When a PR Fails the Gate?
&lt;/h2&gt;

&lt;p&gt;When a pull request scores below the minimum threshold, the GitHub check turns red and blocks the merge. The developer sees a clear summary in the PR timeline showing their score, what went wrong, and where to focus their fixes.&lt;/p&gt;

&lt;p&gt;There's no guessing involved. The report highlights specific issues — things like high cyclomatic complexity, missing error handling, or code duplication — so the developer knows exactly what to address. They fix the flagged issues, push again, and the gate re-evaluates automatically.&lt;/p&gt;

&lt;p&gt;This feedback loop is fast. Most developers get their PR passing on the second push. Over time, you'll notice that first-push quality starts improving on its own because the team internalizes the standards the gate enforces.&lt;/p&gt;

&lt;p&gt;It also eliminates those awkward code review conversations where a senior dev has to tell someone their code isn't up to standard. The gate delivers the feedback objectively, and the team just focuses on fixing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Setting up a quality gate takes five minutes but saves your team hours every week. Bad code gets caught before it merges, reviews become faster, and your codebase stays consistent without relying on manual discipline.&lt;/p&gt;

&lt;p&gt;If you want to explore advanced configurations — custom rulesets, team dashboards, or VS Code integration — check out the full documentation at getcodereviews.com/docs/api.&lt;/p&gt;

&lt;p&gt;Your future self (and your on-call rotation) will thank you.&lt;/p&gt;

</description>
      <category>github</category>
      <category>devops</category>
      <category>cicd</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How a SQL injection bug passed 3 rounds of code review (and how AI caught it instantly)</title>
      <dc:creator>Muhammad Usman Shabir</dc:creator>
      <pubDate>Tue, 31 Mar 2026 03:21:11 +0000</pubDate>
      <link>https://forem.com/muhammad_usmanshabir_19e/how-a-sql-injection-bug-passed-3-rounds-of-code-review-and-how-ai-caught-it-instantly-eco</link>
      <guid>https://forem.com/muhammad_usmanshabir_19e/how-a-sql-injection-bug-passed-3-rounds-of-code-review-and-how-ai-caught-it-instantly-eco</guid>
      <description>&lt;p&gt;It was a Friday afternoon. The sprint was ending. Everyone wanted to go home.&lt;/p&gt;

&lt;p&gt;A pull request came in for a new user lookup feature. Three senior developers reviewed it. All three approved it. It shipped to production that evening.&lt;/p&gt;

&lt;p&gt;Two weeks later a security audit flagged it.&lt;/p&gt;

&lt;p&gt;SQL injection. A textbook one. The kind that every developer learns about in their first week.&lt;/p&gt;

&lt;p&gt;Here's the code that passed three rounds of review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM users WHERE id = &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Three experienced developers looked at this. Nobody caught it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Humans Miss These
&lt;/h2&gt;

&lt;p&gt;Before explaining how AI caught it instantly, it's worth understanding why three smart developers missed something so fundamental.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review fatigue is real.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That PR was the 14th one reviewed that Friday. By the time a developer reaches their 10th PR of the day their brain is actively looking for shortcuts. They scan for the obvious — broken logic, missing edge cases, typos. Deep security analysis requires a different kind of focus that nobody has at 4pm on a Friday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security issues don't look obviously wrong.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That SQL query looks perfectly reasonable at first glance. It's readable. It's concise. The variable name makes sense. Nothing visually jumps out as dangerous unless you specifically stop and think "wait, is this concatenating user input directly into a database query?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time pressure kills thoroughness.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sprint deadlines create invisible pressure on reviewers. Nobody says "approve it faster" — but everyone feels the unspoken expectation. A thorough security review of one file can take 20-30 minutes. Nobody has that kind of time when there are 14 PRs in the queue.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Malicious Request Looks Like
&lt;/h2&gt;

&lt;p&gt;Once that code shipped, any user could send this as their userId:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1 OR 1=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which turns the query into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which returns every single user in the database.&lt;/p&gt;

&lt;p&gt;The fix took literally 10 minutes once we found it. Parameterized queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getUserById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SELECT * FROM users WHERE id = $1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How AI Caught It Instantly
&lt;/h2&gt;

&lt;p&gt;After that incident I started building GetCodeReviews — an AI code reviewer powered by Claude. I fed it that exact function. It caught it in 4 seconds. Here's the actual output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Score: 23/100

CRITICAL — SQL Injection Vulnerability
Your query concatenates user input directly into a SQL string.
This allows an attacker to manipulate the query.

Fix: const query = "SELECT * FROM users WHERE id = $1"
      const result = await db.execute(query, [userId])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No fatigue. No time pressure. No Friday afternoon distraction. Just a clear, specific diagnosis with the exact fix to apply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Automated Security Scanning in 2 Minutes
&lt;/h2&gt;

&lt;p&gt;The real power isn't the manual paste-and-review. It's catching these issues automatically before they ever reach a human reviewer. Here's how to add GetCodeReviews to your GitHub Actions workflow:&lt;br&gt;
→ Sign up at getcodereviews.com and get your API key from the dashboard&lt;br&gt;
→ Add your API key to GitHub Secrets: Settings &amp;gt; Secrets &amp;gt; CODESCAN_API_KEY&lt;br&gt;
→ Add this workflow file to .github/workflows/code-review.yml:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AI Code Review&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;synchronize&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;review&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run GetCodeReviews&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;getcodereviews/action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;api-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CODESCAN_API_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;min-score&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The min-score: 70 means any PR scoring below 70/100 automatically fails and cannot be merged until issues are fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  What It Catches Beyond SQL Injection
&lt;/h2&gt;

&lt;p&gt;SQL injection is the obvious one but the AI catches a lot more that humans routinely miss:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardcoded credentials:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;apiKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sk-prod-abc123xyz789&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;postgres://admin:password123@prod-db&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Missing error handling:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// No catch block = silent failures in production&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchUserData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Off-by-one errors:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// i &amp;lt;= data.length accesses data[data.length] = undefined&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Uncomfortable Truth About Code Review
&lt;/h2&gt;

&lt;p&gt;Human code review is essential. I'm not arguing we should replace it.&lt;/p&gt;

&lt;p&gt;But human code review was never designed to catch every security vulnerability in every PR every day. Modern development — fast sprints, large teams, 10-15 PRs per day — has stretched code review far beyond what it was designed for.&lt;/p&gt;

&lt;p&gt;AI doesn't replace the human review. It handles the mechanical part — catching the obvious security issues, the missing error handling, the dangerous patterns — so the human reviewer can focus on what humans are actually good at: architecture, business logic, maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Paste that vulnerable function into GetCodeReviews (getcodereviews.com) and see what happens. Free to try, no card needed.&lt;/p&gt;

&lt;p&gt;Or drop your worst code review horror story in the comments. What's the most embarrassing bug that made it to production through a human review?&lt;/p&gt;

&lt;p&gt;I'll go first: SQL injection in a user lookup function. Three senior developers approved it. Two weeks in production before anyone noticed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;We don't talk about that sprint anymore.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>How to Set Up Automated Code Quality Gates in GitHub Actions in 5 Minutes</title>
      <dc:creator>Muhammad Usman Shabir</dc:creator>
      <pubDate>Thu, 26 Mar 2026 22:00:03 +0000</pubDate>
      <link>https://forem.com/muhammad_usmanshabir_19e/how-to-set-up-automated-code-quality-gates-in-github-actions-in-5-minutes-d36</link>
      <guid>https://forem.com/muhammad_usmanshabir_19e/how-to-set-up-automated-code-quality-gates-in-github-actions-in-5-minutes-d36</guid>
      <description>&lt;p&gt;Every team has had a bug slip through code review and make it to production.&lt;/p&gt;

&lt;p&gt;Not because the developer didn't know better. Not because the reviewer wasn't paying attention. But because code review is a human process — and humans get tired, rushed, and distracted.&lt;/p&gt;

&lt;p&gt;Quality gates fix this by automating the first pass. If your code scores below a minimum threshold, the build fails automatically. No human intervention needed. Bad code never reaches production.&lt;/p&gt;

&lt;p&gt;In this tutorial I'll show you how to set one up in GitHub Actions in under 5 minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a code quality gate?
&lt;/h2&gt;

&lt;p&gt;A quality gate is a pass/fail check in your CI/CD pipeline that evaluates code against a defined standard. If the code doesn't meet the standard — the pipeline fails and the PR cannot be merged.&lt;/p&gt;

&lt;p&gt;You've probably used basic quality gates already without calling them that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ESLint failing a build on lint errors&lt;/li&gt;
&lt;li&gt;Tests failing before a deploy&lt;/li&gt;
&lt;li&gt;TypeScript refusing to compile with type errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI-powered quality gates take this further by catching things static analysis can't — logic bugs, security vulnerabilities, missing error handling, and performance anti-patterns.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub repository&lt;/li&gt;
&lt;li&gt;A GetCodeReviews API key (free at &lt;a href="https://getcodereviews.com" rel="noopener noreferrer"&gt;getcodereviews.com&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;5 minutes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 — Get your API key
&lt;/h2&gt;

&lt;p&gt;Sign up at &lt;a href="https://getcodereviews.com" rel="noopener noreferrer"&gt;getcodereviews.com&lt;/a&gt; and go to Dashboard → API Keys → Generate Key.&lt;/p&gt;

&lt;p&gt;You'll see a key that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;csai_a1b2c3d4e5f6...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this — you'll add it to GitHub Secrets in the next step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — Add your API key to GitHub Secrets
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to your GitHub repo&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Secrets and variables&lt;/strong&gt; → &lt;strong&gt;Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New repository secret&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;CODESCAN_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: paste your API key&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add secret&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 3 — Create the workflow file
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/code-quality.yml&lt;/code&gt; in your repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Code Quality Gate&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;synchronize&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;reopened&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;quality-gate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AI Code Review&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get changed files&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;changed&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;echo "files=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \&lt;/span&gt;
            &lt;span class="s"&gt;| grep -E '\.(js|ts|jsx|tsx|py|go|rs|java|php|rb)$' \&lt;/span&gt;
            &lt;span class="s"&gt;| head -10 \&lt;/span&gt;
            &lt;span class="s"&gt;| tr '\n' ' ')" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run quality gate&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;steps.changed.outputs.files != ''&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;MIN_SCORE=70&lt;/span&gt;
          &lt;span class="s"&gt;TOTAL=0&lt;/span&gt;
          &lt;span class="s"&gt;COUNT=0&lt;/span&gt;
          &lt;span class="s"&gt;FAILED=0&lt;/span&gt;

          &lt;span class="s"&gt;for FILE in ${{ steps.changed.outputs.files }}; do&lt;/span&gt;
            &lt;span class="s"&gt;if [ -f "$FILE" ]; then&lt;/span&gt;
              &lt;span class="s"&gt;echo "Reviewing: $FILE"&lt;/span&gt;

              &lt;span class="s"&gt;CODE=$(cat "$FILE" | head -200)&lt;/span&gt;
              &lt;span class="s"&gt;EXT="${FILE##*.}"&lt;/span&gt;

              &lt;span class="s"&gt;RESPONSE=$(curl -s -X POST https://getcodereviews.com/api/review \&lt;/span&gt;
                &lt;span class="s"&gt;-H "Content-Type: application/json" \&lt;/span&gt;
                &lt;span class="s"&gt;-H "x-api-key: ${{ secrets.CODESCAN_API_KEY }}" \&lt;/span&gt;
                &lt;span class="s"&gt;-d "{\"code\": $(echo "$CODE" | jq -Rs .), \"language\": \"$EXT\", \"source\": \"github\"}")&lt;/span&gt;

              &lt;span class="s"&gt;SCORE=$(echo $RESPONSE | jq -r '.result.score // 0')&lt;/span&gt;
              &lt;span class="s"&gt;SUMMARY=$(echo $RESPONSE | jq -r '.result.summary // "No summary"')&lt;/span&gt;

              &lt;span class="s"&gt;echo "  Score: $SCORE/100 — $SUMMARY"&lt;/span&gt;

              &lt;span class="s"&gt;TOTAL=$((TOTAL + SCORE))&lt;/span&gt;
              &lt;span class="s"&gt;COUNT=$((COUNT + 1))&lt;/span&gt;

              &lt;span class="s"&gt;if [ "$SCORE" -lt "$MIN_SCORE" ]; then&lt;/span&gt;
                &lt;span class="s"&gt;FAILED=$((FAILED + 1))&lt;/span&gt;
                &lt;span class="s"&gt;echo "  ❌ Below minimum score of $MIN_SCORE"&lt;/span&gt;
              &lt;span class="s"&gt;else&lt;/span&gt;
                &lt;span class="s"&gt;echo "  ✅ Passed"&lt;/span&gt;
              &lt;span class="s"&gt;fi&lt;/span&gt;
            &lt;span class="s"&gt;fi&lt;/span&gt;
          &lt;span class="s"&gt;done&lt;/span&gt;

          &lt;span class="s"&gt;if [ "$COUNT" -gt 0 ]; then&lt;/span&gt;
            &lt;span class="s"&gt;AVG=$((TOTAL / COUNT))&lt;/span&gt;
            &lt;span class="s"&gt;echo ""&lt;/span&gt;
            &lt;span class="s"&gt;echo "Average score: $AVG/100 across $COUNT files"&lt;/span&gt;
            &lt;span class="s"&gt;echo "Failed files: $FAILED"&lt;/span&gt;

            &lt;span class="s"&gt;if [ "$FAILED" -gt 0 ]; then&lt;/span&gt;
              &lt;span class="s"&gt;echo ""&lt;/span&gt;
              &lt;span class="s"&gt;echo "❌ Quality gate failed — $FAILED file(s) scored below $MIN_SCORE/100"&lt;/span&gt;
              &lt;span class="s"&gt;echo "Fix the issues flagged above and push again."&lt;/span&gt;
              &lt;span class="s"&gt;exit 1&lt;/span&gt;
            &lt;span class="s"&gt;else&lt;/span&gt;
              &lt;span class="s"&gt;echo "✅ Quality gate passed!"&lt;/span&gt;
            &lt;span class="s"&gt;fi&lt;/span&gt;
          &lt;span class="s"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push this file. That's it — your quality gate is live.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 — Test it
&lt;/h2&gt;

&lt;p&gt;Open a pull request with any code change. You'll see the &lt;strong&gt;AI Code Review&lt;/strong&gt; check appear in the PR checks section.&lt;/p&gt;

&lt;p&gt;If the code scores above 70/100 it passes with a green checkmark. Below 70 and it fails with details of exactly what needs fixing.&lt;/p&gt;

&lt;p&gt;Here's an example of what the output looks like in the Actions log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reviewing: src/api/users.js
  Score: 45/100 — Critical security issues found
  ❌ Below minimum score of 70

Reviewing: src/utils/helpers.ts  
  Score: 88/100 — Clean code with minor suggestions
  ✅ Passed

Average score: 66/100 across 2 files
Failed files: 1

❌ Quality gate failed — 1 file(s) scored below 70/100
Fix the issues flagged above and push again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 — Customize your threshold
&lt;/h2&gt;

&lt;p&gt;Change the &lt;code&gt;MIN_SCORE&lt;/code&gt; value in the workflow to match your team's standards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;MIN_SCORE=50&lt;/span&gt;   &lt;span class="c1"&gt;# Relaxed — catches only critical issues&lt;/span&gt;
&lt;span class="s"&gt;MIN_SCORE=70&lt;/span&gt;   &lt;span class="c1"&gt;# Standard — balanced quality control (recommended)&lt;/span&gt;
&lt;span class="s"&gt;MIN_SCORE=85&lt;/span&gt;   &lt;span class="c1"&gt;# Strict — high quality standard&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start at 70 and adjust based on your codebase. If you're adding this to an existing project, start lower (50-60) and raise it gradually as you fix existing issues.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it catches
&lt;/h2&gt;

&lt;p&gt;The AI reviews each changed file for:&lt;/p&gt;

&lt;p&gt;🔴 &lt;strong&gt;Critical&lt;/strong&gt; — SQL injection, XSS, hardcoded secrets, missing authentication checks&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Warnings&lt;/strong&gt; — missing error handling, off-by-one errors, memory leaks, deprecated patterns&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Suggestions&lt;/strong&gt; — performance improvements, best practice violations, refactoring opportunities&lt;/p&gt;

&lt;p&gt;Each issue comes with a specific fix — not vague advice like "improve this function" but actual code you can copy and apply.&lt;/p&gt;




&lt;h2&gt;
  
  
  Blocking merges on failure (optional)
&lt;/h2&gt;

&lt;p&gt;To prevent PRs from being merged when the quality gate fails:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your repo → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Branches&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add branch protection rule&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Branch name pattern: &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Require status checks to pass before merging&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Search for and select &lt;strong&gt;AI Code Review&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now the merge button is greyed out until the quality gate passes. Bad code literally cannot reach your main branch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;Most security vulnerabilities don't get caught in code review because reviewers are focused on logic and functionality — not scanning every line for SQL injection patterns or checking if secrets are hardcoded.&lt;/p&gt;

&lt;p&gt;Automated quality gates handle the first pass automatically. Your team still does the architectural review. The AI handles the security and bug check first — every single time, without getting tired.&lt;/p&gt;

&lt;p&gt;The result: your code review process focuses on what humans are actually good at — understanding business logic, architecture decisions, and edge cases — instead of playing grep for security vulnerabilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it free
&lt;/h2&gt;

&lt;p&gt;GetCodeReviews has a free tier with 10 reviews/month — enough to try it on your next PR.&lt;/p&gt;

&lt;p&gt;Pro plan ($29/month) includes 200 reviews, full GitHub Actions integration, VS Code inline diagnostics, and analytics to track your team's code quality over time.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://getcodereviews.com" rel="noopener noreferrer"&gt;getcodereviews.com&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built questions or hit an issue setting this up? Drop a comment below — I read and reply to every one.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>github</category>
    </item>
  </channel>
</rss>
