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
58 changes: 57 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,55 @@ jobs:
fi
npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} --ignore-scripts

# Publish @agent-relay/harnesses after the publish-packages matrix, which is
# where its exact-version workspace deps (@agent-relay/sdk and
# @agent-relay/harness-driver) land on the registry. Publishing harnesses
# before those exist would leave a window where
# `npm install @agent-relay/harnesses@<v>` cannot resolve its dependencies —
# the same install race the broker/sdk ordering above is built to avoid.
publish-harnesses:
Comment thread
cubic-dev-ai[bot] marked this conversation as resolved.
name: Publish @agent-relay/harnesses
needs: [build, publish-packages]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Gate the release on harness publication

For package=all, this new job starts after publish-packages, but nothing downstream waits for it: publish-main only waits on publish-packages and create-release only waits on publish-main. That means if @agent-relay/harnesses publishing fails or is delayed during the first trusted-publisher setup, the workflow can still publish agent-relay and create the GitHub tag/release for that version, leaving the official release without the package this change is meant to ship. Please include this job in the release gating path (or otherwise make create-release wait for it) so a partial release cannot be finalized.

Useful? React with 👍 / 👎.

runs-on: ubuntu-latest
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if: github.event.inputs.package == 'all'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22.14.0'
registry-url: 'https://registry.npmjs.org'

- name: Download build artifacts
uses: actions/download-artifact@v4
Comment on lines +981 to +990

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin action references to commit SHAs in this new job.

The new steps use tag refs (@v4) for third-party actions. Static policy flags this as required-to-fix; pinning to immutable SHAs avoids supply-chain drift.

Example pattern
-      - name: Checkout code
-        uses: actions/checkout@v4
+      - name: Checkout code
+        uses: actions/checkout@<full_commit_sha>

-      - name: Setup Node.js
-        uses: actions/setup-node@v4
+      - name: Setup Node.js
+        uses: actions/setup-node@<full_commit_sha>

-      - name: Download build artifacts
-        uses: actions/download-artifact@v4
+      - name: Download build artifacts
+        uses: actions/download-artifact@<full_commit_sha>
🧰 Tools
🪛 zizmor (1.25.2)

[error] 981-981: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 984-984: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)


[error] 990-990: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/publish.yml around lines 981 - 990, Replace the floating
action tags used in the job (actions/checkout@v4, actions/setup-node@v4,
actions/download-artifact@v4) with immutable commit SHAs: locate the official
GitHub repos for each action (actions/checkout, actions/setup-node,
actions/download-artifact), find the commit SHA that corresponds to the v4
release you intend to use, and update the workflow to reference the full SHA
(e.g., actions/checkout@<SHA>) instead of `@v4`; keep the existing inputs
(node-version, registry-url, etc.) unchanged and ensure each action ref is
pinned consistently across the new job.

with:
name: build-output
path: .

- name: Update npm for OIDC support
run: npm install -g npm@latest

- name: Dry run check
if: github.event.inputs.dry_run == 'true'
working-directory: packages/harnesses
run: npm publish --dry-run --access public --tag ${{ github.event.inputs.tag }} --ignore-scripts

- name: Publish to NPM
if: github.event.inputs.dry_run != 'true'
working-directory: packages/harnesses
run: |
set -euo pipefail
PKG_NAME=$(node -p "require('./package.json').name")
PKG_VERSION=$(node -p "require('./package.json').version")
if npm view "${PKG_NAME}@${PKG_VERSION}" version >/dev/null 2>&1; then
echo "${PKG_NAME}@${PKG_VERSION} already exists on npm; skipping publish"
exit 0
fi
npm publish --access public --provenance --tag ${{ github.event.inputs.tag }} --ignore-scripts

# package=main publishes only the root `agent-relay` tarball, but that
# tarball pins several @agent-relay/* runtime dependencies to the freshly
# bumped version. Publish those direct deps first so a main-only release
Expand Down Expand Up @@ -1528,13 +1577,18 @@ jobs:
# Create git tag and release
create-release:
name: Create Release
needs: [build, build-broker, build-standalone, verify-binaries, publish-main]
needs: [build, build-broker, build-standalone, verify-binaries, publish-main, publish-harnesses]
runs-on: ubuntu-latest
# publish-harnesses only runs for package=all; for a package=main release it
# is skipped, which must not block the tag. Gate on "not failed" rather than
# "succeeded" so a real harness publish failure stops the release but a
# skipped one does not.
if: |
always() &&
github.event.inputs.package != 'cli-prerelease' &&
github.event.inputs.dry_run != 'true' &&
needs.publish-main.result == 'success' &&
(needs.publish-harnesses.result == 'success' || needs.publish-harnesses.result == 'skipped') &&
needs.publish-main.outputs.published == 'true'

steps:
Expand Down Expand Up @@ -2011,6 +2065,7 @@ jobs:
publish-sdk-internal-deps,
publish-broker-packages,
publish-packages,
publish-harnesses,
publish-brand-only,
publish-sdk-py,
publish-main,
Expand Down Expand Up @@ -2053,6 +2108,7 @@ jobs:
echo "| Publish SDK Internal Deps | ${{ needs.publish-sdk-internal-deps.result == 'success' && '✅' || (needs.publish-sdk-internal-deps.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-sdk-internal-deps.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Broker Packages | ${{ needs.publish-broker-packages.result == 'success' && '✅' || (needs.publish-broker-packages.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-broker-packages.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Packages | ${{ needs.publish-packages.result == 'success' && '✅' || (needs.publish-packages.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-packages.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Harnesses | ${{ needs.publish-harnesses.result == 'success' && '✅' || (needs.publish-harnesses.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-harnesses.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Brand | ${{ needs.publish-brand-only.result == 'success' && '✅' || (needs.publish-brand-only.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-brand-only.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Python SDK | ${{ needs.publish-sdk-py.result == 'success' && '✅' || (needs.publish-sdk-py.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-sdk-py.result }} |" >> $GITHUB_STEP_SUMMARY
echo "| Publish Main | ${{ needs.publish-main.result == 'success' && '✅' || (needs.publish-main.result == 'skipped' && '⏭️' || '❌') }} ${{ needs.publish-main.result }} |" >> $GITHUB_STEP_SUMMARY
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- `@agent-relay/harnesses` is now published to npm, so SDK consumers can install the prebuilt PTY harnesses and harness-authoring helpers.
- `agent-relay drive` and `agent-relay passthrough` add adaptive predictive echo so typing stays responsive when driving a high-latency or remote agent, and stays invisible on fast local links.
- `@agent-relay/harness-driver` exports a reusable `PredictiveEchoEngine` so other attach UIs (CLI, Electron, browser) can share one predictive-echo implementation.
- `@agent-relay/sdk` `relay.addListener(...)` on a workspace client now receives all workspace-visible events: `events.connect()` opens the relaycast 2.5 workspace stream when no agent client is present, so the documented `relay.addListener('message.created', ...)` quickstart path streams without registering an agent.
Expand Down
Loading