Repository: nulib/dc-api-v2
Pull request #312: Update broken action & PR creation workflow
Author: login: charlesLoder
Created: 2025-05-07T20:17:29Z | Merged: 2025-05-08T19:24:06Z

## Summary of changes

I didn't squash the commits yet, just for clarity into the changes for now.

- Update the event used from `pull_request_target` to `pull_request`
  - The check of `github.event_name == 'pull_request'` is why it was being skipped as they're different events
- Update the node version being used
- Add a naive `package.json` check
  - it doesn't check if the `version` field has been updated — the logic around that got a little gnarly, but it does check if they were changed
- It removes Mat as the sole PR reviewer

## Assigning reviewers

Instead of just assigning one person as the reviewer, I:

- created a new Github [team](https://github.com/orgs/nulib/teams/repodev-code-review) (so far it's only me)
- a [PR in the types repo](https://github.com/nulib/dcapi-types/pull/15) adds a CODEOWNERS file which assigns the "team" as the reviewer
- the team has a rule set up to round robin reviewers:

<img width="837" alt="image" src="https://github.com/user-attachments/assets/fe58532e-12e6-4cbc-9dfb-8405cc3a37a9" />

Note: this means the `repodev_planning_and_docs` issue doesn't have anyone assigned


Diff:
diff --git a/.github/workflows/production-types.yml b/.github/workflows/production-types.yml
index b298d4d8..5799dbed 100644
--- a/.github/workflows/production-types.yml
+++ b/.github/workflows/production-types.yml
@@ -1,6 +1,6 @@
 name: Generate typescript and create PR into nulib/dcapi-types@main
 on:
-  pull_request_target:
+  pull_request:
     types:
       - closed
     branches:
@@ -30,10 +30,32 @@ jobs:
         uses: actions/checkout@v3
         with:
           path: "${{ env.TMP_SRCDIR }}"
-      - uses: actions/setup-node@v3
+          fetch-depth: 0
+      - name: Find all package.json files and check if they were updated
+        run: |
+          # Find all package.json files in the repo
+          PACKAGE_FILES=$(find . -name "package.json" -not -path "*/node_modules/*")
+
+          UNCHANGED_FILES=()
+          
+          # Check each package.json
+          for PKG_FILE in $PACKAGE_FILES; do
+            if ! echo "$CHANGED_FILES" | grep -q "$PKG_FILE"; then
+              UNCHANGED_FILES+=("$PKG_FILE")
+            fi
+          done
+
+          if [ ${#UNCHANGED_FILES[@]} -gt 0 ]; then
+            echo "Warning: The following package.json files were not updated:"
+            for FILE in "${UNCHANGED_FILES[@]}"; do
+              echo "$FILE"
+            done
+            exit 1
+          fi
+      - uses: actions/setup-node@v4
         with:
           cache-dependency-path: "${{ env.TMP_SRCDIR }}/api/package-lock.json"
-          node-version: 16.x
+          node-version: 20.x
           cache: "npm"
       - name: Set short git commit SHA
         working-directory: "${{ env.TMP_SRCDIR }}"
@@ -68,25 +90,43 @@ jobs:
           git commit -m "nulib/dc-api-v2 v${{ steps.package-version.outputs.current-version}} release"
           git push origin HEAD
         shell: bash
-      - name: Open nulib/dcapi-client PR
+      - name: Open nulib/dcapi-types PR
         id: open-types-pr
         working-directory: "${{ env.TMP_DSTDIR }}"
         run: |
-          pr=$(gh pr create --base main --title "Update types for DC API release v${{ steps.package-version.outputs.current-version}}" --body "A new version of `nulib/dc-api-v2` has been released. Please review changes and release a new version of the types package if needed." --reviewer mathewjordan)
+          pr=$(gh pr create --base main --title "Update types for DC API release v${{ steps.package-version.outputs.current-version}}" --body "A new version of `nulib/dc-api-v2` has been released. Please review changes and release a new version of the types package if needed.")
           echo "pr=$pr" >> $GITHUB_OUTPUT
       - name: Report PR Creation
         run: |
           echo ":rocket: *PR Created:* $PR" >> $GITHUB_STEP_SUMMARY
         env:
-          PR: ${{ steps.open-types-pr.outputs.pr }}
+          PR: ${{ steps.open-types-pr.outputs.pr }} # the url of the PR
       - name: Checkout nulib/repodev_planning_and_docs
         uses: actions/checkout@v3
         with:
           path: "${{env.TMP_REPODEVDIR}}"
           repository: "nulib/repodev_planning_and_docs"
           token: ${{env.GH_TOKEN}}
+      # intentionally run this step after checking out nulib/repodev_planning_and_docs
+      # to ensure that the PR is created and assigned correctly
+      - name: Get PR reviewer handle
+        id: pr-reviewer
+        run: |
+          REVIEWER_LOGIN=$(gh pr view ${{ steps.open-types-pr.outputs.pr }} --json=reviewRequests --jq='.reviewRequests | map(select(.__typename == "User")) | .[0].login // empty')
+          DEFAULT_REVIEWER="mathewjordan"
+          if [[ -z "$REVIEWER_LOGIN" ]]; then
+            echo "handle=$DEFAULT_REVIEWER" >> $GITHUB_OUTPUT
+          else
+            echo "handle=$REVIEWER_LOGIN" >> $GITHUB_OUTPUT
+          fi
+        shell: bash
       - name: Open issue in nulib/repodev_planning_and_docs
         working-directory: "${{env.TMP_REPODEVDIR}}"
         run: |
-          gh issue create -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." -a mathewjordan -l "digital collections" -l "front end"
+          gh issue create \
+            -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" \
+            -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." \
+            -a ${{ steps.pr-reviewer.outputs.handle }} \
+            -l "digital collections" \
+            -l "front end"
         shell: bash
diff --git a/.github/workflows/staging-types.yml b/.github/workflows/staging-types.yml
index 505415f4..bd08d049 100644
--- a/.github/workflows/staging-types.yml
+++ b/.github/workflows/staging-types.yml
@@ -1,6 +1,6 @@
 name: Generate typescript and push to nulib/dcapi-types@staging
 on:
-  pull_request_target:
+  pull_request:
     types:
       - closed
     branches:
@@ -29,10 +29,32 @@ jobs:
         uses: actions/checkout@v3
         with:
           path: "${{ env.TMP_SRCDIR }}"
-      - uses: actions/setup-node@v3
+          fetch-depth: 0
+      - name: Find all package.json files and check if they were updated
+        run: |
+          # Find all package.json files in the repo
+          PACKAGE_FILES=$(find . -name "package.json" -not -path "*/node_modules/*")
+
+          UNCHANGED_FILES=()
+          
+          # Check each package.json
+          for PKG_FILE in $PACKAGE_FILES; do
+            if ! echo "$CHANGED_FILES" | grep -q "$PKG_FILE"; then
+              UNCHANGED_FILES+=("$PKG_FILE")
+            fi
+          done
+
+          if [ ${#UNCHANGED_FILES[@]} -gt 0 ]; then
+            echo "Warning: The following package.json files were not updated:"
+            for FILE in "${UNCHANGED_FILES[@]}"; do
+              echo "$FILE"
+            done
+            exit 1
+          fi
+      - uses: actions/setup-node@v4
         with:
           cache-dependency-path: "${{ env.TMP_SRCDIR }}/api/package-lock.json"
-          node-version: 16.x
+          node-version: 20.x
           cache: "npm"
       - name: get-npm-version
         id: package-version


Reviews:
user: login: kdid
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T20:56:07Z
user: login: charlesLoder
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-07T21:01:23Z
user: login: kdid
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T21:09:24Z

Review comments:
diff_hunk: @@ -88,5 +110,5 @@ jobs:
       - name: Open issue in nulib/repodev_planning_and_docs
         working-directory: "${{env.TMP_REPODEVDIR}}"
         run: |
-          gh issue create -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." -a mathewjordan -l "digital collections" -l "front end"
+          gh issue create -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." -l "digital collections" -l "front end"
path: .github/workflows/production-types.yml
user: login: kdid
body: But the CODEOWNERS + teams won't affect the Github issue will it? (If not, let's not remove Mat otherwise the issue will fall into oblivion.)
created_at: 2025-05-07T20:56:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -88,5 +110,5 @@ jobs:
       - name: Open issue in nulib/repodev_planning_and_docs
         working-directory: "${{env.TMP_REPODEVDIR}}"
         run: |
-          gh issue create -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." -a mathewjordan -l "digital collections" -l "front end"
+          gh issue create -t "Update nulib/dcapi-types for API release v${{ steps.package-version.outputs.current-version}}" -b "Review PR: ${{ steps.open-types-pr.outputs.pr}} and release nulib/dcapi-types if needed." -l "digital collections" -l "front end"
path: .github/workflows/production-types.yml
user: login: charlesLoder
body: You're right, it doesn't affect the issue creation, but I wasn't sure how necessary/relevant that is if someone is reviewing the PR anyways. I'll add Mat back in for the issue
created_at: 2025-05-07T21:01:22Z
author_association: NONE

PR comments:
user: login: kdid
created_at: 2025-05-07T20:58:07Z
body: Can we add the stuff about the teams and reviewers to the readme?

https://github.com/nulib/dc-api-v2?tab=readme-ov-file#dc-api-typescript-npm-package

It wouldn't hurt to add it to this readme as well: https://github.com/nulib/dcapi-types?tab=readme-ov-file#publishingupdating-types
author_association: CONTRIBUTOR
user: login: kdid
created_at: 2025-05-07T21:08:52Z
body: Once those ☝️  are done, approval 👍  from me - it looks good.  Hard to tell if it will work correctly until deploy. Maybe update the title of the PR though so our Git history stays meaningful. 🙏 
author_association: CONTRIBUTOR
user: login: charlesLoder
created_at: 2025-05-08T16:10:01Z
body: @kdid 

Did some testing and made the production action a little more robust

## Testing

First, the CODEOWNERS in `dcapi-types` was merged.

Next, I created a [PR](https://github.com/nulib/dcapi-types/pull/17) using the cli like the action

```bash
gh pr create --base main --title "Testing cli outputs" --body "Testing things - Charles"     
```

Next, the PR requested a review from the team, and then specifically you:

<img width="956" alt="image" src="https://github.com/user-attachments/assets/b03527e3-ae6c-4270-a32d-4e7b0bc8c71b" />

Next, using the cli, the reviewer can be requested:

```bash
gh pr view https://github.com/nulib/dcapi-types/pull/17 \
--json reviewRequests \
--jq '.reviewRequests | map(select(.__typename == "User")) | .[0].login // empty'
```

which gets the user handle — `kdid`

In the action, I added a step to do this, and if no reviewer is found, it defaults to mat.

---

The jq filtering can be tested using this:

```json
{ 
    "reviewRequests":
        [
            {
                "__typename": "User",
                "login": "kdid"
            }
        ]
}
```

on their [playground](https://play.jqlang.org/)

author_association: NONE
user: login: kdid
created_at: 2025-05-08T17:29:54Z
body: Looks good to me 👍 
author_association: CONTRIBUTOR