github icon indicating copy to clipboard operation
github copied to clipboard

fix: replace github search api with graphql in success lifecycle method

Open babblebey opened this issue 1 year ago • 8 comments
trafficstars

This Pull Request refactors the success lifecycle function replacing the usage of Github "Search API" with "GraphQL API".

Changes Made

  • Added buildAssociatedPRsQuery helper function to which builds GraphQL query for fetching associated PRs to a list of commit hash (sha). It does this by collecting a list of shas which maps down to a list of strings that leverages the GraphQL fragment enabling ability to request data of multiple commits in one request using GitObject.

    /**
     * Builds GraphQL query for fetching associated PRs to a list of commit hash (sha)
     * @param {Array<string>} shas
     * @returns {string}
     */
    export function buildAssociatedPRsQuery(shas) {
      return `#graphql
        query getAssociatedPRs($owner: String!, $repo: String!) {
          repository(owner: $owner, name: $repo) {
            ${shas
              .map((sha) => {
                return `commit${sha.slice(0, 6)}: object(oid: "${sha}") {
                ...on Commit {
                  associatedPullRequests(first: 100) {
                    nodes {
                      url
                      number
                      body
                    }
                  }
                }
              }`;
              })
              .join("")}
          }
        }
      `;
    }
    
  • Replaced the instance of the search api consumption with the getSearchQueries method integration with the graphql api integration, which was used to retrieve all associated pull requests.

    const { repository } = await octokit.graphql(
      buildAssociatedPRsQuery(shas),
      { owner, repo },
    );
    const associatedPRs = Object.values(repository).map(
      (item) => item.associatedPullRequests.nodes,
    );
    
  • Modified test suites in acknowledgement of the changes..

Related Issue

Fixes #644

Screencast/Screenshot

screencast-bpconcjcammlapcogcnnelfmaeghhagj-2024.06.24-14_54_49.webm

babblebey avatar Jun 13 '24 19:06 babblebey

requires some new dependencies

you don't need the @octokit/graphql dependency to mock graphql requests, you just mock the POST /graphql request like any other.

gr2m avatar Jun 14 '24 04:06 gr2m

you don't need the @octokit/graphql dependency to mock graphql requests, you just mock the POST /graphql request like any other.

Oh wow, I'll give that a shot... I already done too much if this is the case in my initial attempt 🫣

babblebey avatar Jun 14 '24 06:06 babblebey

Holler if you need help with this PR

gr2m avatar Jun 14 '24 16:06 gr2m

I ran it locally and got the following error

[8:46:26 PM] [semantic-release] › ℹ  Start step "success" of plugin "@semantic-release/github"
[8:46:27 PM] [semantic-release] › ✘  Failed step "success" of plugin "@semantic-release/github"
[8:46:27 PM] [semantic-release] › ✘  An error occurred while running semantic-release: Error: Parse error on "commit338966" (STRING) at [4, 9]
    at file:///Users/gr2m/code/semantic-release/semantic-release/node_modules/aggregate-error/index.js:23:26
    at Array.map (<anonymous>)
    at new AggregateError (file:///Users/gr2m/code/semantic-release/semantic-release/node_modules/aggregate-error/index.js:16:19)
    at file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/pipeline.js:55:13
    at async pluginsConfigAccumulator.<computed> [as success] (file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/index.js:87:11)
    at async run (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:218:3)
    at async Module.default (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:278:22)
    at async default (file:///Users/gr2m/code/semantic-release/semantic-release/cli.js:55:5) {
  locations: [ { line: 4, column: 9 } ],
  pluginName: '@semantic-release/github'
}
AggregateError: 
    Error: Parse error on "commit338966" (STRING) at [4, 9]
        at Array.map (<anonymous>)
        at file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/pipeline.js:55:13
        at async pluginsConfigAccumulator.<computed> [as success] (file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/index.js:87:11)
        at async run (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:218:3)
        at async Module.default (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:278:22)
        at async default (file:///Users/gr2m/code/semantic-release/semantic-release/cli.js:55:5)
    at file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/pipeline.js:55:13
    at async pluginsConfigAccumulator.<computed> [as success] (file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/index.js:87:11)
    at async run (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:218:3)
    at async Module.default (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:278:22)
    at async default (file:///Users/gr2m/code/semantic-release/semantic-release/cli.js:55:5) {
  errors: [
    Error: Parse error on "commit338966" (STRING) at [4, 9]
        at file:///Users/gr2m/code/semantic-release/semantic-release/node_modules/aggregate-error/index.js:23:26
        at Array.map (<anonymous>)
        at new AggregateError (file:///Users/gr2m/code/semantic-release/semantic-release/node_modules/aggregate-error/index.js:16:19)
        at file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/pipeline.js:55:13
        at async pluginsConfigAccumulator.<computed> [as success] (file:///Users/gr2m/code/semantic-release/semantic-release/lib/plugins/index.js:87:11)
        at async run (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:218:3)
        at async Module.default (file:///Users/gr2m/code/semantic-release/semantic-release/index.js:278:22)
        at async default (file:///Users/gr2m/code/semantic-release/semantic-release/cli.js:55:5) {
      locations: [Array],
      pluginName: '@semantic-release/github'
    }
  ]

In order to run it locally, checkout the semantic-release/semantic-release repo and the semantic-release/github repo. Run npm install in both. Then in the semantic-release folder, run npm install <relative path to the github folder> (e.g. in my case on Mac OS, the folders are next to each other, I ran npm install ../github.

The way I ran it locally is as follows

  1. Create a test repository with a package.json, set "version": "0.0.0-development"

  2. check it out locally

  3. Add a commit with feat: initial version or similar (git commit --allow-empty -m 'feat: initial version')

  4. Make sure you are signed out of npm locally (run npm logout)

  5. Create a classic automation token on npm (https://www.npmjs.com/settings//tokens/`)

  6. Create a personal access token with the repo scope

  7. Set the following environment variables

    CI=true
    GITHUB_ACTIONS=true
    GITHUB_REF=master
    GITHUB_SHA=<latest commit sha>
    GITHUB_RUN_ID=1
    GITHUB_REPOSITORY=<your full repository name (owner/repo)>
    GITHUB_WORKSPACE=<path to current folder>
    NPM_TOKEN=<your npm token>
    GITHUB_TOKEN=<your github token>
    
  8. Run the following command in your local clone of the test repository

    <path to semantic-release folder>/bin/semantic-release.js
    

Not sure if this could be streamlined ... but we should document it somewhere for future reference and improve if we can 😁

gr2m avatar Jun 15 '24 03:06 gr2m

It's possible that this error is an edge case that only happens because I ran it locally. The commit only exist on my machine due to the local testing. When your query is sent, the commit does not exist and probably returns null or even an error. If that happens, I'd simply ignore the commit and move on to the next one

gr2m avatar Jun 15 '24 04:06 gr2m

It's possible that this error is an edge case that only happens because I ran it locally. The commit only exist on my machine due to the local testing. When your query is sent, the commit does not exist and probably returns null or even an error. If that happens, I'd simply ignore the commit and move on to the next one

@gr2m, I figured it was a GraphQL error... turned out I had a some part of the query returned string (from the buildAssociatedPRsQuery) wrongly typed... i.e. the alias text and the oid.

I have recorded and added a screencast to description above.

babblebey avatar Jun 21 '24 14:06 babblebey

Great work! I'd like to see that the success step actually posts a comment, we can pair on it during our checkin today

gr2m avatar Jun 21 '24 17:06 gr2m

Hi @gr2m, turns out the reason why the comment wasn't posting to only merged PRs and not the associated closed/fixed issue is because I failed to retrieve the body property on the graphql fetched associatedPRs, hence no PR body to parse the associated closed/fixed issueNumber from.

Kindly checkout description for updated Demo Video, also PRs and Issue below...

  • https://github.com/babblebey/sr/issues/8
  • https://github.com/babblebey/sr/pull/7

🤦

babblebey avatar Jun 24 '24 14:06 babblebey

How fitting that the release of this fix also ran into the secondary rate limit issue: https://github.com/semantic-release/github/actions/runs/9748385825/job/26903265854 (but that was still using the old code though)

gr2m avatar Jul 01 '24 17:07 gr2m

(but that was still using the old code though)

I sigh in relief**** 😮‍💨

babblebey avatar Jul 01 '24 17:07 babblebey