Skip to content

Commit bdb5de9

Browse files
committed
feat: Replace 'session_state_path' (a string) with 'playwright_context_options' (a stringified object containing that string—and other stuff too)
1 parent 8eae088 commit bdb5de9

9 files changed

Lines changed: 37 additions & 26 deletions

File tree

.github/actions/auth/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ Authenticate with Playwright and save session state. Supports HTTP Basic and for
2323
2424
### Outputs
2525

26-
#### `session_state_path`
26+
#### `playwright_context_options`
2727

28-
Path to a file containing authenticated session state.
28+
Stringified JSON object containing [Playwright `BrowserContext`](https://playwright.dev/docs/api/class-browsercontext) options, including `httpCredentials` and `storageState`. For example: `{"httpCredentials":{"username":"some-user",password:"correct-horse-battery-staple"},"storageState":"/tmp/.auth/12345678/sessionState.json"}`

.github/actions/auth/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ inputs:
1313
required: true
1414

1515
outputs:
16-
session_state_path:
17-
description: "Path to a file containing authenticated session state"
16+
playwright_context_options:
17+
description: "Stringified JSON object containing Playwright 'BrowserContext' options, including 'httpCredentials' and 'storageState'"
1818

1919
runs:
2020
using: "node20"

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ export default async function () {
3232
context = await browser.newContext({
3333
// Try HTTP Basic authentication
3434
httpCredentials: {
35-
username: username,
36-
password: password,
35+
username,
36+
password,
3737
},
3838
});
3939
page = await context.newPage();
@@ -66,8 +66,14 @@ export default async function () {
6666

6767
// Write authenticated session state to a file and output its path
6868
await context.storageState({ path: sessionStatePath });
69-
core.setOutput("session_state_path", sessionStatePath);
7069
core.info(`Wrote authenticated session state to ${sessionStatePath}`);
70+
core.setOutput(
71+
"playwright_context_options",
72+
JSON.stringify({
73+
httpCredentials: { username, password },
74+
storageState: sessionStatePath,
75+
})
76+
);
7177
} catch (error) {
7278
if (page) {
7379
core.info(`Errored at page URL: ${page.url()}`);

.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+
#### `playwright_context_options`
1919

20-
**Optional** Path to a file containing authenticated session state.
20+
**Optional** Stringified JSON object containing [Playwright `BrowserContext`](https://playwright.dev/docs/api/class-browsercontext) options, including `httpCredentials` and `storageState`. For example: `{"httpCredentials":{"username":"some-user",password:"correct-horse-battery-staple"},"storageState":"/tmp/.auth/12345678/sessionState.json"}`
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+
playwright_context_options:
10+
description: "Stringified JSON object containing Playwright 'BrowserContext' options, including 'httpCredentials' and 'storageState'"
1111
required: false
1212

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

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

.github/actions/find/src/findForUrl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import type { Finding } from './types.d.js';
22
import AxeBuilder from '@axe-core/playwright'
33
import playwright from 'playwright';
44

5-
export async function findForUrl(url: string, sessionStatePath?: string): Promise<Finding[]> {
5+
export async function findForUrl(url: string, playwrightContextOptions?: playwright.BrowserContextOptions): Promise<Finding[]> {
66
const browser = await playwright.chromium.launch({ headless: true, executablePath: process.env.CI ? '/usr/bin/google-chrome' : undefined });
7-
const context = await browser.newContext({ storageState: !!sessionStatePath ? sessionStatePath : undefined });
7+
const context = await browser.newContext(playwrightContextOptions);
88
const page = await context.newPage();
99
await page.goto(url);
1010

.github/actions/find/src/index.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1+
import type playwright from "playwright";
12
import core from "@actions/core";
23
import { findForUrl } from "./findForUrl.js";
34

45
export default async function () {
56
core.info("Starting 'find' action");
6-
const urls = core.getMultilineInput('urls', { required: true });
7+
const urls = core.getMultilineInput("urls", { required: true });
78
core.debug(`Input: 'urls: ${JSON.stringify(urls)}'`);
8-
const sessionStatePath = core.getInput('session_state_path', { required: false });
9-
core.debug(`Input: 'session_state_path: ${sessionStatePath}'`);
9+
const playwrightContextOptions: playwright.BrowserContextOptions = JSON.parse(
10+
core.getInput("playwright_context_options", { required: false }) ?? "{}"
11+
);
12+
if (playwrightContextOptions?.httpCredentials?.password) {
13+
core.setSecret(playwrightContextOptions.httpCredentials.password);
14+
}
1015

1116
let findings = [];
1217
for (const url of urls) {
13-
core.info(`Scanning ${url}`)
14-
const findingsForUrl = await findForUrl(url, sessionStatePath);
18+
core.info(`Scanning ${url}`);
19+
const findingsForUrl = await findForUrl(url, playwrightContextOptions);
1520
if (findingsForUrl.length === 0) {
1621
core.info(`No accessibility gaps were found on ${url}`);
1722
continue;

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ Trigger the workflow manually or automatically based on your configuration. The
100100
| `login_url` | No | If scanned pages require authentication, the URL of the login page | `https://github.com/login` |
101101
| `username` | No | If scanned pages require authentication, the username to use for login | `some-user` |
102102
| `password` | No | If scanned pages require authentication, the password to use for login | `correct-horse-battery-staple` |
103-
| `session_state_path` | No | If scanned pages require authentication, the path to a file containing authenticated session state | `/tmp/.auth/12345678/sessionState.json` |
103+
| `playwright_context_options` | No | If scanned pages require authentication, a stringified JSON object containing [Playwright `BrowserContext`](https://playwright.dev/docs/api/class-browsercontext) options | `{"storageState":"/tmp/.auth/12345678/sessionState.json"}` |
104104
| `skip_copilot_assignment` | No | Whether to skip assigning filed issues to Copilot | `true` |
105105

106106
---
@@ -109,7 +109,7 @@ Trigger the workflow manually or automatically based on your configuration. The
109109

110110
If access to a page requires logging-in first, and logging-in requires only a username and password, then provide the `login_url`, `username`, and `password` inputs.
111111

112-
If your login flow is more complex—if it requires two-factor authentication, single sign-on, passkeys, etc.–and you have a custom action that [authenticates with Playwright](https://playwright.dev/docs/auth) and persists authenticated session state to a file, then provide the `session_state_path` input. (If `session_state_path` is provided, `login_url`, `username`, and `password` will be ignored.)
112+
If your login flow is more complex—if it requires two-factor authentication, single sign-on, passkeys, etc.–and you have a custom action that [authenticates with Playwright](https://playwright.dev/docs/auth) and persists authenticated session state to a file, then provide the `playwright_context_options` input. (If `playwright_context_options` is provided, `login_url`, `username`, and `password` will be ignored.)
113113

114114
> [!IMPORTANT]
115115
> Don’t put passwords in your workflow as plain text; instead reference a [repository secret](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets#creating-secrets-for-a-repository).

action.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ inputs:
2424
password:
2525
description: "If scanned pages require authentication, the password to use for login"
2626
required: false
27-
session_state_path:
28-
description: "If scanned pages require authentication, the path to a file containing authenticated session state"
27+
playwright_context_options:
28+
description: "If scanned pages require authentication, a stringified JSON object containing Playwright 'BrowserContext' options"
2929
required: false
3030
skip_copilot_assignment:
3131
description: "Whether to skip assigning filed issues to Copilot"
@@ -51,7 +51,7 @@ runs:
5151
with:
5252
key: ${{ steps.cache_key.outputs.cache_key }}
5353
token: ${{ inputs.token }}
54-
- if: ${{ inputs.login_url && inputs.username && inputs.password && !inputs.session_state_path }}
54+
- if: ${{ inputs.login_url && inputs.username && inputs.password && !inputs.playwright_context_options }}
5555
name: Authenticate
5656
id: auth
5757
uses: ./.github/actions/auth
@@ -64,7 +64,7 @@ runs:
6464
uses: ./.github/actions/find
6565
with:
6666
urls: ${{ inputs.urls }}
67-
session_state_path: ${{ inputs.session_state_path || steps.auth.outputs.session_state_path }}
67+
playwright_context_options: ${{ inputs.playwright_context_options || steps.auth.outputs.playwright_context_options }}
6868
- name: File
6969
id: file
7070
uses: ./.github/actions/file
@@ -90,4 +90,4 @@ runs:
9090

9191
branding:
9292
icon: "compass"
93-
color: "blue"
93+
color: "blue"

0 commit comments

Comments
 (0)