Repository navigation
ci: SDK publish workflows (OIDC trusted publishing, tag-gated) #7601
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| name: sdk publish crates | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - "mux-sdk-v*" | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "SDK version to validate/publish, for example 0.1.0" | ||
| required: true | ||
| type: string | ||
|
|
||
| permissions: {} | ||
|
|
||
| concurrency: | ||
| group: sdk-publish-crates-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| version: | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| permissions: | ||
| contents: read | ||
| outputs: | ||
| version: ${{ steps.version.outputs.version }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Validate tag and package versions | ||
| id: version | ||
| env: | ||
| DISPATCH_VERSION: ${{ inputs.version }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then | ||
| [[ "$GITHUB_REF_NAME" =~ ^mux-sdk-v[0-9]+\.[0-9]+\.[0-9]+$ ]] || { | ||
| echo "tag must match mux-sdk-vX.Y.Z" >&2 | ||
| exit 1 | ||
| } | ||
| version="${GITHUB_REF_NAME#mux-sdk-v}" | ||
| else | ||
| version="$DISPATCH_VERSION" | ||
| [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { | ||
| echo "workflow_dispatch version must match X.Y.Z" >&2 | ||
| exit 1 | ||
| } | ||
| fi | ||
| python3 - "$version" <<'PY' | ||
| import json | ||
| import pathlib | ||
| import sys | ||
| import tomllib | ||
|
|
||
| expected = sys.argv[1] | ||
| root = pathlib.Path.cwd() | ||
| versions = { | ||
| "typescript package.json": json.loads((root / "mux/bindings/typescript/package.json").read_text())["version"], | ||
| "python pyproject.toml": tomllib.loads((root / "mux/bindings/python/pyproject.toml").read_text())["project"]["version"], | ||
| "rust Cargo.toml": tomllib.loads((root / "mux/bindings/rust/Cargo.toml").read_text())["package"]["version"], | ||
| } | ||
| mismatches = {name: got for name, got in versions.items() if got != expected} | ||
| if mismatches: | ||
| for name, got in mismatches.items(): | ||
| print(f"{name}: expected {expected}, got {got}", file=sys.stderr) | ||
| raise SystemExit(1) | ||
| print(f"All package versions match {expected}") | ||
| PY | ||
| echo "version=$version" >> "$GITHUB_OUTPUT" | ||
|
|
||
| bindings-e2e-rust: | ||
| needs: version | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| timeout-minutes: 40 | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Init ghostty submodule | ||
| run: git submodule update --init --depth 1 ghostty | ||
|
|
||
| - name: Install Linux build dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y clang libclang-dev pkg-config | ||
|
|
||
| - name: Install zig | ||
| run: ./scripts/install-zig-ci.sh | ||
|
|
||
| - name: Rust version | ||
| run: | | ||
| rustc --version || true | ||
| if ! command -v cargo >/dev/null; then | ||
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable | ||
| echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" | ||
| fi | ||
|
|
||
| - name: Build mux server | ||
| working-directory: mux | ||
| run: cargo build -p mux-tui | ||
|
|
||
| - name: Python conformance fixtures | ||
| run: python3 mux/bindings/conformance/runner.py | ||
|
|
||
| - name: Rust binding e2e | ||
| run: bash mux/bindings/conformance/e2e.sh --require rust | ||
|
|
||
| publish: | ||
| needs: bindings-e2e-rust | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| permissions: | ||
| contents: read | ||
| id-token: write | ||
| environment: | ||
| name: crates-io | ||
| url: https://crates.io/crates/cmux-client | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Authenticate with crates.io trusted publishing | ||
| id: auth | ||
| uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5 | ||
|
|
||
| - name: Publish cmux-client | ||
| working-directory: mux | ||
| env: | ||
| CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }} | ||
| run: cargo publish -p cmux-client --locked | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Publish job lacks Rust toolchainMedium Severity The Reviewed by Cursor Bugbot for commit 2c3d626. Configure here. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| name: sdk publish go | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - "mux-sdk-v*" | ||
|
Comment on lines
+5
to
+6
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Go binding is a nested module at Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "SDK version to validate, for example 0.1.0" | ||
| required: true | ||
| type: string | ||
|
|
||
| permissions: {} | ||
|
|
||
| concurrency: | ||
| group: sdk-publish-go-${{ github.ref }} | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| version: | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| permissions: | ||
| contents: read | ||
| outputs: | ||
| version: ${{ steps.version.outputs.version }} | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Validate tag and package versions | ||
| id: version | ||
| env: | ||
| DISPATCH_VERSION: ${{ inputs.version }} | ||
| run: | | ||
| set -euo pipefail | ||
| if [[ "${GITHUB_REF_TYPE:-}" == "tag" ]]; then | ||
| [[ "$GITHUB_REF_NAME" =~ ^mux-sdk-v[0-9]+\.[0-9]+\.[0-9]+$ ]] || { | ||
| echo "tag must match mux-sdk-vX.Y.Z" >&2 | ||
| exit 1 | ||
| } | ||
| version="${GITHUB_REF_NAME#mux-sdk-v}" | ||
| else | ||
| version="$DISPATCH_VERSION" | ||
| [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { | ||
| echo "workflow_dispatch version must match X.Y.Z" >&2 | ||
| exit 1 | ||
| } | ||
| fi | ||
| python3 - "$version" <<'PY' | ||
| import json | ||
| import pathlib | ||
| import sys | ||
| import tomllib | ||
|
|
||
| expected = sys.argv[1] | ||
| root = pathlib.Path.cwd() | ||
| versions = { | ||
| "typescript package.json": json.loads((root / "mux/bindings/typescript/package.json").read_text())["version"], | ||
| "python pyproject.toml": tomllib.loads((root / "mux/bindings/python/pyproject.toml").read_text())["project"]["version"], | ||
| "rust Cargo.toml": tomllib.loads((root / "mux/bindings/rust/Cargo.toml").read_text())["package"]["version"], | ||
| } | ||
| mismatches = {name: got for name, got in versions.items() if got != expected} | ||
| if mismatches: | ||
| for name, got in mismatches.items(): | ||
| print(f"{name}: expected {expected}, got {got}", file=sys.stderr) | ||
| raise SystemExit(1) | ||
| print(f"All package versions match {expected}") | ||
| PY | ||
| echo "version=$version" >> "$GITHUB_OUTPUT" | ||
|
Comment on lines
+21
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift Consider extracting the version validation job into a reusable workflow. The version validation job (lines 21–71) is duplicated verbatim across all four SDK publish workflows. A bug or schema change in the validation logic would require coordinated edits in four files. A reusable workflow ( 🧰 Tools🪛 zizmor (1.26.1)[info] 21-21: workflow or action definition without a name (anonymous-definition): this job (anonymous-definition) 🤖 Prompt for AI Agents |
||
|
|
||
| bindings-e2e-go: | ||
| needs: version | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| timeout-minutes: 40 | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Init ghostty submodule | ||
| run: git submodule update --init --depth 1 ghostty | ||
|
|
||
| - name: Install Linux build dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y clang libclang-dev pkg-config | ||
|
|
||
| - name: Install zig | ||
| run: ./scripts/install-zig-ci.sh | ||
|
|
||
| - name: Rust version | ||
| run: | | ||
| rustc --version || true | ||
| if ! command -v cargo >/dev/null; then | ||
| curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable | ||
| echo "$HOME/.cargo/bin" >> "$GITHUB_PATH" | ||
| fi | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win Disable default caching on
🔒️ Proposed fix - name: Set up Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version: "1.22.x"
+ cache: falseApply the same Also applies to: 129-129 🧰 Tools🪛 zizmor (1.26.1)[error] 104-104: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default (cache-poisoning) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| with: | ||
| go-version: "1.22.x" | ||
|
|
||
| - name: Build mux server | ||
| working-directory: mux | ||
| run: cargo build -p mux-tui | ||
|
|
||
| - name: Python conformance fixtures | ||
| run: python3 mux/bindings/conformance/runner.py | ||
|
|
||
| - name: Go binding e2e | ||
| run: bash mux/bindings/conformance/e2e.sh --require go | ||
|
|
||
| validate-go-module: | ||
| needs: bindings-e2e-go | ||
| runs-on: ${{ vars.LINUX_RUNNER || 'blacksmith-4vcpu-ubuntu-2404' }} | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 | ||
| with: | ||
| go-version: "1.22.x" | ||
|
|
||
| - name: Validate Go module | ||
| working-directory: mux/bindings/go | ||
| run: | | ||
| go build ./... | ||
| go vet ./... | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔒 Security & Privacy | 🔵 Trivial | 💤 Low value
Add a comment explaining the
id-token: writepermission.The
id-token: writepermission is required for OIDC trusted publishing viarust-lang/crates-io-auth-action, but it has no explanatory comment. Adding one improves auditability for security reviewers.📝 Suggested comment
permissions: contents: read - id-token: write + id-token: write # Required for OIDC trusted publishing to crates.io📝 Committable suggestion
🧰 Tools
🪛 zizmor (1.26.1)
[warning] 118-118: permissions without explanatory comments (undocumented-permissions): needs an explanatory comment
(undocumented-permissions)
[info] 113-113: workflow or action definition without a name (anonymous-definition): this job
(anonymous-definition)
🤖 Prompt for AI Agents
Source: Linters/SAST tools