Skip to content

Commit c385de3

Browse files
committed
fix ci
1 parent 67c4204 commit c385de3

5 files changed

Lines changed: 92 additions & 60 deletions

File tree

.github/workflows/ci.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,26 @@ jobs:
3131
- name: Setup Go
3232
uses: actions/setup-go@v5
3333
with:
34-
go-version: '1.23.x'
34+
go-version: "1.23.x"
3535

3636
- name: Install Task
3737
run: |
3838
curl -sL https://taskfile.dev/install.sh | sh -s -- -b /usr/local/bin
3939
task --version
4040
41+
- name: Install Convox CLI
42+
run: |
43+
set -euo pipefail
44+
ARCH=$(uname -m)
45+
URL="https://github.com/convox/convox/releases/latest/download/convox-linux"
46+
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
47+
URL="https://github.com/convox/convox/releases/latest/download/convox-linux-arm64"
48+
fi
49+
curl -fsSL "$URL" -o /tmp/convox
50+
sudo mv /tmp/convox /usr/local/bin/convox
51+
sudo chmod 755 /usr/local/bin/convox
52+
convox version || true
53+
4154
- name: Go tests
4255
run: task go:test
4356

@@ -49,7 +62,7 @@ jobs:
4962
- name: Setup Node
5063
uses: actions/setup-node@v4
5164
with:
52-
node-version: '20'
65+
node-version: "20"
5366

5467
- name: Enable corepack
5568
run: corepack enable

.github/workflows/e2e.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ jobs:
7979
docker compose pull postgres || docker pull postgres:16-alpine
8080
8181
- name: Start stack (gateway serves UI)
82-
run: docker compose up -d --no-build --pull=never mock-oauth mock-convox gateway-api
82+
run: docker compose up -d --no-build --pull=never mock-oauth mock-convox gateway-api-preview
8383

8484
- name: Wait for services
8585
run: |
@@ -126,7 +126,7 @@ jobs:
126126
- name: Setup Go
127127
uses: actions/setup-go@v5
128128
with:
129-
go-version: '1.23.x'
129+
go-version: "1.23.x"
130130

131131
- name: Download gateway image
132132
uses: actions/download-artifact@v4
@@ -148,7 +148,7 @@ jobs:
148148
docker compose pull postgres || docker pull postgres:16-alpine
149149
150150
- name: Start stack (gateway serves UI)
151-
run: docker compose up -d --no-build --pull=never mock-oauth mock-convox gateway-api
151+
run: docker compose up -d --no-build --pull=never mock-oauth mock-convox gateway-api-preview
152152

153153
- name: Wait for services
154154
run: |

Taskfile.web.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,11 @@ tasks:
5858
desc: Run Web E2E against dev stack (Vite/HMR)
5959
deps: [":docker:up:dev", "e2e:deps"]
6060
cmds:
61-
- env WEB_PORT={{.WEB_PORT}} pnpm e2e
61+
- env WEB_PORT={{.WEB_PORT}} PLAYWRIGHT_FORCE_TTY=false pnpm e2e
6262

6363
e2e:preview:
6464
dir: web
6565
desc: Run Web E2E against preview stack (compiled SPA)
6666
deps: [":docker:up:preview", "e2e:deps"]
6767
cmds:
68-
- env GATEWAY_PORT={{.GATEWAY_PORT}} pnpm e2e
68+
- env GATEWAY_PORT={{.GATEWAY_PORT}} PLAYWRIGHT_FORCE_TTY=false pnpm e2e

web/e2e/fixtures.ts

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,73 @@
1-
import { test as base, expect } from '@playwright/test'
1+
import { test as base, expect } from "@playwright/test";
22

33
export const test = base.extend({
44
page: async ({ page }, use) => {
5-
const errors: string[] = []
6-
let lastMe401At = 0
5+
const errors: string[] = [];
76
// Log 4xx/5xx responses with URL and a short body snippet
8-
page.on('response', async (resp) => {
9-
const status = resp.status()
7+
page.on("response", async (resp) => {
8+
const status = resp.status();
109
if (status >= 400) {
11-
const req = resp.request()
12-
const method = req.method()
13-
const url = resp.url()
14-
const debugAuth = (process.env.LOG_LEVEL || '').toLowerCase() === 'debug'
15-
if (status === 401 && url.includes('/.gateway/api/me') && !debugAuth) {
16-
return
17-
}
18-
let body = ''
19-
try { body = await resp.text() } catch {}
20-
const snippet = body ? body.slice(0, 200).replace(/\s+/g, ' ').trim() : ''
21-
console.log(`[resp ${status}] ${method} ${url}${snippet ? ' body="' + snippet + '"' : ''}`)
22-
if (status === 401 && url.includes('/.gateway/api/me')) {
23-
lastMe401At = Date.now()
10+
const req = resp.request();
11+
const method = req.method();
12+
const url = resp.url();
13+
const debugAuth =
14+
(process.env.LOG_LEVEL || "").toLowerCase() === "debug";
15+
if (status === 401 && url.includes("/.gateway/api/me") && !debugAuth) {
16+
return;
2417
}
18+
let body = "";
19+
try {
20+
body = await resp.text();
21+
} catch {}
22+
const snippet = body
23+
? body.slice(0, 200).replace(/\s+/g, " ").trim()
24+
: "";
25+
26+
if (status === 401 && url.includes("/.gateway/api/me")) return;
27+
28+
console.log(
29+
`[resp ${status}] ${method} ${url}${
30+
snippet ? ' body="' + snippet + '"' : ""
31+
}`
32+
);
2533
}
26-
})
27-
page.on('console', (msg) => {
28-
const text = msg.text()
29-
const url = page.url()
34+
});
35+
page.on("console", (msg) => {
36+
const text = msg.text();
37+
const url = page.url();
3038
// Suppress generic 401 console noise entirely (expected before login)
31-
const isGeneric401 = /the server responded with a status of 401 \(Unauthorized\)\s*$/i.test(text) || /\b401\b/i.test(text)
32-
if (isGeneric401) return
39+
const isGeneric401 =
40+
/the server responded with a status of 401 \(Unauthorized\)\s*$/i.test(
41+
text
42+
) || /\b401\b/i.test(text);
43+
if (isGeneric401) return;
44+
if (msg.type() === "debug" && text.includes("[vite] connect")) return;
45+
if (
46+
msg.type() === "info" &&
47+
text.includes(
48+
"Download the React DevTools for a better development experience"
49+
)
50+
)
51+
return;
52+
3353
// Always print console logs for diagnosis (after suppression checks)
34-
console.log('console:', msg.type(), text)
35-
if (msg.type() === 'error') {
54+
console.log("console:", msg.type(), text);
55+
if (msg.type() === "error") {
3656
// Ignore all 401/Unauthorized console errors (expected before login)
37-
const is401 = /\b401\b/i.test(text) || /Unauthorized/i.test(text)
38-
if (is401) return
39-
errors.push(`console.${msg.type()}: ${text}`)
57+
const is401 = /\b401\b/i.test(text) || /Unauthorized/i.test(text);
58+
if (is401) return;
59+
errors.push(`console.${msg.type()}: ${text}`);
4060
}
41-
})
42-
page.on('pageerror', (err) => {
43-
console.log('pageerror:', err)
44-
errors.push(`pageerror: ${String(err)}`)
45-
})
46-
await use(page)
61+
});
62+
page.on("pageerror", (err) => {
63+
console.log("pageerror:", err);
64+
errors.push(`pageerror: ${String(err)}`);
65+
});
66+
await use(page);
4767
if (errors.length > 0) {
48-
throw new Error('JS errors detected during test:\n' + errors.join('\n'))
68+
throw new Error("JS errors detected during test:\n" + errors.join("\n"));
4969
}
5070
},
51-
})
71+
});
5272

53-
export { expect }
73+
export { expect };

web/e2e/login.spec.ts

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
1-
import { expect, test } from './fixtures'
1+
import { expect, test } from "./fixtures";
22

3-
test('login button triggers gateway OAuth redirect', async ({ page }) => {
4-
page.on('console', (m) => console.log('console:', m.type(), m.text()))
5-
page.on('pageerror', (e) => console.log('pageerror:', e))
3+
test("login button triggers gateway OAuth redirect", async ({ page }) => {
4+
page.on("pageerror", (e) => console.log("pageerror:", e));
65

7-
await page.goto('/.gateway/web/login')
6+
await page.goto("/.gateway/web/login");
87

98
const btn = page
10-
.getByTestId('login-cta')
11-
.or(page.getByRole('button', { name: /Continue with/i }))
12-
.or(page.getByRole('link', { name: /Continue with/i }))
9+
.getByTestId("login-cta")
10+
.or(page.getByRole("button", { name: /Continue with/i }))
11+
.or(page.getByRole("link", { name: /Continue with/i }));
1312

1413
try {
15-
await expect(btn).toBeVisible({ timeout: 5000 })
14+
await expect(btn).toBeVisible({ timeout: 5000 });
1615
} catch (e) {
17-
const html = await page.content()
18-
console.log('--- login page HTML (first 1200 chars) ---')
19-
console.log(html.slice(0, 1200))
20-
throw e
16+
const html = await page.content();
17+
console.log("--- login page HTML (first 1200 chars) ---");
18+
console.log(html.slice(0, 1200));
19+
throw e;
2120
}
2221

2322
await Promise.all([
2423
page.waitForNavigation({ url: /oauth2\/v2\/auth|dev\/select-user/i }),
2524
btn.click(),
26-
])
27-
})
25+
]);
26+
});

0 commit comments

Comments
 (0)