Skip to content

Commit 3ca1c8f

Browse files
authored
Merge branch 'main' into dependabot/npm_and_yarn/dot-github/actions/find/types/node-24.7.0
2 parents d10edca + 5ee8116 commit 3ca1c8f

File tree

23 files changed

+353
-179
lines changed

23 files changed

+353
-179
lines changed

.github/actions/auth/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# auth
22

3-
Log in using Playwright, then write authenticated session state to a file for reuse in other Playwright sessions.
3+
Authenticate with Playwright and save session state. Supports HTTP Basic and form authentication.
44

55
## Usage
66

@@ -23,6 +23,6 @@ Log in using Playwright, then write authenticated session state to a file for re
2323
2424
### Outputs
2525

26-
#### `session_state_path`
26+
#### `auth_context`
2727

28-
Path to a file containing authenticated session state.
28+
Stringified JSON object containing `username`, `password`, `cookies`, and/or `localStorage` from an authenticated session. For example: `{"username":"some-user","password":"correct-horse-battery-staple","cookies":[{"name":"theme-preference","value":"light","domain":"primer.style","path":"/"}],"localStorage":{"https://primer.style":{"theme-preference":"light"}}}`

.github/actions/auth/action.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: "Auth"
2-
description: "Log in using Playwright, then write authenticated session state to a file for reuse in other Playwright sessions."
2+
description: "Authenticate with Playwright and save session state. Supports HTTP Basic and form authentication."
33

44
inputs:
55
login_url:
@@ -13,13 +13,13 @@ inputs:
1313
required: true
1414

1515
outputs:
16-
session_state_path:
17-
description: "Path to a file containing authenticated session state"
16+
auth_context:
17+
description: "Stringified JSON object containing 'username', 'password', 'cookies', and/or 'localStorage' from an authenticated session"
1818

1919
runs:
2020
using: "node20"
2121
main: "bootstrap.js"
2222

2323
branding:
2424
icon: "lock"
25-
color: "blue"
25+
color: "blue"

.github/actions/auth/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "auth",
33
"version": "1.0.0",
4-
"description": "Log in using Playwright, then write authenticated session state to a file for reuse in other Playwright sessions.",
4+
"description": "Authenticate with Playwright and save session state. Supports HTTP Basic and form authentication.",
55
"main": "dist/index.js",
66
"module": "dist/index.js",
77
"scripts": {

.github/actions/auth/src/index.ts

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { AuthContextOutput } from "./types.d.js";
12
import crypto from "node:crypto";
23
import process from "node:process";
34
import * as url from "node:url";
@@ -29,26 +30,62 @@ export default async function () {
2930
headless: true,
3031
executablePath: process.env.CI ? "/usr/bin/google-chrome" : undefined,
3132
});
32-
context = await browser.newContext();
33+
context = await browser.newContext({
34+
// Try HTTP Basic authentication
35+
httpCredentials: {
36+
username,
37+
password,
38+
},
39+
});
3340
page = await context.newPage();
3441

35-
// Log in
42+
// Navigate to login page
3643
core.info("Navigating to login page");
3744
await page.goto(loginUrl);
38-
core.info("Filling username");
39-
await page.getByLabel(/username/i).fill(username);
40-
core.info("Filling password");
41-
await page.getByLabel(/password/i).fill(password);
42-
core.info("Logging in");
43-
await page
44-
.getByLabel(/password/i)
45-
.locator("xpath=ancestor::form")
46-
.evaluate((form) => (form as HTMLFormElement).submit());
4745

48-
// Write authenticated session state to a file and output its path
49-
await context.storageState({ path: sessionStatePath });
50-
core.setOutput("session_state_path", sessionStatePath);
51-
core.info(`Wrote authenticated session state to ${sessionStatePath}`);
46+
// Check for a login form.
47+
// If no login form is found, then either HTTP Basic auth succeeded, or the page does not require authentication.
48+
core.info("Checking for login form");
49+
const [usernameField, passwordField] = await Promise.all([
50+
page.getByLabel(/username/i).first(),
51+
page.getByLabel(/password/i).first(),
52+
]);
53+
const [usernameFieldExists, passwordFieldExists] = await Promise.all([
54+
usernameField.count(),
55+
passwordField.count(),
56+
]);
57+
if (usernameFieldExists && passwordFieldExists) {
58+
// Try form authentication
59+
core.info("Filling username");
60+
await usernameField.fill(username);
61+
core.info("Filling password");
62+
await passwordField.fill(password);
63+
core.info("Logging in");
64+
await page
65+
.getByLabel(/password/i)
66+
.locator("xpath=ancestor::form")
67+
.evaluate((form) => (form as HTMLFormElement).submit());
68+
} else {
69+
core.info("No login form detected");
70+
// This occurs if HTTP Basic auth succeeded, or if the page does not require authentication.
71+
}
72+
73+
// Output authenticated session state
74+
const { cookies, origins } = await context.storageState();
75+
const authContextOutput: AuthContextOutput = {
76+
username,
77+
password,
78+
cookies,
79+
localStorage: origins.reduce((acc, { origin, localStorage }) => {
80+
acc[origin] = localStorage.reduce((acc, { name, value }) => {
81+
acc[name] = value;
82+
return acc;
83+
}, {} as Record<string, string>);
84+
return acc;
85+
}, {} as Record<string, Record<string, string>>),
86+
};
87+
core.setOutput("auth_context", JSON.stringify(authContextOutput));
88+
core.debug("Output: 'auth_context'");
5289
} catch (error) {
5390
if (page) {
5491
core.info(`Errored at page URL: ${page.url()}`);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export type Cookie = {
2+
name: string;
3+
value: string;
4+
domain: string;
5+
path: string;
6+
expires?: number;
7+
httpOnly?: boolean;
8+
secure?: boolean;
9+
sameSite?: "Strict" | "Lax" | "None";
10+
};
11+
12+
export type LocalStorage = {
13+
[origin: string]: {
14+
[key: string]: string;
15+
};
16+
};
17+
18+
export type AuthContextOutput = {
19+
username?: string;
20+
password?: string;
21+
cookies?: Cookie[];
22+
localStorage?: LocalStorage;
23+
};

.github/actions/file/package-lock.json

Lines changed: 38 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/actions/file/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"type": "module",
1515
"dependencies": {
1616
"@actions/core": "^1.11.1",
17-
"@octokit/core": "^7.0.4",
18-
"@octokit/plugin-throttling": "^11.0.1"
17+
"@octokit/core": "^7.0.5",
18+
"@octokit/plugin-throttling": "^11.0.2"
1919
},
2020
"devDependencies": {
2121
"@types/node": "^24.5.2",

.github/actions/find/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ https://primer.style
1515
https://primer.style/octicons/
1616
```
1717

18-
#### `session_state_path`
18+
#### `auth_context`
1919

20-
**Optional** Path to a file containing authenticated session state.
20+
**Optional** Stringified JSON object containing `username`, `password`, `cookies`, and/or `localStorage` from an authenticated session. For example: `{"username":"some-user","password":"correct-horse-battery-staple","cookies":[{"name":"theme-preference","value":"light","domain":"primer.style","path":"/"}],"localStorage":{"https://primer.style":{"theme-preference":"light"}}}`
2121

2222
### Outputs
2323

.github/actions/find/action.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ inputs:
66
description: "Newline-delimited list of URLs to check for accessibility issues"
77
required: true
88
multiline: true
9-
session_state_path:
10-
description: "Path to a file containing authenticated session state"
9+
auth_context:
10+
description: "Stringified JSON object containing 'username', 'password', 'cookies', and/or 'localStorage' from an authenticated session"
1111
required: false
1212

1313
outputs:
@@ -20,4 +20,4 @@ runs:
2020

2121
branding:
2222
icon: "compass"
23-
color: "blue"
23+
color: "blue"

0 commit comments

Comments
 (0)