Git Product home page Git Product logo

create-linked-clubhouse-story's Introduction

Create Linked Clubhouse Story

This repository is currently unmaintained. The author of this code no longer uses Clubhouse. Now that Clubhouse has announced they are changing their name to Shortcut, this seems like a good time to drop maintainership of this project, since it will probably take a fair amount of work to fix this project to work with the new name.

This is a GitHub Action that will automatically create a story on Clubhouse when a pull request is opened, unless the pull request already has a link to a Clubhouse story in the description.

Basic Usage

Create a Clubhouse API token, and store it as an encrypted secret in your GitHub repository settings. Check the GitHub documentation for how to create an encrypted secret. Name this secret CLUBHOUSE_TOKEN.

Create a file named clubhouse.yml in the .github/workflows directory of your repository. Put in the following content:

on:
  pull_request:
    types: [opened, closed]

jobs:
  clubhouse:
    runs-on: ubuntu-latest
    steps:
      - uses: singingwolfboy/[email protected]
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
          project-name: Engineering
          opened-state-name: Started
          merged-state-name: Done
          closed-state-name: Abandoned

The project-name variable should contain the name of the Clubhouse project that you want the Clubhouse story to be associated with. The opened-state-name, merged-state-name, and closed-state-name variables should contain the name of the state that you want the Clubhouse story to be in when the pull request is opened, merged, and closed, respectively.

Disabled for Built-In Integration

Clubhouse already has an integration with GitHub. It works for the opposite use-case, assuming that the Clubhouse story exists before the pull request is created.

This Action will specifically check for branch names that follow the naming convention for this built-in integration. Any branch name that contains ch#### will be ignored by this Action, on the assumption that a Clubhouse story already exists for the pull request. The ch#### must be separated from leading or following text with either a / or a -. So, branches named ch1, prefix/ch23, prefix-ch123, ch3456/suffix, ch3456-suffux, prefix/ch987/suffix would match, but xch123 and ch987end would not.

Customizing the Pull Request Comment

You can customize the comment posted on pull requests using the comment-template variable, like this:

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    opened-state-name: Started
    merged-state-name: Done
    closed-state-name: Abandoned
    comment-template: >-
      Thanks for the pull request! [I've created a Clubhouse story
      for you.]({{{ story.app_url }}})

This comment template is processed using the Mustache templating system. It receives the Story object returned from the Clubhouse API. Note that you may want to use the triple mustache syntax to disable HTML escaping.

GitHub will automatically process the comment text as Markdown, so you can use features like links and images if you make your comment template output valid Markdown, as shown above.

If you don't provide a comment template, this action will use this comment template by default: Clubhouse story: {{{ story.app_url }}}

Customizing the Clubhouse Story Title and Body

You can customize the Clubhouse title and description when creating stories using the story-title-template and story-description-template variables, like this:

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    opened-state-name: Started
    merged-state-name: Done
    closed-state-name: Abandoned
    story-title-template: >-
      {{{ payload.repository.name }}} - {{{ payload.pull_request.title }}}
    story-description-template: >-
      :zap: New story created for pull request [**{{{ payload.pull_request.title }}}**]({{{ payload.pull_request.html_url }}})
      in repo **{{{ payload.repository.name }}}**.
      {{{ #payload.pull_request.body }}}
        The body of the PR is: {{{ payload.pull_request.body }}}
      {{{ /payload.pull_request.body }}}

The story title and body templates are processed using the Mustache templating system. It receives the Payload object returned from the GitHub API. Note that you may want to use the triple mustache syntax to disable HTML escaping. Also Clubhouse supports full Markdown formatting, emojis, and @ mentions. Feel free to use them to your heart's desire. ๐Ÿ˜ป

If you don't provide a title or body template, this action will simply use the Pull Request Title ({{{ payload.pull_request.title }}}) and Pull Request Body ({{{ payload.pull_request.body }}}) by default.

User Map

This Action does its best to automatically assign the created Clubhouse story to the person who created the GitHub pull request. However, due to limitations of the GitHub API and the Clubhouse API, this will only work automatically when the GitHub user and the Clubhouse user share the same primary email address. Even though both services allow you to add multiple secondary email addresses, only the primary email address is exposed in the API.

As a workaround, you can maintain a user map, which teaches this Action how to map GitHub users to Clubhouse users. The user map should be passed in the with section, and due to the limitations of GitHub Actions, must be a JSON formatted string. Here's an example:

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    user-map: |
      {
        "octocat": "12345678-9012-3456-7890-123456789012",
        "mona": "01234567-8901-2345-6789-012345678901"
      }

The keys of this JSON object must be GitHub usernames, while the values must be Clubhouse UUIDs that identify members. Unfortunately, these UUIDs are not exposed on the Clubhouse website; the best way to look them up is to go to the User Directory for your Clubhouse workspace, open the Developer Tools in your browser, find the API request for https://app.clubhouse.io/backend/api/private/members, and examine the API response to find the id for each user. Note that Clubhouse makes a distinction between a User and a Member: you need to look up the UUID for the Member object.

Ignored Users

You can also add a list of GitHub users to ignore for this integration by using the ignored-users input. Multiple users should be separated by commas.

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    ignored-users: hubot, dependabot

Only Users

You can also add a list of GitHub only-users for this integration. This works opposite of the ignored users list above. For example, if you wanted only PRs from a specific GitHub user such as dependabot PRs. Multiple users should be separated by commas.

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    only-users: dependabot

Iteration Support

Clubhouse supports the concept of iterations -- time-boxed periods of development for stories. You can configure this Action to automatically assign the Clubhouse stories it creates to Clubhouse iterations, using GitHub labels and Clubhouse groups to identify the correct iteration to use.

In order to use this feature, this Action makes a few assumptions about the way you use Clubhouse and GitHub:

  • We assume that each team has an associated Clubhouse group, and that Clubhouse iterations are associated with this group.
  • We assume that the correct iteration to use is the most recent in-progress iteration for the group, as determined by the "last updated" time. (However, you may exclude specific iterations by name.)
  • We assume that each team has an associated GitHub label, and that this label is applied to pull requests consistently. (You may do this manually, or use an automated system like the Labeler Action.)

If you want to use this feature, and you have a different workflow that does not match these assumptions, open a GitHub Issue on this repo and let's talk about it! Maybe we can find a way to make this Action support other workflows, as well.

If your workflow is compatible with these assumptions, and you want to use this feature, first you must modify the on section of your config file to include the labeled activity type for the pull_request event. For example:

on:
  pull_request:
    types: [opened, closed, labeled]

Next, provide a JSON-formatted string to the label-iteration-group-map input. This is used to map GitHub labels to Clubhouse groups. Here is an example:

- uses: singingwolfboy/[email protected]
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    clubhouse-token: ${{ secrets.CLUBHOUSE_TOKEN }}
    project-name: Engineering
    label-iteration-group-map: |
      {
        "Team Octocat": {
          "groupId": "12345678-9012-3456-7890-123456789012",
          "excludeName": "Backlog"
        },
        "Unicorns": {
          "groupId": "34567890-1234-5678-9012-345678901234"
        }
      }

In this example, "Team Octocat" and "Unicorns" are labels on GitHub. The "groupId" refers to the ID of the Clubhouse group that are associated with these respective teams. The "excludeName" key is optional; if provided, it is used to exclude specific iterations from consideration.

create-linked-clubhouse-story's People

Contributors

etipton avatar jdcargile avatar singingwolfboy avatar spang avatar toddburnside avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

create-linked-clubhouse-story's Issues

getOctokit

Today I tried to create a PR with the action installed but got this error

Run singingwolfboy/[email protected]
(node:2618) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'getOctokit' of undefined
    at Object.<anonymous> (/home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:513:42)
        at Generator.next (<anonymous>)
    at /home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:274:71
       at new Promise (<anonymous>)
    at module.exports.__webpack_modules__.24.__awaiter (/home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:270:12)
        at Object.getClubhouseURLFromPullRequest (/home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:503:12)
    at Object.<anonymous> (/home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:219:43)
        at Generator.next (<anonymous>)
    at /home/runner/work/_actions/singingwolfboy/create-linked-clubhouse-story/v1.4/dist/index.js:197:71
       at new Promise (<anonymous>)
	(node:2618) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)

I wonder if I should install some lib before running the action?

npm run lint causes `Unnecessary escape character` error on eslint

Steps to reproduce:

  1. Pull down repo.
  2. Run npm install
  3. Run npm lint
  4. You receive the following error.
./create-linked-clubhouse-story/src/util.ts
16:54  error  Unnecessary escape character: \/  no-useless-escape
16:71  error  Unnecessary escape character: \/  no-useless-escape

Not all PRs are worthy of a story

With our workflow, we end up with a lot of PRs that we don't need or want to track in clubhouse. This is cluttering up clubhouse.

I considered making a PR that would not create a PR if you put a token in a PR title or description, or not create a story for a draft PR, or something along those lines. But as I thought about it more, it seemed like a different approach would work better for us.

The clubhouse github integration is what I would consider opt-in. In order to associate a PR with a story, you need to name the branch with the story id in it, put a token in any of a number of places, or add a label to the PR. I think an opt-in approach to creating a new story for a PR would work better for us. For example, placing a token like [ch-new] in the PR description.

Another advantage of this approach is not needing to check all of the ways in which a story can be associated with an existing clubhouse story. This GitHub action currently only checks the branch name - so, I assume a new story would be created even if the PR was being associated with one of the other methods. This would eliminate the need to try to check all of the other ways. It would also allow the user to create a PR and associate it with an existing story later, without creating a spurious new story when the PR was created.

If you are interested in this approach, I could submit a PR with a new config key named something like opt-in-only. If set to true, it would only create the story if the [ch-new] token was in the PR description. It would skip the branch name check.

Create stories based on issues and labels

Hey @singingwolfboy,

is it possible to use this action to create linked clubhouse stories when labeling issues?

In best case, I would like to create label called "clubhouse" and whenever I assign this label to an existing issue, it creates the story.

on:
  pull_request:
    types: [opened, closed]

ignored-users

Hi, thanks for this it is looking great
I'm testing the ignored-users option but I'm getting this error

 ##[warning]Unexpected input(s) 'ignored-users', valid inputs are ['github-token', 'clubhouse-token', 'project-name', 'opened-state-name', 'closed-state-name', 'merged-state-name', 'comment-template', 'user-map']
 Run singingwolfboy/[email protected]
   with:
       github-token: ***
           clubhouse-token: ***
	   project-name: Explore
	   opened-state-name: Started
           merged-state-name: Done
           closed-state-name: Abandoned
           ignored-users: scala-steward
           comment-template: Clubhouse story: {{{ story.app_url }}}

I looked at the code and it seems it takes ignored-users maybe v1.3 refers to an older version?
Thanks for this tool, seems very useful

"create story" payload invalid w/r/t external_tickets

@singingwolfboy first of all, thanks for making this!

My issue: I tried it out and was getting a 400 error from the Clubhouse API. I took a look at the payload, and I think it's related to sending "external_tickets" rather than "external_links" -- maybe they changed their v3 API? https://clubhouse.io/api/rest/v3/#Stories

I forked this repo, made these changes, and it worked (without external links of course).

Just letting you know, thx for reading

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.