How WebdriverIO is using Resend and GitHub Action to Pay Back their Contributor

14/2/2024 5-minute read

The WebdriverIO project has recently implemented a new automated system designed to streamline the disbursement of funds to project contributors - this blog post explores the workings of this process and discusses its potential applicability to other Open Source projects.

WebdriverIO, a project I’m proud to maintain, has recently forged partnerships with leading cloud vendors in the testing ecosystem. This collaboration has led to monthly donations, enabling us to establish governance policies focused on financially compensating our contributors. Our objective is clear: to reward every contributor who submits a pull request with a significant impact across our ecosystem’s projects, distributed through various GitHub organizations. Achieving this goal hinges on two pivotal principles:

  1. Ensuring that financial rewards are directed exclusively to genuine contributors on GitHub, eliminating any need for guesswork during the approval or rejection of expense claims.
  2. Minimizing the administrative burden on contributors seeking reimbursement, by automating the process as comprehensively as possible.

Being a member of the OpenJS Foundation mandates adherence to specific governance standards for WebdriverIO, including the signing of a contributor license agreement (CLA) by contributors. This requirement, while potentially daunting for new members, fortifies our expense process by verifying the email addresses of contributors, thereby simplifying their identification and facilitating direct engagement.

To preclude the possibility of fraudulent expense claims, our process initiates with an email to the pull request author. This email provides detailed instructions on claiming their stipend, a link to our Open Collective page (where our funds are managed), and, crucially, a randomly generated code to authenticate their claim. This ensures that only verified contributors can claim their rewards.

When I heart about @zenorocha and his company Resend I hoped there would be a day where I need such a service. Well, the day has come and I was excited to be able to send out well crafted, auto-generated emails using React showing the appreciation about peoples contribution. While it was initially difficult to come up with an email design myself, I found a nice template I just needed to adjust. After a couple of tweaks to the template I came up with a satisfying result:

Example Email

By setting a simple A-Record to the AWS Route 53 settings of the webdriver.io domain I was able to easily send emails on behalf of the WebdriverIO team, using a beautiful, well crafted design within less than an hour. I can’t imagine how long this would have taken me if I would have done this from scratch.

The email is sent to the mailbox specified by the pull request author, with myself included as a BCC recipient. My primary task is to cross-reference the code provided with what’s detailed in the contributor’s expense report. Given that the email undergoes verification by GitHub and adheres to the foundation’s CLA process, there’s minimal concern about the authenticity of the individual submitting the expense claim, reducing the likelihood of dealing with an impostor.

We tested this process and it worked great for us. However we came across a new issue quickly: how to scale and adopt this process to other ecosystem projects. We didn’t only wanted to expense folks contributing to the WebdriverIO core project but to all repositories that are part of the WebdriverIO and its community organization.

We came up with a simple GitHub Action that would cover the whole expense flow, including the process of detecting the PR authors email address and sending the email through Resend. Now all what’s needed to set up the same expense process in a WebdriverIO project is to create a simple GitHub workflow using the webdriverio/expense-action@v1 action, e.g. like this:


name: Expense Contribution

on:
  workflow_dispatch:
    inputs:
      prNumber:
        description: "Number of the PR (without #)"
        required: true
      amount:
        description: "The expense amount you like to grant for the contribution in $"
        required: true
        type: choice
        default: 25
        options: [25 ,50 ,100 ,150 ,200 ,250 ,300 ,350 ,400 ,450 ,500 ,550 ,600 ,650 ,700 ,750 ,800 ,850 ,900 ,950 ,1000]

jobs:
  # (optional): make sure that the expense workflow is triggered
  # by someone connected to a certain team, e.g. `technical-steering-committee`
  authorize:
    runs-on: ubuntu-latest
    steps:
      - uses: octokit/request-action@v2.1.9
        with:
          route: GET /orgs/:organisation/teams/:team/memberships/${{ github.actor }}
          team: technical-steering-committee
          organisation: webdriverio
        env:
          GITHUB_TOKEN: ${{ secrets.WDIO_BOT_GITHUB_TOKEN }}
  expense:
    needs: [authorize]
    runs-on: ubuntu-latest
    permissions:
      contents: write
      id-token: write
    steps:
      - name: Run Expense Flow
        uses: webdriverio/expense-action@v1
        with:
          prNumber: ${{ github.event.inputs.prNumber }}
          amount: ${{ github.event.inputs.amount }}
        env:
          RESEND_API_KEY: ${{ secrets.RESEND_API_KEY }}
          GH_TOKEN: ${{ secrets.WDIO_BOT_GITHUB_TOKEN }}

The workflow is initiated manually by the project maintainer responsible for reviewing and approving contributions. It requires input of the pull request number and the allocated stipend amount for the specific contribution. To prevent any awkward errors, such as accidentally adding an extra zero or omitting one, the stipend amount is chosen from a predefined list of values. This approach ensures that the selection of the stipend amount is deliberate and accurate.

Furthermore the workflow is initiated with a step that verifies that the person who triggered it is part of a certain team, in this case the technical steering committee. This makes it very intentional who can grant stipends to contributor since workflows can be triggered by members with different access roles.

This system simplifies the automation of reimbursing contributions from external collaborators. However, it doesn’t address the method of compensating project members, who are paid by the hour. Developing an automated process for this will be more challenging, especially considering that the WebdriverIO project also values support provided on Discord as a notable contribution. We’ll need to devise a new strategy to accommodate these complexities.

That said, I believe we found a solid approach that allows us to pay back contributors without much manual work involved. While it probably is possible to use Open Collectives API to automate the approval process as well I believe it makes sense to keep a last manual step in place to keep control about the overall process. With the GitHub Action in place we now can easily scale this to as many projects we want throughout multiple GitHub organizations.

If you are an OSS maintainer looking for a way to expense your contributors in a transparent and automated fashion, I hope this might give you some inspiration. You can easily fork the GitHub Action, update the email template and apply a similar process to your project. If you do so, please let me know as I am always curious about how folks approach this. On this note I want to thank Nicholas Zakas as his team at Eslint who have been a great model for defining governance around project donations and creating a sustainable open-source model.