From c0c338874b01045b63ce89824dad1711df9afdbd Mon Sep 17 00:00:00 2001
From: charly-bg <85914018+charly-bg@users.noreply.github.com>
Date: Wed, 15 Jan 2025 14:27:11 -0300
Subject: [PATCH 1/3] chore: exclude some labels on enforce approvals workflow

---
 .github/workflows/enforce-group-approvals.yml | 197 +++++++++---------
 1 file changed, 94 insertions(+), 103 deletions(-)

diff --git a/.github/workflows/enforce-group-approvals.yml b/.github/workflows/enforce-group-approvals.yml
index b239e922d6..d15fadcdb2 100644
--- a/.github/workflows/enforce-group-approvals.yml
+++ b/.github/workflows/enforce-group-approvals.yml
@@ -7,111 +7,102 @@ on:
     types: [submitted, review_requested, ready_for_review]
 
 jobs:
+  setup-context:
+    runs-on: ubuntu-latest
+    outputs:
+      pr_number: ${{ steps.set-vars.outputs.pr_number }}
+      repo_owner: ${{ steps.set-vars.outputs.repo_owner }}
+      repo_name: ${{ steps.set-vars.outputs.repo_name }}
+
+    steps:
+      - name: Set PR number and repo details
+        id: set-vars
+        run: |
+          echo "Fetching context details..."
+          PR_NUMBER=${{ github.event.pull_request.number }}
+          if [ -z "$PR_NUMBER" ]; then
+            echo "::error::PR number is missing from the event context."
+            exit 1
+          fi
+
+          REPO_OWNER=${{ github.repository_owner }}
+          REPO_NAME=$(echo ${{ github.repository }} | cut -d'/' -f2)
+
+          echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
+          echo "repo_owner=$REPO_OWNER" >> $GITHUB_OUTPUT
+          echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
+
   enforce-approvals:
+    needs: setup-context
     runs-on: ubuntu-latest
+    env:
+      GH_TOKEN: ${{ secrets.ORG_ACCESS_TOKEN }}
+      PR_NUMBER: ${{ needs.setup-context.outputs.pr_number }}
+      REPO_OWNER: ${{ needs.setup-context.outputs.repo_owner }}
+      REPO_NAME: ${{ needs.setup-context.outputs.repo_name }}
 
     steps:
+      - name: Check for excluding labels
+        run: |
+          # Check if the label "auto-pr" is set
+          LABELS=$(gh api \
+            "/repos/$REPO_OWNER/$REPO_NAME/issues/$PR_NUMBER/labels" --jq '.[].name')
+
+          if echo "$LABELS" | grep -q "auto-pr"; then
+            echo "SKIP=true" >> $GITHUB_ENV
+            echo ">>> Skipping approval validation as 'auto-pr' label is set."
+            exit 0
+          fi
+
       - name: Validate Group Approvals
-        uses: actions/github-script@v6
-        with:
-          script: |
-            const fetchTeamMembers = async (teamSlug, token) => {
-              const url = `https://api.github.com/orgs/${context.repo.owner}/teams/${teamSlug}/members`;
-              console.log(`Fetching team members for team: ${teamSlug}`);
-
-              try {
-                const response = await fetch(url, {
-                  method: "GET",
-                  headers: {
-                    authorization: `Bearer ${token}`,
-                    accept: "application/vnd.github.v3+json",
-                  },
-                });
-
-                console.log("Response Status:", response.status, response.statusText);
-
-                const data = await response.json();
-                if (!response.ok) {
-                  console.error("Response Headers:", JSON.stringify([...response.headers], null, 2));
-                  throw new Error(`HTTP ${response.status} - ${data.message}`);
-                }
-
-                console.log(`Fetched Members for ${teamSlug}:`, data.map(member => member.login));
-                return data.map(member => member.login);
-              } catch (error) {
-                console.error(`Error fetching team members for ${teamSlug}:`, error.message);
-                throw error;
-              }
-            };
-
-            const fetchPullRequestReviews = async (token) => {
-              if (!context.payload.pull_request) {
-                throw new Error("This workflow must be triggered by a pull_request event.");
-              }
-
-              const url = `https://api.github.com/repos/${context.repo.owner}/${context.repo.repo}/pulls/${context.payload.pull_request.number}/reviews`;
-              console.log("Fetching PR reviews...");
-
-              try {
-                const response = await fetch(url, {
-                  method: "GET",
-                  headers: {
-                    authorization: `Bearer ${token}`,
-                    accept: "application/vnd.github.v3+json",
-                  },
-                });
-
-                console.log("Response Status:", response.status, response.statusText);
-
-                const data = await response.json();
-                if (!response.ok) {
-                  console.error("Response Headers:", JSON.stringify([...response.headers], null, 2));
-                  throw new Error(`HTTP ${response.status} - ${data.message}`);
-                }
-
-                console.log("Fetched PR Reviews:", data);
-                return data;
-              } catch (error) {
-                console.error("Error fetching PR reviews:", error.message);
-                throw error;
-              }
-            };
-
-            const token = process.env.ORG_ACCESS_TOKEN;
-            const QA_TEAM = "qa";
-            const DEV_TEAM = "explorer-devs";
-
-            // Fetch team members
-            const qaMembers = await fetchTeamMembers(QA_TEAM, token);
-            const devMembers = await fetchTeamMembers(DEV_TEAM, token);
-
-            // Fetch PR reviews
-            const reviews = await fetchPullRequestReviews(token);
-
-            // Filter unique APPROVED reviews
-            const uniqueApprovals = reviews.filter(
-              (review, index, self) =>
-                review.state === "APPROVED" &&
-                self.findIndex(r => r.user.login === review.user.login) === index
-            );
-
-            console.log("Unique Approvals:", uniqueApprovals.map(approval => approval.user.login));
-
-            // Validate approvals
-            const hasQaApproval = uniqueApprovals.some(review => qaMembers.includes(review.user.login));
-            const hasDevApproval = uniqueApprovals.some(review => devMembers.includes(review.user.login));
-
-            if (!hasQaApproval || !hasDevApproval) {
-              const missing = [
-                !hasQaApproval ? "QA approval" : null,
-                !hasDevApproval ? "DEV approval" : null,
-              ]
-                .filter(Boolean)
-                .join(" and ");
-
-              throw new Error(`PR must have at least 1 ${missing}.`);
-            }
-
-            console.log("PR has the required approvals.");
-        env:
-          ORG_ACCESS_TOKEN: ${{ secrets.ORG_ACCESS_TOKEN }}
+        if: env.SKIP != 'true'
+        run: |
+          # Define the teams
+          QA_TEAM="qa"
+          DEV_TEAM="explorer-devs"
+
+          # Fetch team members
+          fetch_team_members() {
+            local team_slug=$1
+            echo "Fetching team members for team: $team_slug"
+            gh api \
+              "/orgs/$REPO_OWNER/teams/$team_slug/members" --jq '.[].login'
+          }
+
+          QA_MEMBERS=$(fetch_team_members "$QA_TEAM")
+          DEV_MEMBERS=$(fetch_team_members "$DEV_TEAM")
+
+          echo ">>> QA Team Members: $QA_MEMBERS"
+          echo ">>> DEV Team Members: $DEV_MEMBERS"
+
+          # Fetch PR reviews
+          echo ">>> Fetching PR reviews for PR #$PR_NUMBER"
+          PR_REVIEWS=$(gh api \
+            "/repos/$REPO_OWNER/$REPO_NAME/pulls/$PR_NUMBER/reviews" --jq '.[] | select(.state == "APPROVED") | .user.login')
+
+          echo "Approved Reviews: $PR_REVIEWS"
+
+          # Validate approvals
+          HAS_QA_APPROVAL=false
+          HAS_DEV_APPROVAL=false
+
+          for reviewer in $PR_REVIEWS; do
+            if echo "$QA_MEMBERS" | grep -q "^$reviewer$"; then
+              HAS_QA_APPROVAL=true
+            fi
+
+            if echo "$DEV_MEMBERS" | grep -q "^$reviewer$"; then
+              HAS_DEV_APPROVAL=true
+            fi
+          done
+
+          if [ "$HAS_QA_APPROVAL" != true ] || [ "$HAS_DEV_APPROVAL" != true ]; then
+            MISSING=()
+            [ "$HAS_QA_APPROVAL" != true ] && MISSING+=("QA approval")
+            [ "$HAS_DEV_APPROVAL" != true ] && MISSING+=("DEV approval")
+            MISSING_MSG=$(IFS=", "; echo "${MISSING[*]}")
+            echo "::error::PR must have at least 1: $MISSING_MSG."
+            exit 1
+          fi
+
+          echo ">>> PR has the required approvals."

From b0f7b0ea4bbe74db896307306051159407b6221a Mon Sep 17 00:00:00 2001
From: charly-bg <85914018+charly-bg@users.noreply.github.com>
Date: Wed, 15 Jan 2025 14:34:40 -0300
Subject: [PATCH 2/3] chore: add additional types on pull requests triggers

---
 .github/workflows/enforce-group-approvals.yml | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/enforce-group-approvals.yml b/.github/workflows/enforce-group-approvals.yml
index d15fadcdb2..0c8176c3f0 100644
--- a/.github/workflows/enforce-group-approvals.yml
+++ b/.github/workflows/enforce-group-approvals.yml
@@ -4,7 +4,14 @@ on:
   pull_request:
     branches:
       - dev # Only run for PRs targeting the dev branch
-    types: [submitted, review_requested, ready_for_review]
+    types:
+      - submitted
+      - opened
+      - reopened
+      - synchronize
+      - review_requested
+      - ready_for_review
+      - labeled
 
 jobs:
   setup-context:

From e673db491ddc8579675dbd805ddf567d24ae2cd5 Mon Sep 17 00:00:00 2001
From: charly-bg <85914018+charly-bg@users.noreply.github.com>
Date: Wed, 15 Jan 2025 15:10:42 -0300
Subject: [PATCH 3/3] chore: add trigger for pull request review only on dev
 branch

---
 .github/workflows/enforce-group-approvals.yml | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/enforce-group-approvals.yml b/.github/workflows/enforce-group-approvals.yml
index 0c8176c3f0..0e19fbf2c1 100644
--- a/.github/workflows/enforce-group-approvals.yml
+++ b/.github/workflows/enforce-group-approvals.yml
@@ -2,19 +2,19 @@ name: Enforce QA and DEV Approvals
 
 on:
   pull_request:
-    branches:
-      - dev # Only run for PRs targeting the dev branch
     types:
-      - submitted
       - opened
       - reopened
       - synchronize
       - review_requested
       - ready_for_review
       - labeled
+      - unlabeled
+  pull_request_review:
 
 jobs:
   setup-context:
+    if: github.event.pull_request.base.ref == 'dev'
     runs-on: ubuntu-latest
     outputs:
       pr_number: ${{ steps.set-vars.outputs.pr_number }}
@@ -40,6 +40,7 @@ jobs:
           echo "repo_name=$REPO_NAME" >> $GITHUB_OUTPUT
 
   enforce-approvals:
+    if: github.event.pull_request.base.ref == 'dev'
     needs: setup-context
     runs-on: ubuntu-latest
     env: