Skip to content
Open
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
95 changes: 95 additions & 0 deletions .github/workflows/sdk-proto-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: SDK Proto Check

on:
merge_group:
types: [checks_requested]
push:
branches:
- "pull-request/[0-9]+"
workflow_dispatch:

env:
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

permissions:
contents: read
packages: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
pr_metadata:
name: Resolve PR metadata
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.gate.outputs.should_run }}
matrix: ${{ steps.config.outputs.matrix }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- id: gate
uses: ./.github/actions/pr-gate

- id: config
name: Load SDK configuration
run: echo "matrix=$(jq -c '.include' tasks/sdk-sync-config.json)" >> "$GITHUB_OUTPUT"

sdk_proto_drift:
name: Proto Drift (${{ matrix.sdk.name }})
needs: pr_metadata
if: needs.pr_metadata.outputs.should_run == 'true'
runs-on: linux-amd64-cpu8
timeout-minutes: 15
container:
image: ghcr.io/nvidia/openshell/ci:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
strategy:
fail-fast: false
matrix:
sdk: ${{ fromJSON(needs.pr_metadata.outputs.matrix) }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install tools
run: mise install --locked

- name: Check proto drift
id: drift
run: |
REPORT=$(mise run ${{ matrix.sdk.drift_task }} 2>"$RUNNER_TEMP/drift_stderr.log") || true

if echo "$REPORT" | jq -e 'has("synced") and (.synced | type == "boolean")' >/dev/null 2>&1; then
SYNCED=$(echo "$REPORT" | jq -r '.synced')
DELIMITER="REPORT_EOF_$(openssl rand -hex 16)"
{
echo "report<<$DELIMITER"
echo "$REPORT"
echo "$DELIMITER"
} >> "$GITHUB_OUTPUT"
echo "synced=$SYNCED" >> "$GITHUB_OUTPUT"
else
echo "::warning::Proto drift check failed: unable to parse report"
Comment thread
Ygnas marked this conversation as resolved.
echo "stderr: $(cat "$RUNNER_TEMP/drift_stderr.log")"
echo "synced=error" >> "$GITHUB_OUTPUT"
fi

- name: Annotate drift warning
if: steps.drift.outputs.synced == 'false'
env:
DRIFT_REPORT: ${{ steps.drift.outputs.report }}
SDK_NAME: ${{ matrix.sdk.name }}
run: |
SUMMARY=$(echo "$DRIFT_REPORT" | jq -r '.summary')
FILES=$(echo "$DRIFT_REPORT" | jq -r '.files[] | select(.status != "synced") | " - \(.name) (\(.status), \(.diff_lines) lines changed)"' | sed ':a;N;$!ba;s/\n/%0A/g')
echo "::warning::SDK proto drift detected for ${SDK_NAME}: ${SUMMARY}%0A${FILES}"
149 changes: 149 additions & 0 deletions .github/workflows/sdk-sync-dashboard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

name: SDK Proto Sync

on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:

env:
MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

permissions:
actions: read
contents: read
packages: read
issues: write

concurrency:
group: sdk-proto-sync
cancel-in-progress: true

jobs:
load_config:
name: Load SDK configuration
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
matrix: ${{ steps.config.outputs.matrix }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: config
run: echo "matrix=$(jq -c '.include' tasks/sdk-sync-config.json)" >> "$GITHUB_OUTPUT"

sdk_sync_check:
Comment thread
Ygnas marked this conversation as resolved.
name: Sync Check (${{ matrix.sdk.name }})
needs: load_config
runs-on: linux-amd64-cpu8
timeout-minutes: 30
container:
image: ghcr.io/nvidia/openshell/ci:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
strategy:
fail-fast: false
matrix:
sdk: ${{ fromJSON(needs.load_config.outputs.matrix) }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
run: mise install --locked
Comment thread
Ygnas marked this conversation as resolved.
- name: Check proto drift and build
env:
SDK_NAME: ${{ matrix.sdk.name }}
DRIFT_TASK: ${{ matrix.sdk.drift_task }}
BUILD_CHECK_TASK: ${{ matrix.sdk.build_check_task }}
run: |
mkdir -p report
mise run "$DRIFT_TASK" > report/drift.json 2> report/drift.stderr || true
if ! jq -e 'has("synced") and (.synced | type == "boolean")' report/drift.json >/dev/null 2>&1; then
jq -n --arg sdk "$SDK_NAME" '{sdk:$sdk, has_drift:"error", build_failed:"false"}' > report/status.json
exit 0
fi
SYNCED=$(jq -r '.synced' report/drift.json)
if [ "$SYNCED" = "true" ]; then
jq -n --arg sdk "$SDK_NAME" '{sdk:$sdk, has_drift:"false", build_failed:"false"}' > report/status.json
exit 0
fi
if mise run "$BUILD_CHECK_TASK" > report/build.json 2> report/build.stderr; then
BUILD_FAILED=false
else
BUILD_FAILED=true
fi
jq -n --arg sdk "$SDK_NAME" --arg build_failed "$BUILD_FAILED" \
'{sdk:$sdk, has_drift:"true", build_failed:$build_failed}' > report/status.json
- name: Upload SDK report
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: sdk-sync-${{ matrix.sdk.name }}
path: report/
if-no-files-found: error
retention-days: 1

issue_management:
name: Manage Drift Issue (${{ matrix.sdk.name }})
needs: [load_config, sdk_sync_check]
if: always() && needs.load_config.result == 'success' && needs.sdk_sync_check.result == 'success'
runs-on: linux-amd64-cpu8
timeout-minutes: 5
container:
image: ghcr.io/nvidia/openshell/ci:latest
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
strategy:
fail-fast: false
matrix:
sdk: ${{ fromJSON(needs.load_config.outputs.matrix) }}
steps:
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: sdk-sync-${{ matrix.sdk.name }}
path: report
- name: Read SDK status
id: status
run: |
echo "has_drift=$(jq -r '.has_drift' report/status.json)" >> "$GITHUB_OUTPUT"
echo "build_failed=$(jq -r '.build_failed' report/status.json)" >> "$GITHUB_OUTPUT"
- name: Warn on drift detection error
if: steps.status.outputs.has_drift == 'error'
run: |
echo "::error::Drift detection failed for ${{ matrix.sdk.name }} SDK"
cat report/drift.stderr
exit 1
- if: steps.status.outputs.has_drift == 'true' && steps.status.outputs.build_failed == 'true'
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Install tools
if: steps.status.outputs.has_drift == 'true' && steps.status.outputs.build_failed == 'true'
run: mise install --locked
- name: Create or update drift issue
if: steps.status.outputs.has_drift == 'true' && steps.status.outputs.build_failed == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
RESULT=$(uv run python tasks/scripts/sdk_sync.py manage-issue \
--drift-report "$(cat report/drift.json)" \
--build-report "$(cat report/build.json)" \
--sdk "${{ matrix.sdk.name }}" \
--repo "$GITHUB_REPOSITORY" \
--label "${{ matrix.sdk.label }}")
echo "$RESULT" | jq .
ACTION=$(echo "$RESULT" | jq -r '.action // "unknown"')
if [ "$ACTION" = "error" ] || [ "$ACTION" = "unknown" ]; then
echo "::error::Issue management for ${{ matrix.sdk.name }} failed: $ACTION"
exit 1
fi
- name: Close resolved drift issue
if: steps.status.outputs.has_drift == 'false' || (steps.status.outputs.has_drift == 'true' && steps.status.outputs.build_failed == 'false')
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ISSUE=$(gh issue list --repo "$GITHUB_REPOSITORY" --label "${{ matrix.sdk.label }}" --state open --json number --jq '.[0].number')
if [ -n "$ISSUE" ]; then
gh issue close "$ISSUE" --repo "$GITHUB_REPOSITORY" --comment "SDK builds and tests pass after proto regeneration. Closing automatically."
echo "Closed issue #$ISSUE"
fi
48 changes: 11 additions & 37 deletions tasks/go.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,43 +138,17 @@ hide = true
["go:proto:check"]
description = "Verify generated Go SDK proto files are up to date"
dir = "sdk/go"
run = """
#!/usr/bin/env bash
set -euo pipefail

SDK_ROOT=$(pwd -P)
REPO_ROOT=$(cd ../.. && pwd -P)

for tool in buf protoc-gen-go protoc-gen-go-grpc; do
if ! command -v "$tool" &>/dev/null; then
echo "ERROR: $tool not found. Run 'mise install' to install it."
exit 1
fi
done

WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT

if find proto -maxdepth 1 -name '*.proto' -print -quit | grep -q .; then
echo "ERROR: sdk/go/proto contains copied proto sources."
echo "Proto sources belong in the repository root proto/ directory."
exit 1
fi

# Generate to temp directory with adjusted output path
CHECK_TEMPLATE=$(sed 's|out: sdk/go|out: '"$WORK_DIR"'|' buf.gen.yaml)
(cd "$REPO_ROOT" && buf generate --template "$CHECK_TEMPLATE")

DIFF_OUTPUT=$(diff -r "$WORK_DIR/proto" "$SDK_ROOT/proto" 2>&1) || true
run = 'bash ../../tasks/scripts/go_proto_check.sh text'
hide = true
Comment thread
Ygnas marked this conversation as resolved.

if [ -n "$DIFF_OUTPUT" ]; then
echo "ERROR: Generated proto files are out of date."
echo "Run 'mise run go:proto:gen' to regenerate."
echo ""
echo "$DIFF_OUTPUT"
exit 1
fi
["go:proto:drift"]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as said above, I would align the naming convention along side the typescript task (and add a sdk: prefix)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as #3123 (comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, same reasoning as above. Resolving.

description = "Check Go SDK proto drift and output a JSON report"
dir = "sdk/go"
run = 'bash ../../tasks/scripts/go_proto_check.sh json'
hide = true

echo "Proto check passed: generated files are up to date."
"""
["go:proto:build-check"]
description = "Run full Go SDK proto sync, generate, build, and test pipeline"
dir = "sdk/go"
run = 'bash ../../tasks/scripts/sdk_build_check.sh go gen=go:proto:gen build=go:build test=go:test'
hide = true
Loading
Loading