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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ jobs:
test:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Run complete non-privileged gate
run: ./bazel test //:test --test_output=errors --zip_undeclared_test_outputs
run: ./bazel test //:test --keep_going --test_output=errors --zip_undeclared_test_outputs
- name: Retain test logs and browser evidence
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: bazel-test-evidence
# Browser evidence names can contain ':'; upload Bazel's archive instead.
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ jobs:
contents: read
packages: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Build and load Bazel-owned linux/amd64 image
if: ${{ !inputs.reuse_image }}
run: ./bazel run --config=release //release:load
- name: Restore validated release image
if: ${{ inputs.reuse_image }}
uses: actions/download-artifact@v4
uses: actions/download-artifact@v8
with:
name: pulsebeam-amd64-image
path: ${{ runner.temp }}/pulsebeam-image
Expand All @@ -53,14 +53,14 @@ jobs:
run: docker save pulsebeam:local -o "$RUNNER_TEMP/pulsebeam-amd64-image.tar"
- name: Retain validated release image
if: ${{ inputs.validate_only }}
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: pulsebeam-amd64-image
path: ${{ runner.temp }}/pulsebeam-amd64-image.tar
if-no-files-found: error
- name: Image tags
id: meta
uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302
with:
images: ${{ env.GHCR_IMAGE }}
tags: |
Expand All @@ -71,7 +71,7 @@ jobs:
type=raw,value=latest,enable={{is_default_branch}}
- name: Registry login
if: ${{ !inputs.validate_only && github.event_name != 'pull_request' }}
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/meet-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ jobs:
permissions:
contents: read
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Build and validate deployable static export
run: ./bazel test //apps/meet:check
- uses: actions/upload-pages-artifact@v4
- uses: actions/upload-pages-artifact@v5
with:
path: bazel-bin/apps/meet/out
deploy:
Expand All @@ -32,4 +32,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@v5
4 changes: 2 additions & 2 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
timeout-minutes: 120
continue-on-error: true
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Sweep and retain replay commands
shell: bash
Expand All @@ -34,7 +34,7 @@ jobs:
fi
./bazel run //:sweep -- --seeds "$seeds" --from-seed "$from" 2>&1 | tee seed-sweep.log
- if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: seed-sweep-evidence
path: seed-sweep.log
2 changes: 1 addition & 1 deletion .github/workflows/npm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
contents: read
id-token: write
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Validate package release identity
run: ./bazel run //release/npm:plan -- --tag "$GITHUB_REF_NAME"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/provisioning-acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
native-image:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Validate GNU release artifacts
run: ./bazel test --config=release //release:elf_contract //release:contract --test_output=errors
Expand All @@ -30,17 +30,17 @@ jobs:
native-arm:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Validate native aarch64 GNU release contracts
run: ./bazel test --config=release //release:contract //release:elf_contract --test_output=errors
meet:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Assemble deployable Meet output without deployment
run: ./bazel test //apps/meet:check --test_output=errors
- uses: actions/upload-pages-artifact@v4
- uses: actions/upload-pages-artifact@v5
with:
path: bazel-bin/apps/meet/out
12 changes: 6 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
outputs:
plan: ${{ steps.plan.outputs.plan }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- id: plan
name: Validate version tag against package authority
Expand All @@ -35,7 +35,7 @@ jobs:
target: aarch64-unknown-linux-gnu
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- name: Build architecture-appropriate release assets
run: |
Expand All @@ -49,7 +49,7 @@ jobs:
tar -xJf pulsebeam-${{ matrix.target }}.tar.xz -C "$temporary"
"$temporary/pulsebeam-${{ matrix.target }}/pulsebeam" --version
rm -rf "$temporary"
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: release-${{ matrix.target }}
path: bazel-bin/release/artifacts/*
Expand All @@ -58,10 +58,10 @@ jobs:
needs: [plan, checks]
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v7
- uses: ./.github/actions/setup-ci
- run: ./bazel build //release:global
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: release-global
path: bazel-bin/release/global-artifacts/*
Expand All @@ -81,7 +81,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
- uses: actions/download-artifact@v8
with:
pattern: release-*
path: artifacts
Expand Down
3 changes: 2 additions & 1 deletion agents/pulsebeam-agent-web/src/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ impl BrowserRuntime {
let actor = actor
.as_ref()
.ok_or_else(|| js_error("runtime actor not initialized"))?;
actor.send_public(PublicCommand::SetLogLevel(level.into()))
actor
.send_public(PublicCommand::SetLogLevel(level.into()))
.map_err(js_error)?;
self.inner.logger.set_level(level);
Ok(())
Expand Down
5 changes: 1 addition & 4 deletions agents/pulsebeam-agent-web/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,7 @@ impl fmt::Debug for PublicCommand {
.debug_tuple("SetConnected")
.field(connected)
.finish(),
Self::SetLogLevel(level) => formatter
.debug_tuple("SetLogLevel")
.field(level)
.finish(),
Self::SetLogLevel(level) => formatter.debug_tuple("SetLogLevel").field(level).finish(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions agents/pulsebeam-agent-web/tests/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ async fn web(server: &StaticServer, failure: bool) -> TestResult<()> {
"attachRemoteVideo",
"createAgent",
"createCaptureSource",
"createManagedAgent",
"nativeCaptureTrack"
]
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ new Promise((resolve, reject) => {
const after = agent.getSnapshot();
resolve(
after.connection === "terminal-failure" &&
agent.connection === after.connection &&
after.failure === failure &&
error === failure,
agent.connection === after.connection &&
after.failure === failure &&
error === failure,
);
});
agent.setState({ connected: true });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,16 @@
),
})),
);
const topics = JSON.stringify(
{
status: window.__meet?.sender?.getSnapshot().topics,
chats: window.__meet?.chats,
emojis: window.__meet?.emojis,
},
(_, value) => (typeof value === "bigint" ? value.toString() : value),
);
throw new Error(
`Meet media condition: ${label}; UI: ${document.body.innerText.slice(0, 1500)}; transports: ${JSON.stringify(transports)}`,
`Meet media condition: ${label}; UI: ${document.body.innerText.slice(0, 1500)}; topics: ${topics}; transports: ${JSON.stringify(transports)}`,
);
};
const peers = new Set();
Expand Down
19 changes: 19 additions & 0 deletions agents/pulsebeam-agent-web/tests/contracts/meet-publisher-start.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,24 @@
await source.close();
},
});
await window.__meet.wait(() => {
const snapshot = sender.getSnapshot();
const subscribers = snapshot.topics.subscribers;
return (
snapshot.connection === "connected" &&
subscribers.some(
(status) =>
status.name === "chat" &&
status.mode === "ordered" &&
status.connected,
) &&
subscribers.some(
(status) =>
status.name === "reactions" &&
status.mode === "latest" &&
status.connected,
)
);
}, "publisher topic subscriptions ready");
return true;
})();
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
type AgentFailure,
type AgentSnapshot,
type AgentState,
type ConnectionState,
type FailureClass,
type PlaybackFailure,
type RemoteMediaAttachment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,35 @@
received.every((track) => track.readyState === "live"),
"close rejects recovery and leaves borrowed media live",
);
const retainedAudio = independent.participant("alice").audio("second");
independent.resetPlayback();
await wait(
() => otherContext.state === "closed",
"deactivation releases the audio context",
);
assert(
otherOutput.routes.size === 0 &&
decoders[1].paused &&
decoders[1].srcObject === null,
"deactivation releases audible routes and private decoding",
);
independent.update(snapshot);
await wait(() => {
retainedAudio.readWaveform(wave);
return (
contexts[2]?.state === "running" &&
wave.some((value) => Math.abs(value) > 0.00001)
);
}, "reactivated audio output");
assert(
independent.participant("alice").audio("second") === retainedAudio &&
retainedAudio.receiving &&
contexts.length === 3 &&
outputs.get(contexts[2]).routes.size === 1 &&
captured.every((track) => track.readyState === "live") &&
received.every((track) => track.readyState === "live"),
"reactivation retains handles and borrowed media without duplicate output",
);
return true;
} finally {
catalogs.forEach((catalog) => catalog.close());
Expand Down
11 changes: 11 additions & 0 deletions agents/pulsebeam-agent-web/tests/meet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,17 @@ async fn meet_media_contract(gesture_before_media: bool) -> TestResult<()> {
driver.find(By::Css("form input")).await?.send_keys("outbound Meet chat").await?;
click(&driver, "Send message").await?;
click(&driver, "Send a reaction").await?;
let _: bool = evaluate_json(&bidi, &context, r#"(async () => {
await __meet.wait(() => {
const menu = document.querySelector('[role="menu"]');
if (!menu) return false;
for (let node = menu; node; node = node.parentElement) {
if (node.getAnimations().some(animation => animation.pending || animation.playState === 'running')) return false;
}
return true;
}, 'reaction menu animation settled');
return true;
})()"#).await?;
click(&driver, "React with 👍").await?;
let _: bool = evaluate_json(&bidi, &context, r#"(async () => {
await __meet.wait(() => __meet.chats.some(({text}) => text === 'outbound Meet chat') && __meet.emojis.some(({emoji}) => emoji === '👍'), 'real Meet sends both topics');
Expand Down
14 changes: 10 additions & 4 deletions agents/pulsebeam-agent-web/web/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,22 +391,25 @@ class AgentFacade implements Agent {
try {
runtime = new BrowserRuntime(this.#runtimeConfig);
} catch (error) {
if (active()) this.#terminalFailure("invalid-configuration", message(error));
if (active())
this.#terminalFailure("invalid-configuration", message(error));
throw error;
}
this.#runtime = runtime;
runtime.set_event_listener((event: unknown) => {
if (active()) this.#runtimeEvent(event);
});
runtime.set_error_listener((error: unknown) => {
if (active()) this.#emitFailure(localFailureClass(error), message(error));
if (active())
this.#emitFailure(localFailureClass(error), message(error));
});
try {
runtime.replace_desired(
desiredValue(this.#effectiveState(this.#state)),
);
} catch (error) {
if (active()) this.#terminalFailure("invalid-configuration", message(error));
if (active())
this.#terminalFailure("invalid-configuration", message(error));
runtime.abort();
this.#runtime = undefined;
throw error;
Expand Down Expand Up @@ -447,6 +450,7 @@ class AgentFacade implements Agent {
runtime.close();
runtime.abort();
}
this.#remote.resetPlayback();
this.#publish(emptySnapshot("disconnected"));
}

Expand Down Expand Up @@ -586,7 +590,9 @@ class AgentFacade implements Agent {
void this.replaceLocalTrack(
slot,
track,
kind === "video" ? { contentHint: "motion" } : { contentHint: "speech" },
kind === "video"
? { contentHint: "motion" }
: { contentHint: "speech" },
).catch(() => {});
}

Expand Down
Loading
Loading