Skip to main content

Live tail GitHub Actions runs on git push

Project description

octotail

Live tail GitHub Action runs on git push. It's cursed.

Motivation

I really liked how Codecrafters test runs are mirrored back right in the terminal when you git push, so I thought: "surely this is something the gh CLI supports". It doesn't.

A couple of hours of messing with HTTPS mitm proxies, websockets, headless browsers, you-name-it, and octotail was born.

Wait, what?!

Invoked with a commit_sha (and optionally --workflow-name and/or --ref-name), it polls the GitHub API for a matching workflow run. When a job associated with the run starts, it instructs a headless chromium-based browser to visit the job's page.

The browser's traffic passes through a mitmproxy instance that it uses to extract the authenticated WebSocket subscriptions for live tailing.

The WebSocket address and subscribe messages are then passed to the tailing workers.

The headless browser tabs are cleaned up immediately after the WebSocket extraction, so the overhead is minimal. (well, it's still an empty browser)

Installation

Pre-install

  • python 3.12
  • a working chromium-based browser under /usr/bin/chromium

Make sure /usr/bin/chromium points to a working chromium-based browser.

If unsure, and on Arch:

paru ungoogled-chromium-bin

Pypi package

mkdir octotail && cd octotail
python3 -mvenv .venv && source .venv/bin/activate
pip3 install octotail

# or .bashrc, config.fish, etc.
echo "alias octotail='$(pwd)/.venv/bin/python3 $(pwd)/.venv/bin/octotail'" >> ~/.zshrc

Via git and make

git clone https://github.com/rarescosma/octotail.git
cd octotail
make
sudo make install

Via git - all manual

Clone the repo:

git clone https://github.com/rarescosma/octotail.git
cd octotail

Make a virtual environment, activate it, and install the package.

python3 -m venv .venv
source .venv/bin/activate
poetry install --no-dev
sudo ln -sf $(pwd)/octotail/main.py /usr/local/bin/octotail

Important: post-install

Run mitmproxy once and install its root certificate:

mitmproxy
^C

sudo trust anchor ~/.mitmproxy/mitmproxy-ca-cert.cer

Usage

# octotail --help

 Usage: octotail [OPTIONS] COMMIT_SHA                                                               
                                                                                                    
 Look for an active workflow run for the given <COMMIT_SHA> (and optionally --workflow and/or       
 --ref-name) and attempt to tail its logs.                                                          
 NOTE: the <COMMIT_SHA> has to be of the full 40 characters length.                                 
                                                                                                    
╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────────╮
│ *    commit_sha      TEXT  Full commit SHA that triggered the workflow. [default: None]          │
│                            [required]                                                            │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮
│ *  --gh-pat                         TEXT     GitHub personal access token. (for API auth)        │
│                                              [env var: _GH_PAT]                                  │
│                                              [required]                                          │
│ *  --gh-user                        TEXT     GitHub username. (for web auth) [env var: _GH_USER] │
│                                              [required]                                          │
│ *  --gh-pass                        TEXT     GitHub password. (for web auth) [env var: _GH_PASS] │
│                                              [required]                                          │
│    --gh-otp                         TEXT     GitHub OTP. (for web auth) [env var: _GH_OTP]       │
│                                              [default: None]                                     │
│    --workflow  -w                   TEXT     Only consider workflows with this name.             │
│    --ref-name  -r                   TEXT     Only consider workflows triggered by this ref.      │
│                                              Example: 'refs/heads/main'                          │
│    --repo      -R                   TEXT     Use this GitHub repo to look for workflow runs. If  │
│                                              unspecified, will look for a remote matching        │
│                                              'git@github.com:<user>/<repo>.git' in the current   │
│                                              directory.                                          │
│                                              Examples: 'user/repo' OR 'org_name/repo'            │
│    --headless      --no-headless             [env var: _HEADLESS] [default: headless]            │
│    --port                           INTEGER  [env var: _PORT]                                    │
│                                              [default: (random in range 8100-8500)]              │
│    --help                                    Show this message and exit.                         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯

Tail after push

A simple use case is tailing a workflow run right after git push:

git push origin main
octotail $(git rev-parse origin/main) -r refs/heads/main

Or if pushing a tag:

git push origin v1.0.42
octotail $(git rev-parse v1.0.42^{commit}) -r refs/tags/v1.0.42

Or if simply pushing the HEAD of the current branch:

git push
octotail $(git rev-parse HEAD)

As a post-receive hook

A slightly more advanced use case that allows streaming the run outputs on git push without invoking octotail explicitly, similar to Codecrafters test runs.

For this to work we'll need control over the remote's output, so we can't use the GitHub remote directly. Instead, we'll use a bare repository as our proxy remote and set up its post-receive hook to call octotail.

cd your-original-repo
export PROXY_REPO="/wherever/you/want/to/store/the/proxy-repo"

mkdir -p $PROXY_REPO
git clone --mirror "$(git remote get-url origin)" $PROXY_REPO
git remote add proxy $PROXY_REPO
# back to octotail
cd -

cp post-receive.sample $PROXY_REPO/hooks/post-receive

Edit $PROXY_REPO/hooks/post-receive and change things according to your setup:

  • set _GH_USER to your GitHub username
  • set _GH_PASS_CMD to a command that outputs the GitHub password, e.g. _GH_PASS_CMD="pass github.com"
  • if using 2FA - set _GH_OTP_CMD to a command that outputs an OTP token for the GitHub 2FA, e.g. _GH_OTP_CMD="totp github.com"
  • set _GH_PAT_CMD to a command that outputs your GitHub personal access token, e.g. _GH_PAT_CMD="pass github_pat"

NOTE: the hook assumes one is using zsh. The shebang can be changed to any other shell, but it's best to invoke it with the right flags to get an interactive, login shell. Useful to get access to custom functions and aliases.

That's it! (phew) - now try pushing to the proxy remote and check if the GitHub Actions workflow run logs are streaming right back:

cd your-original-repo
git commit --allow-empty -m 'test octotail'
git push proxy

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

octotail-1.0.7.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

octotail-1.0.7-py3-none-any.whl (16.8 kB view details)

Uploaded Python 3

File details

Details for the file octotail-1.0.7.tar.gz.

File metadata

  • Download URL: octotail-1.0.7.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.7 Linux/5.10.0-32-amd64

File hashes

Hashes for octotail-1.0.7.tar.gz
Algorithm Hash digest
SHA256 4e3dee5cc6e4cdea11dac8d94c5ed8857885ccfeca46dde1511ef5eddf3cc5d8
MD5 d6938e8b1c3241416c2dca0b175e05b2
BLAKE2b-256 d6af7e20bd8aa81510828c9de7cdcab75cf6f0a94103b4eb027acab702c060e4

See more details on using hashes here.

File details

Details for the file octotail-1.0.7-py3-none-any.whl.

File metadata

  • Download URL: octotail-1.0.7-py3-none-any.whl
  • Upload date:
  • Size: 16.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.12.7 Linux/5.10.0-32-amd64

File hashes

Hashes for octotail-1.0.7-py3-none-any.whl
Algorithm Hash digest
SHA256 f98620c8798c6dcb5bfbfceccaaab89cee31f7bc1d183be8eff2282bf782a319
MD5 e23b57f0e39dbae361c081275bbdaaa7
BLAKE2b-256 1585a3a3fe73a233ffcd0a3c83949202cb7adb09c3a10b13a14bdf825be68904

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page