Skip to content
Merged
Show file tree
Hide file tree
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
73 changes: 59 additions & 14 deletions .github/workflows/remote-maintenance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ name: Remote Gateway Maintenance
on:
workflow_dispatch:
inputs:
target:
description: Gateway target (from IB_GATEWAY_TARGETS_JSON)
required: false
default: all
type: string
action:
description: Maintenance action to run on the gateway VM
required: true
Expand All @@ -15,32 +20,72 @@ on:
- restart-gateway
- status

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

concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: false

jobs:
resolve:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.resolve.outputs.matrix }}
steps:
- name: Resolve gateway targets
id: resolve
env:
TARGETS_JSON: ${{ vars.IB_GATEWAY_TARGETS_JSON }}
SELECTED_TARGET: ${{ github.event.inputs.target || 'all' }}
run: |
import json, os, sys
raw = os.environ.get("TARGETS_JSON", "").strip()
if not raw: raise SystemExit("IB_GATEWAY_TARGETS_JSON is required")
loaded = json.loads(raw)
targets = []
if isinstance(loaded, dict):
for name, config in loaded.items():
cfg = dict(config); cfg["name"] = name; targets.append(cfg)
elif isinstance(loaded, list):
targets = loaded
else:
raise SystemExit("IB_GATEWAY_TARGETS_JSON must be an object or list")
selected_name = os.environ.get("SELECTED_TARGET", "all")
if selected_name == "all":
selected = targets
else:
selected = [t for t in targets if t["name"] == selected_name]
if not selected:
known = ", ".join(t["name"] for t in targets)
raise SystemExit(f"Unknown target {selected_name!r}. Known: {known}")
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
f.write("matrix=" + json.dumps({"target": selected}, separators=(",", ":")) + "\n")
print("Targets: " + ", ".join(t["name"] for t in selected))
shell: python3

maintenance:
needs: resolve
if: needs.resolve.outputs.matrix != '{"target":[]}'
runs-on: ubuntu-latest
timeout-minutes: 8
strategy:
matrix: ${{ fromJson(needs.resolve.outputs.matrix) }}
fail-fast: false
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 }}
DEPLOY_PATH: ${{ vars.IB_GATEWAY_DEPLOY_PATH }}
IB_GATEWAY_MODE: ${{ vars.IB_GATEWAY_MODE }}
IB_GATEWAY_CONTAINER_NAME: ${{ vars.IB_GATEWAY_CONTAINER_NAME }}
IB_GATEWAY_COMPOSE_SERVICE_NAME: ${{ vars.IB_GATEWAY_COMPOSE_SERVICE_NAME }}
IB_GATEWAY_UNIT_SUFFIX: ${{ vars.IB_GATEWAY_UNIT_SUFFIX }}
SSH_PRIVATE_KEY_SECRET_NAME: ${{ vars.IB_GATEWAY_SSH_PRIVATE_KEY_SECRET_NAME }}
TARGET_NAME: ${{ matrix.target.name }}
GCP_PROJECT_ID: ${{ matrix.target.gcp_project_id }}
GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ matrix.target.gcp_workload_identity_provider }}
GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT: ${{ matrix.target.gcp_workload_identity_service_account }}
GCE_USER: ${{ matrix.target.gce_user }}
GCE_INSTANCE_NAME: ${{ matrix.target.gce_instance_name }}
GCE_ZONE: ${{ matrix.target.gce_zone }}
DEPLOY_PATH: ${{ matrix.target.deploy_path }}
IB_GATEWAY_MODE: ${{ matrix.target.mode }}
IB_GATEWAY_CONTAINER_NAME: ${{ matrix.target.container_name }}
IB_GATEWAY_COMPOSE_SERVICE_NAME: ${{ matrix.target.compose_service_name }}
IB_GATEWAY_UNIT_SUFFIX: ${{ matrix.target.unit_suffix || '' }}
SSH_PRIVATE_KEY_SECRET_NAME: ${{ matrix.target.ssh_private_key_secret_name }}
MAINTENANCE_ACTION: ${{ github.event.inputs.action }}
steps:
- name: Authenticate to Google Cloud
Expand Down
8 changes: 4 additions & 4 deletions tests/test_workflow_shared_config.sh
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ done
grep -Fq 'stop-gateway' "$maintenance_workflow_file"
grep -Fq 'restart-gateway' "$maintenance_workflow_file"
grep -Fq 'status' "$maintenance_workflow_file"
grep -Fq 'DEPLOY_PATH: ${{ vars.IB_GATEWAY_DEPLOY_PATH }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_MODE: ${{ vars.IB_GATEWAY_MODE }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_CONTAINER_NAME: ${{ vars.IB_GATEWAY_CONTAINER_NAME }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_COMPOSE_SERVICE_NAME: ${{ vars.IB_GATEWAY_COMPOSE_SERVICE_NAME }}' "$maintenance_workflow_file"
grep -Fq 'DEPLOY_PATH: ${{ matrix.target.deploy_path }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_MODE: ${{ matrix.target.mode }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_CONTAINER_NAME: ${{ matrix.target.container_name }}' "$maintenance_workflow_file"
grep -Fq 'IB_GATEWAY_COMPOSE_SERVICE_NAME: ${{ matrix.target.compose_service_name }}' "$maintenance_workflow_file"
grep -Fq 'sudo systemctl disable --now' "$maintenance_workflow_file"
grep -Fq 'sudo docker update --restart=no "${container_name}"' "$maintenance_workflow_file"
grep -Fq 'sudo docker compose down' "$maintenance_workflow_file"
Expand Down
Loading