iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🪦

When a Custom CLI Tool's Mission Ends: Replacing gh-attach with playwright-cli

に公開

Eyecatch

Introduction

Previously, I created a CLI tool called gh-attach for uploading images to GitHub Issues and Pull Requests.

https://zenn.dev/atani/articles/gh-attach-github-image-upload

GitHub does not provide an API for uploading images to Issue comments. While you can drag and drop images in the Web UI, you cannot attach them via CLI or CI. To overcome this limitation, I built a tool that automates browser operations using Playwright and expanded it to support three different upload modes.

I have now archived gh-attach because playwright-cli can now achieve what I originally wanted to do.

Problems gh-attach Solved

GitHub's Issue comment API only accepts Markdown text in the body parameter. The image upload destination, uploads.github.com, does not accept authentication via OAuth tokens and requires a browser session cookie.

gh-attach took three approaches to address this limitation.

Mode Method Characteristics
Browser Operates the browser via Playwright to upload images Default
Release Uploads images to GitHub Releases and retrieves the URL No browser required, but images disappear if the release is reverted
Direct Obtains the upload policy from the browser and uploads via curl Targeted at GitHub Enterprise (GHE)

All modes were built on the premise of "using a browser as a workaround because GitHub lacks the necessary API."

gh-attach Stopped Working

The turning point was the update to GHE 3.19. The Direct mode of gh-attach relied on obtaining the upload policy API and uploading files with curl, but starting with GHE 3.19, fetching that API began to fail.

Browser mode also required constant maintenance to keep up with GHE UI changes because it ran Playwright scripts internally. I realized there was a limit to how long I could keep hacking GitHub's internal APIs with a custom tool.

Solving it with playwright-cli's File Chooser

What I could use instead was playwright-cli, released by Microsoft. It is a tool that provides browser operations as CLI commands, allowing me to directly execute what gh-attach was doing internally by combining commands.

The procedure is as follows:

# 1. Open the Issue page with Playwright
playwright-cli open "https://github.com/owner/repo/issues/123"

# 2. Get the page structure and check the element's ref number
playwright-cli snapshot

# 3. Click the "Paste, drop, or click to add files" button
playwright-cli click <ref>

# 4. The file chooser opens, so specify the image
#    → After the upload is complete, the following is automatically inserted into the text area:
#      ![image](https://github.com/.../user-attachments/assets/xxx)

# 5. Extract the URL from the text area
playwright-cli snapshot

The key point is that the comment submission itself is not done via playwright-cli. We only retrieve the user-attachments URL automatically inserted into the text area and perform the actual comment posting using gh api. This keeps browser interaction to a minimum.

The custom implementation of upload policy retrieval and fetch interception that gh-attach had is no longer necessary. Since it simply uses the file attachment functionality provided by the GitHub UI, it becomes easier to follow GHE version updates.

Retrospective

When I started developing gh-attach, playwright-cli did not exist. Therefore, gh-attach was a necessary tool.

Looking back, however, the essence of what gh-attach was doing was "automating the browser's file attachment UI to retrieve image URLs." If playwright-cli had existed from the beginning, it would have only taken a few lines of shell script to accomplish.

The lessons learned in the process of growing my own tool have not been in vain. The implementation of Browser mode, the revert issue with Release mode and the evolution into Direct mode, and the techniques of fetch interception. However, an approach that relied on GitHub's internal APIs always carried the risk of breaking with every update. The approach of playwright-cli, which directly automates the official UI, is simpler and more robust.

Archiving gh-attach

I have archived the gh-attach repository. I've included the alternative method using playwright-cli in the README.

If you are already using gh-attach, please consider migrating to playwright-cli.

Discussion