Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions .github/workflows/capture-screen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Capture Gateway Screen

on:
workflow_dispatch:

env:
GCP_PROJECT_ID: interactivebrokersquant
GCP_WORKLOAD_IDENTITY_PROVIDER: projects/303168642265/locations/global/workloadIdentityPools/github-actions/providers/github-ibkr-gateway-main
GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT: ibkr-gateway-deploy@interactivebrokersquant.iam.gserviceaccount.com

jobs:
capture:
runs-on: ubuntu-latest
timeout-minutes: 8
permissions:
contents: read
id-token: write
env:
GCE_USER: ${{ vars.IB_GATEWAY_GCE_USER }}
GCE_INSTANCE_NAME: ${{ vars.IB_GATEWAY_INSTANCE_NAME }}
GCE_ZONE: ${{ vars.IB_GATEWAY_ZONE }}
SSH_PRIVATE_KEY_SECRET_NAME: ${{ vars.IB_GATEWAY_SSH_PRIVATE_KEY_SECRET_NAME }}
steps:
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v3
with:
workload_identity_provider: ${{ env.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT }}

- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v3
with:
project_id: ${{ env.GCP_PROJECT_ID }}
version: '>= 416.0.0'

- name: Prepare SSH key
run: |
set -euo pipefail

if [ -z "${SSH_PRIVATE_KEY_SECRET_NAME:-}" ]; then
echo "SSH_PRIVATE_KEY_SECRET_NAME is required." >&2
exit 1
fi

install -d -m 700 "$RUNNER_TEMP/ssh"
SSH_KEY_FILE="$RUNNER_TEMP/ssh/google_compute_engine"
ssh_private_key="$(gcloud secrets versions access latest \
--project "${GCP_PROJECT_ID}" \
--secret "${SSH_PRIVATE_KEY_SECRET_NAME}")"
printf '%s\n' "$ssh_private_key" | tr -d '\r' > "$SSH_KEY_FILE"
chmod 600 "$SSH_KEY_FILE"
ssh-keygen -y -f "$SSH_KEY_FILE" > "$SSH_KEY_FILE.pub"
chmod 644 "$SSH_KEY_FILE.pub"
echo "SSH_KEY_FILE=$SSH_KEY_FILE" >> "$GITHUB_ENV"

- name: Capture X11 screen
run: |
set -euo pipefail

for var_name in GCE_USER GCE_INSTANCE_NAME GCE_ZONE; do
if [ -z "${!var_name:-}" ]; then
echo "${var_name} is required." >&2
exit 1
fi
done

REMOTE_TARGET="${GCE_USER}@${GCE_INSTANCE_NAME}"
SSH_FLAGS=(
--project "${GCP_PROJECT_ID}"
--zone "${GCE_ZONE}"
--quiet
--tunnel-through-iap
--ssh-key-file "${SSH_KEY_FILE}"
--ssh-flag="-o ServerAliveInterval=30"
--ssh-flag="-o ServerAliveCountMax=4"
--ssh-flag="-o TCPKeepAlive=yes"
)
SCP_FLAGS=(
--project "${GCP_PROJECT_ID}"
--zone "${GCE_ZONE}"
--quiet
--tunnel-through-iap
--ssh-key-file "${SSH_KEY_FILE}"
--scp-flag="-o ServerAliveInterval=30"
--scp-flag="-o ServerAliveCountMax=4"
--scp-flag="-o TCPKeepAlive=yes"
)

remote_png="/tmp/ibkr-gateway-screen.png"
local_png="$RUNNER_TEMP/ibkr-gateway-screen.png"
REMOTE_COMMAND=$(cat <<'EOF'
set -euo pipefail

sudo docker exec -u root ib-gateway bash -lc '
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
if ! command -v xwd >/dev/null 2>&1 || ! command -v xwdtopnm >/dev/null 2>&1 || ! command -v pnmtopng >/dev/null 2>&1; then
apt-get update
apt-get install -y --no-install-recommends x11-apps netpbm
apt-get clean
rm -rf /var/lib/apt/lists/*
fi
export DISPLAY=:1
xwd -root -silent -out /tmp/ibkr-gateway-screen.xwd
xwdtopnm /tmp/ibkr-gateway-screen.xwd | pnmtopng > /tmp/ibkr-gateway-screen.png
chmod 0644 /tmp/ibkr-gateway-screen.png
'
sudo docker cp ib-gateway:/tmp/ibkr-gateway-screen.png /tmp/ibkr-gateway-screen.png
chmod 0644 /tmp/ibkr-gateway-screen.png
ls -lh /tmp/ibkr-gateway-screen.png
EOF
)

gcloud compute ssh "${REMOTE_TARGET}" "${SSH_FLAGS[@]}" --command "${REMOTE_COMMAND}"
gcloud compute scp "${REMOTE_TARGET}:${remote_png}" "${local_png}" "${SCP_FLAGS[@]}"
echo "SCREENSHOT_PATH=${local_png}" >> "$GITHUB_ENV"

- name: Upload screenshot
uses: actions/upload-artifact@v4
with:
name: ibkr-gateway-screen
path: ${{ env.SCREENSHOT_PATH }}
if-no-files-found: error