DEV Community

loading...
Cover image for How I built a small ReactJS app to automatically invite collaborators to a private GitHub repo πŸ‘Œ

How I built a small ReactJS app to automatically invite collaborators to a private GitHub repo πŸ‘Œ

alexgurr profile image Alex Gurr ・3 min read

I currently maintain a GitHub repo called react-coding-challenges. It involves a variety of different difficulty challenges people can check out and complete. I also have a separate, private repository for the solutions to these challenges. The solutions are invite-only, meaning I need to invite each person as a collaborator before they get access (see the why here).

This was fine at the start, with a small amount of people requesting access. Now however, I have a steady stream of requests (usually via email which goes in to my spam folder) and it's becoming increasingly difficult/time consuming to manually do this process.

So what did I do? I built a MERN application that can automate this entire process with no-touch. Check it out at solutions.alexgurr.com.

How Does It Work?

Client

The user clicks the main CTA button cta

This uses a great library called react-github-login.

  import GitHubLogin from 'react-github-login';

  <GitHubLogin
    clientId="CLIENT_ID"
    onSuccess={joinRepo}
    onFailure={onFailure}

    // We only need the read:user scope to determine who the user is
    scope="read:user"

    // This is irrelevant because the auth window gets closed
    redirectUri=""

    // Use animate.css to give the button a pulse effect
    className={`button animate__animated animate__pulse animate__infinite animate__slow ${loading ? 'is-loading' : ''}`}
  >
    <div>
      <span className="icon">
        <i className="fab fa-github"></i>
      </span>
      <span>Let Me In</span>
    </div>
  </GitHubLogin>
Enter fullscreen mode Exit fullscreen mode

Β 

The library starts the GitHub OAuth login process and calls our callback with an oAuth code

  const joinRepo = async ({ code }) => {
    try {
      // The code gets sent to the server
      await axios.post(config.serverUrl, { code });

      setJoined(true);
    } catch(e) {
      // if it's a 409, the user is already in the repository
      if (e.response && e.response.status && e.response.status === 409) {
        setAlreadyIn(true);

        return void setJoined(true);
      }

      toast("Oops, something went wrong.", { type: 'error', position: "bottom-left", hideProgressBar: true })
    }
  }
Enter fullscreen mode Exit fullscreen mode

success

Β 

Server

Generate an access token for the user, using a client secret/id & the client code

  const { data } = await axios.post('https://github.com/login/oauth/access_token', {
    client_id: 'ID',
    client_secret: 'SECRET',
    code: code
  });
Enter fullscreen mode Exit fullscreen mode

Β 

Retrieve the user's information using the generated access token

  const { data: user } = await axios.get('https://api.github.com/user', {
    headers: { Authorization: `token ${data.split('&')[0].split('=')[1]}` }
  });
Enter fullscreen mode Exit fullscreen mode

Β 

Check if the user's a collaborator already

We use the @octokit/rest library for the more complex GitHub API actions, which is a node GitHub SDK

  await octokit.repos.checkCollaborator({
    owner: GITHUB_UN,
    repo: 'react-coding-solutions',
    username
  });
Enter fullscreen mode Exit fullscreen mode

If they are already a collaborator, we return at this point and return a response with 409 status code.

Β 

Invite the user as a collaborator and return a success (201) response

  await octokit.repos.addCollaborator({
    owner: GITHUB_UN,
    repo: 'react-coding-solutions',
    username
  });
Enter fullscreen mode Exit fullscreen mode

Β 

Store the user record in our database

We use mongodb and mongoose as our user record store. This record write is non-blocking and we don't wait for it to finish before returning a response.

  User.create({ username });
Enter fullscreen mode Exit fullscreen mode

Β 
Β 
Overall, this was quite an easy app to build. I hope this gives some insight into how you could invite users to GitHub repos, or provide some inspiration to go and automate things!

Discussion (0)

Forem Open with the Forem app