diff --git a/README.md b/README.md index 56106f4..fa68bfd 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ Works with both GitHub.com and GitHub Enterprise. ## Requirements - [gh CLI](https://cli.github.com/) (authenticated) -- [playwright-cli](https://github.com/microsoft/playwright-mcp) (browser mode only, not needed for `--release` mode) +- [playwright-cli](https://github.com/microsoft/playwright-mcp) (browser/direct mode, not needed for `--release` mode) +- [jq](https://jqlang.github.io/jq/) (direct mode only) ## Install @@ -92,6 +93,23 @@ After: ' gh-attach --issue 123 --image ./screenshot.png --release ``` +### Direct mode (GHE) + +For hosts configured in `~/.config/gh-attach/config`, direct mode is auto-enabled. This uploads via the upload policies API + curl, producing `user-attachments` URLs without creating release artifacts. + +```bash +# ~/.config/gh-attach/config +# direct_hosts=your-ghe-host.com + +gh-attach --issue 123 --image ./screenshot.png --host your-ghe-host.com --repo owner/repo +``` + +Use `--browser` to override and force browser mode: + +```bash +gh-attach --issue 123 --image ./screenshot.png --browser +``` + ### From file ```bash @@ -124,16 +142,39 @@ If no placeholder is present, images are appended to the end. | `--host ` | No | auto-detected | GitHub host (for Enterprise) | | `--release` | No | - | Use GitHub Releases API (no browser needed) | | `--release-tag ` | No | gh-attach-assets | Release tag for uploads | -| `--headed` | No | - | Show browser window (browser mode only) | +| `--browser` | No | - | Force browser mode (skip direct upload) | +| `--headed` | No | - | Show browser window | + +## Upload modes -## How it works +### Browser mode (default) 1. Create a comment with placeholder(s) 2. Open GitHub in browser via playwright-cli -3. Upload image(s) using GitHub's native upload +3. Upload image(s) using GitHub's native upload UI 4. Extract the uploaded URL(s) 5. Update the comment with `` tags +### Release mode (`--release`) + +1. Create a comment with placeholder(s) +2. Upload image(s) to a GitHub Release via `gh release upload` +3. Update the comment with release download URLs + +### Direct mode (auto-detected) + +1. Create a comment with placeholder(s) +2. Open GitHub in browser via playwright-cli (for authentication) +3. Trigger the file-attachment component to obtain upload policies +4. Upload file(s) via curl to the media server +5. Update the comment with `user-attachments` URLs + +Direct mode is auto-enabled for hosts listed in `~/.config/gh-attach/config`: + +``` +direct_hosts=host1.example.com,host2.example.com +``` + ## Notes - PR comments use the same API as issue comments (use PR number) diff --git a/bin/gh-attach b/bin/gh-attach index 6f539ba..b243afe 100755 --- a/bin/gh-attach +++ b/bin/gh-attach @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -euo pipefail -VERSION="0.5.2" +VERSION="0.6.0" # Use bundled playwright-cli if available (Homebrew installation) SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -24,7 +24,8 @@ Options: --host GitHub host (auto-detected) --release Use GitHub Releases for upload (no browser needed) --release-tag Release tag for uploads (default: gh-attach-assets) - --headed Run browser in headed mode (visible, browser mode only) + --browser Force browser mode (skip direct upload) + --headed Run browser in headed mode (visible) -h, --help Show help -v, --version Show version @@ -38,6 +39,16 @@ Upload Modes: Requires: gh CLI authentication only (no browser needed) Note: Creates a release tag in your repository + Direct mode (auto-detected): + Uses upload policies API via browser auth + curl upload. + Produces user-attachments URLs without release artifacts. + Auto-enabled for hosts listed in ~/.config/gh-attach/config + Use --browser to override and force browser mode. + +Configuration: + ~/.config/gh-attach/config + direct_hosts=host1,host2 Hosts that use direct upload mode + Placeholders: Single image (replaced by first image) Numbered placeholder for multiple images @@ -50,6 +61,9 @@ Examples: # Release mode (no browser, CLI auth only) gh-attach --issue 123 --image ./screenshot.png --release + # Force browser mode (override direct mode) + gh-attach --issue 123 --image ./screenshot.png --browser + # With custom body gh-attach --issue 123 --image ./e2e.png --body 'Result: ' USAGE @@ -69,6 +83,7 @@ body_file="" host="" headed="" use_release="" +use_browser="" release_tag="gh-attach-assets" while [[ $# -gt 0 ]]; do @@ -82,6 +97,7 @@ while [[ $# -gt 0 ]]; do --host) host="$2"; shift 2;; --release) use_release="true"; shift;; --release-tag) release_tag="$2"; shift 2;; + --browser) use_browser="true"; shift;; --headed) headed="--headed"; shift;; -h|--help) usage; exit 0;; -v|--version) echo "gh-attach $VERSION"; exit 0;; @@ -93,10 +109,10 @@ while [[ $# -gt 0 ]]; do esac done -# Check playwright-cli only for browser mode +# Check playwright-cli for browser and direct modes if [[ -z "$use_release" ]]; then if ! command -v playwright-cli >/dev/null 2>&1; then - echo "playwright-cli is required for browser mode. Install with: npm install -g @playwright/cli" >&2 + echo "playwright-cli is required for browser/direct mode. Install with: npm install -g @playwright/cli" >&2 echo "Or use --release flag for CLI-only mode (no browser needed)." >&2 exit 1 fi @@ -137,6 +153,33 @@ if [[ -z "$host" ]]; then host="$(echo "$repo_url" | sed -E 's#https?://([^/]+)/.*#\1#')" fi +# Determine upload mode based on config +use_direct="" +if [[ -z "$use_release" && -z "$use_browser" ]]; then + config_file="${XDG_CONFIG_HOME:-$HOME/.config}/gh-attach/config" + if [[ -f "$config_file" ]]; then + direct_hosts="" + while IFS= read -r line; do + line="${line%%#*}" + line="${line#"${line%%[![:space:]]*}"}" + line="${line%"${line##*[![:space:]]}"}" + [[ -z "$line" ]] && continue + if [[ "$line" == direct_hosts=* ]]; then + direct_hosts="${line#direct_hosts=}" + fi + done < "$config_file" + IFS=',' read -ra hosts_array <<< "$direct_hosts" + for dhost in "${hosts_array[@]}"; do + dhost="${dhost#"${dhost%%[![:space:]]*}"}" + dhost="${dhost%"${dhost##*[![:space:]]}"}" + if [[ "$host" == "$dhost" ]]; then + use_direct="true" + break + fi + done + fi +fi + # Normalize escaped HTML comments (e.g. <\!-- from bash history expansion) body="${body//<\\!--/