Starting Github Action Workflows From Observable
Tom Larkworthy
Posted on December 27, 2021
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.
- authenticated, where notebook readers provide the access token to trigger a workflow
- 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'
Repository Dispatch Client Library for Observable
The authenticated dispatch function takes an access token, plus the other options, to perform the dispatch
async function dispatch(
token,
{ owner, repo, event_type = "event_type", client_payload = undefined } = {}
)
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.
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.
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"
})
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.
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]
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
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.
Posted on December 27, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.