DEV Community

Tom Larkworthy
Tom Larkworthy

Posted on • Originally published at observablehq.com on

Starting Github Action Workflows From Observable

Using Observable as the front end for Github Actions is a great way to provide a nice interface without the hassle of hosting anything. Recently I developed a notebook library which allows authenticated and unauthenticated users to kick off Action workflow via a repository dispatch.

A repository dispatch triggers Github Action workflows via an authenticated HTTP request. See the documentation on Github. From there you can do all kinds of things, even programmatically creating commits.

We document two major ways to trigger actions from an Observable notebook.

  1. authenticated, where notebook readers provide the access token to trigger a workflow
  2. pre-authenticated, where the notebook author configures a proxy using their own creds, so anybody can trigger workflows on the author's blessed path.

To use

import {dispatch, createDispatchProxy} from '@tomlarkworthy/repository-dispatch'
Enter fullscreen mode Exit fullscreen mode

Repository Dispatch Client Library for Observable

The authenticated dispatch function takes an access token, plus the other options, to perform the dispatch

Image description

async function dispatch(
  token,
  { owner, repo, event_type = "event_type", client_payload = undefined } = {}
)

Enter fullscreen mode Exit fullscreen mode

Example Usecase 1: Pass Personal Token In Notebook

To use our simple dispatch function, we need a Github API access token. A simple way is to ask the reader for one.

Image description

Note: If you use localStorageView you can remember the input across page sessions in local storage.

There are situations where you don't want the reader to provide a token. For this, we need to introduce a secure environment.

Example Usecase 2: Use Shared Secret Stored in Webcode.run to pre-authorize a configuration

Code executed on webcode.run is remote, and so secrets are not exposed to notebook readers. By creating a proxy to do the request, we can expose Github workflows to the public without requiring them to supply tokens. Instead, the secret can be set in the inline UI (or at @endpointservices/secrets). But default, the secret should be called github_token, but you can override this in the createDispatchProxy arguments.

Image description

which you can call to invoke a github workflow

Note, configuration of the dispatch function has to be done when creating the proxy so that the endpoint cannot be used against arbitrary repositories. An opt-in exception is that when the client_payload arg is set to undefined, the client can pass a value of client_payload as the first argument (this is to enable passing data into a workflow).

viewof remoteDispatch = createDispatchProxy({
  owner: "tomlarkworthy",
  repo: "octokit-test"
})
Enter fullscreen mode Exit fullscreen mode

The result of a createDispatchProxy call is a view. The UI is the default webcode.run UI, which provides a method of setting the secret once you are logged in. You will need to create a stored secret called github_token and bind it to the endpoint. If you forget to configure the secret, the underlying Octokit API will throw HTTPError: Not Found exceptions. Your notebook needs to be published for it to work when you are logged out.

The data channel of the returned createDispatchProxy view is a dispatch function. When called, it will run the dispatch remotely, but importantly, you do not need to pass any authentication credentials. So you can just place it in a button for anybody to use. Try mine below.

Image description
Refer to the source notebook for the interactive demo

The above workflow will trigger this workflow which in turn write back into the repository as a log entry found here. So you can see for yourself that your triggers are registered by inspecting the timestamps in the logs!

The example here will cause a commit to occur in a repository you would not normally have permissions to! Now imagine what is possible when you can offload storage into git repositories for public users on Observablehq!

Writing workflows

I recommend Triggering GitHub Actions Using Repository Dispatches for a good overview of the technique.

At the beginning of a workflow file (stored in /.github/workflows/<name>.yml) you announce how the workflow is triggered. For an externally HTTP triggered workflow you use repository_dispatch. You also can optionally restrict what the event_type must be through the types array property:-

name: HTTP triggered workflow
on:
  repository_dispatch:
  types: [start-example-workflow]

Enter fullscreen mode Exit fullscreen mode

Next, you list jobs with steps. Steps can include anything off the vast Github Actions marketplace or just simple shell scripting!

jobs:
  commit-timestamp:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Log workflow execution in log
        run: |
          mkdir -p ./log
          echo "$(date '+%Y-%m-%d %H:%M:%S') inbound HTTP" >> ./log/http.log
      - name: Commit updated log
        run: |
          git config --global user.name 'Log External HTTP'
          git config --global user.email 'robot@webcode.run'
          git add ./log/http.log
          git commit -am "Log inbound HTTP"
          git push

Enter fullscreen mode Exit fullscreen mode

Observable + Github Actions

Observable is a great way to provide a lightweight interactive UI with minimal development effort. When paired with Github actions you can use Observable to create a nice GUI over the Action primitives. You can also use Actions to enhance the Observable experience, for example, auto-backing up notebooks into a Github repo using the onversion hook.

Top comments (0)