e2e: move backend/dex/frontend from 8080 to 18080 so runners don't collide
Two of the fleet's Gitea Actions runners (morpheus, architect) already had 8080 permanently bound by unrelated services (nginx on morpheus, envio-hasura on architect) — every e2e run scheduled there died at playwright's webServer preflight with "http://127.0.0.1:8080/healthz is already used". 18080 is unused across morpheus/tank/architect. Swap 8080 → 18080 in the eight e2e-scoped sites: clawmates.e2e.toml (listen_addr + slack base_url + oauth redirect_base), dex.yaml (client redirect URIs must match backend), playwright.config.ts + tests (p4-slack, p6-oauth), the http.ts dev-fallback origin, and the two shell scripts (e2e-backend safety check, rehearse-install healthz probe). Prod compose (/opt/clawmates/docker-compose.yml on gw-04) is untouched; prod continues to expose the server on 8080 internally on the compose network (that's per-network, not host-shared).
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
# CLAWMATES_MODE=e2e, which applies the deterministic seed at boot.
|
# CLAWMATES_MODE=e2e, which applies the deterministic seed at boot.
|
||||||
|
|
||||||
deploy_target = "air_gapped"
|
deploy_target = "air_gapped"
|
||||||
listen_addr = "127.0.0.1:8080"
|
listen_addr = "127.0.0.1:18080"
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
url = "postgres://postgres:[email protected]:54330/clawmates_e2e"
|
url = "postgres://postgres:[email protected]:54330/clawmates_e2e"
|
||||||
@@ -19,10 +19,10 @@ mode = "local"
|
|||||||
socket_path = "/tmp/clawmates-e2e-broker.sock"
|
socket_path = "/tmp/clawmates-e2e-broker.sock"
|
||||||
|
|
||||||
[slack]
|
[slack]
|
||||||
base_url = "http://127.0.0.1:8080/__slack"
|
base_url = "http://127.0.0.1:18080/__slack"
|
||||||
|
|
||||||
[oauth]
|
[oauth]
|
||||||
issuer_url = "http://127.0.0.1:54556/dex"
|
issuer_url = "http://127.0.0.1:54556/dex"
|
||||||
client_id = "clawmates"
|
client_id = "clawmates"
|
||||||
client_secret = "tc-e2e-oauth-secret"
|
client_secret = "tc-e2e-oauth-secret"
|
||||||
redirect_base = "http://127.0.0.1:8080"
|
redirect_base = "http://127.0.0.1:18080"
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ staticClients:
|
|||||||
secret: tc-e2e-oauth-secret
|
secret: tc-e2e-oauth-secret
|
||||||
name: Clawmates
|
name: Clawmates
|
||||||
redirectURIs:
|
redirectURIs:
|
||||||
- http://127.0.0.1:8080/api/apps/oauth/callback
|
- http://127.0.0.1:18080/api/apps/oauth/callback
|
||||||
enablePasswordDB: true
|
enablePasswordDB: true
|
||||||
staticPasswords:
|
staticPasswords:
|
||||||
- email: [email protected]
|
- email: [email protected]
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export default defineConfig({
|
|||||||
webServer: [
|
webServer: [
|
||||||
{
|
{
|
||||||
command: "bash ../scripts/e2e-backend.sh",
|
command: "bash ../scripts/e2e-backend.sh",
|
||||||
url: "http://127.0.0.1:8080/healthz",
|
url: "http://127.0.0.1:18080/healthz",
|
||||||
reuseExistingServer: !process.env.CI,
|
reuseExistingServer: !process.env.CI,
|
||||||
timeout: 180_000,
|
timeout: 180_000,
|
||||||
},
|
},
|
||||||
@@ -28,7 +28,7 @@ export default defineConfig({
|
|||||||
url: "http://127.0.0.1:3100/login",
|
url: "http://127.0.0.1:3100/login",
|
||||||
reuseExistingServer: !process.env.CI,
|
reuseExistingServer: !process.env.CI,
|
||||||
timeout: 180_000,
|
timeout: 180_000,
|
||||||
env: { API_ORIGIN: "http://127.0.0.1:8080" },
|
env: { API_ORIGIN: "http://127.0.0.1:18080" },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export { TOKEN_COOKIE } from "@/lib/auth/bearer";
|
|||||||
|
|
||||||
/** Origin of the Rust backend, reachable from the Next server process. */
|
/** Origin of the Rust backend, reachable from the Next server process. */
|
||||||
export function apiOrigin(): string {
|
export function apiOrigin(): string {
|
||||||
return process.env.API_ORIGIN ?? "http://127.0.0.1:8080";
|
return process.env.API_ORIGIN ?? "http://127.0.0.1:18080";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Thrown when there is no session or the backend rejects it; callers
|
/** Thrown when there is no session or the backend rejects it; callers
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ test("connect Slack, then an outbound post is gated and broker-executed", async
|
|||||||
await expect(card.getByText(/wants to:/)).toContainText("Post to Slack #general");
|
await expect(card.getByText(/wants to:/)).toContainText("Post to Slack #general");
|
||||||
|
|
||||||
// Provably blocked: the sink saw nothing.
|
// Provably blocked: the sink saw nothing.
|
||||||
const before = await request.get("http://127.0.0.1:8080/__slack/posts");
|
const before = await request.get("http://127.0.0.1:18080/__slack/posts");
|
||||||
expect(await before.json()).toHaveLength(0);
|
expect(await before.json()).toHaveLength(0);
|
||||||
|
|
||||||
// Approve → the broker posts exactly once.
|
// Approve → the broker posts exactly once.
|
||||||
await card.getByRole("button", { name: "Approve" }).click();
|
await card.getByRole("button", { name: "Approve" }).click();
|
||||||
await expect(page.getByText(/Posted to #general/)).toBeVisible();
|
await expect(page.getByText(/Posted to #general/)).toBeVisible();
|
||||||
|
|
||||||
const after = await request.get("http://127.0.0.1:8080/__slack/posts");
|
const after = await request.get("http://127.0.0.1:18080/__slack/posts");
|
||||||
const posts = (await after.json()) as { channel: string; text: string }[];
|
const posts = (await after.json()) as { channel: string; text: string }[];
|
||||||
expect(posts).toHaveLength(1);
|
expect(posts).toHaveLength(1);
|
||||||
expect(posts[0].channel).toBe("#general");
|
expect(posts[0].channel).toBe("#general");
|
||||||
@@ -74,7 +74,7 @@ test("connect Slack, then an outbound post is gated and broker-executed", async
|
|||||||
createHmac("sha256", "e2e-signing-secret")
|
createHmac("sha256", "e2e-signing-secret")
|
||||||
.update(`v0:${timestamp}:${mention}`)
|
.update(`v0:${timestamp}:${mention}`)
|
||||||
.digest("hex");
|
.digest("hex");
|
||||||
const inbound = await request.post("http://127.0.0.1:8080/api/slack/events", {
|
const inbound = await request.post("http://127.0.0.1:18080/api/slack/events", {
|
||||||
headers: {
|
headers: {
|
||||||
"x-slack-request-timestamp": timestamp,
|
"x-slack-request-timestamp": timestamp,
|
||||||
"x-slack-signature": signature,
|
"x-slack-signature": signature,
|
||||||
@@ -96,7 +96,7 @@ test("connect Slack, then an outbound post is gated and broker-executed", async
|
|||||||
await expect(page.getByText(/All clear/)).toBeVisible();
|
await expect(page.getByText(/All clear/)).toBeVisible();
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => {
|
.poll(async () => {
|
||||||
const res = await request.get("http://127.0.0.1:8080/__slack/posts");
|
const res = await request.get("http://127.0.0.1:18080/__slack/posts");
|
||||||
return ((await res.json()) as { text: string }[]).map((p) => p.text);
|
return ((await res.json()) as { text: string }[]).map((p) => p.text);
|
||||||
})
|
})
|
||||||
.toContain("On it!");
|
.toContain("On it!");
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { expect, test } from "@playwright/test";
|
|||||||
|
|
||||||
const OWNER_EMAIL = "[email protected]";
|
const OWNER_EMAIL = "[email protected]";
|
||||||
const OWNER_PASSWORD = "e2e-password";
|
const OWNER_PASSWORD = "e2e-password";
|
||||||
const BACKEND = "http://127.0.0.1:8080";
|
const BACKEND = "http://127.0.0.1:18080";
|
||||||
|
|
||||||
test("connecting an app via OAuth walks the real dex login", async ({
|
test("connecting an app via OAuth walks the real dex login", async ({
|
||||||
page,
|
page,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ done
|
|||||||
# Refuse to run against someone else's 8080 (e.g. the compose stack):
|
# Refuse to run against someone else's 8080 (e.g. the compose stack):
|
||||||
# reuseExistingServer would silently point every journey at the wrong
|
# reuseExistingServer would silently point every journey at the wrong
|
||||||
# backend with the wrong seed.
|
# backend with the wrong seed.
|
||||||
if curl -fsS -o /dev/null --max-time 2 http://127.0.0.1:8080/healthz 2>/dev/null; then
|
if curl -fsS -o /dev/null --max-time 2 http://127.0.0.1:18080/healthz 2>/dev/null; then
|
||||||
echo "e2e-backend: port 8080 is already serving — stop the other stack first" >&2
|
echo "e2e-backend: port 8080 is already serving — stop the other stack first" >&2
|
||||||
echo " (docker compose -f deploy/compose/docker-compose.yml down)" >&2
|
echo " (docker compose -f deploy/compose/docker-compose.yml down)" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ docker compose --project-directory "$CLAWMATES_HOME" up -d --no-build
|
|||||||
|
|
||||||
echo "==> Waiting for the platform"
|
echo "==> Waiting for the platform"
|
||||||
for _ in $(seq 1 60); do
|
for _ in $(seq 1 60); do
|
||||||
if curl -fsS http://127.0.0.1:8080/healthz >/dev/null 2>&1; then
|
if curl -fsS http://127.0.0.1:18080/healthz >/dev/null 2>&1; then
|
||||||
echo "==> Server is healthy"
|
echo "==> Server is healthy"
|
||||||
if curl -fsS http://127.0.0.1:3000/login | grep -q clawmates; then
|
if curl -fsS http://127.0.0.1:3000/login | grep -q clawmates; then
|
||||||
echo "==> Frontend serves the login page"
|
echo "==> Frontend serves the login page"
|
||||||
|
|||||||
Reference in New Issue
Block a user