|
1 | | -import type { AuthContextOutput } from "./types.d.js"; |
2 | | -import crypto from "node:crypto"; |
3 | | -import process from "node:process"; |
4 | | -import * as url from "node:url"; |
5 | | -import core from "@actions/core"; |
6 | | -import playwright from "playwright"; |
| 1 | +import type {AuthContextOutput} from './types.d.js' |
| 2 | +import process from 'node:process' |
| 3 | +import core from '@actions/core' |
| 4 | +import playwright from 'playwright' |
7 | 5 |
|
8 | 6 | export default async function () { |
9 | | - core.info("Starting 'auth' action"); |
| 7 | + core.info("Starting 'auth' action") |
10 | 8 |
|
11 | | - let browser: playwright.Browser | undefined; |
12 | | - let context: playwright.BrowserContext | undefined; |
13 | | - let page: playwright.Page | undefined; |
| 9 | + let browser: playwright.Browser | undefined |
| 10 | + let context: playwright.BrowserContext | undefined |
| 11 | + let page: playwright.Page | undefined |
14 | 12 | try { |
15 | 13 | // Get inputs |
16 | | - const loginUrl = core.getInput("login_url", { required: true }); |
17 | | - const username = core.getInput("username", { required: true }); |
18 | | - const password = core.getInput("password", { required: true }); |
19 | | - core.setSecret(password); |
20 | | - |
21 | | - // Determine storage path for authenticated session state |
22 | | - // Playwright will create missing directories, if needed |
23 | | - const actionDirectory = `${url.fileURLToPath(new URL(import.meta.url))}/..`; |
24 | | - const sessionStatePath = `${ |
25 | | - process.env.RUNNER_TEMP ?? actionDirectory |
26 | | - }/.auth/${crypto.randomUUID()}/sessionState.json`; |
| 14 | + const loginUrl = core.getInput('login_url', {required: true}) |
| 15 | + const username = core.getInput('username', {required: true}) |
| 16 | + const password = core.getInput('password', {required: true}) |
| 17 | + core.setSecret(password) |
27 | 18 |
|
28 | 19 | // Launch a headless browser |
29 | 20 | browser = await playwright.chromium.launch({ |
30 | 21 | headless: true, |
31 | | - executablePath: process.env.CI ? "/usr/bin/google-chrome" : undefined, |
32 | | - }); |
| 22 | + executablePath: process.env.CI ? '/usr/bin/google-chrome' : undefined, |
| 23 | + }) |
33 | 24 | context = await browser.newContext({ |
34 | 25 | // Try HTTP Basic authentication |
35 | 26 | httpCredentials: { |
36 | 27 | username, |
37 | 28 | password, |
38 | 29 | }, |
39 | | - }); |
40 | | - page = await context.newPage(); |
| 30 | + }) |
| 31 | + page = await context.newPage() |
41 | 32 |
|
42 | 33 | // Navigate to login page |
43 | | - core.info("Navigating to login page"); |
44 | | - await page.goto(loginUrl); |
| 34 | + core.info('Navigating to login page') |
| 35 | + await page.goto(loginUrl) |
45 | 36 |
|
46 | 37 | // Check for a login form. |
47 | 38 | // 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"); |
| 39 | + core.info('Checking for login form') |
49 | 40 | const [usernameField, passwordField] = await Promise.all([ |
50 | 41 | page.getByLabel(/user ?name/i).first(), |
51 | 42 | page.getByLabel(/password/i).first(), |
52 | | - ]); |
53 | | - const [usernameFieldExists, passwordFieldExists] = await Promise.all([ |
54 | | - usernameField.count(), |
55 | | - passwordField.count(), |
56 | | - ]); |
| 43 | + ]) |
| 44 | + const [usernameFieldExists, passwordFieldExists] = await Promise.all([usernameField.count(), passwordField.count()]) |
57 | 45 | if (usernameFieldExists && passwordFieldExists) { |
58 | 46 | // 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"); |
| 47 | + core.info('Filling username') |
| 48 | + await usernameField.fill(username) |
| 49 | + core.info('Filling password') |
| 50 | + await passwordField.fill(password) |
| 51 | + core.info('Logging in') |
64 | 52 | await page |
65 | 53 | .getByLabel(/password/i) |
66 | | - .locator("xpath=ancestor::form") |
67 | | - .evaluate((form) => (form as HTMLFormElement).submit()); |
| 54 | + .locator('xpath=ancestor::form') |
| 55 | + .evaluate(form => (form as HTMLFormElement).submit()) |
68 | 56 | } else { |
69 | | - core.info("No login form detected"); |
| 57 | + core.info('No login form detected') |
70 | 58 | // This occurs if HTTP Basic auth succeeded, or if the page does not require authentication. |
71 | 59 | } |
72 | 60 |
|
73 | 61 | // Output authenticated session state |
74 | | - const { cookies, origins } = await context.storageState(); |
| 62 | + const {cookies, origins} = await context.storageState() |
75 | 63 | const authContextOutput: AuthContextOutput = { |
76 | 64 | username, |
77 | 65 | password, |
78 | 66 | 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'"); |
| 67 | + localStorage: origins.reduce( |
| 68 | + (acc, {origin, localStorage}) => { |
| 69 | + acc[origin] = localStorage.reduce( |
| 70 | + (acc, {name, value}) => { |
| 71 | + acc[name] = value |
| 72 | + return acc |
| 73 | + }, |
| 74 | + {} as Record<string, string>, |
| 75 | + ) |
| 76 | + return acc |
| 77 | + }, |
| 78 | + {} as Record<string, Record<string, string>>, |
| 79 | + ), |
| 80 | + } |
| 81 | + core.setOutput('auth_context', JSON.stringify(authContextOutput)) |
| 82 | + core.debug("Output: 'auth_context'") |
89 | 83 | } catch (error) { |
90 | 84 | if (page) { |
91 | | - core.info(`Errored at page URL: ${page.url()}`); |
| 85 | + core.info(`Errored at page URL: ${page.url()}`) |
92 | 86 | } |
93 | | - core.setFailed(`${error}`); |
94 | | - process.exit(1); |
| 87 | + core.setFailed(`${error}`) |
| 88 | + process.exit(1) |
95 | 89 | } finally { |
96 | 90 | // Clean up |
97 | | - await context?.close(); |
98 | | - await browser?.close(); |
| 91 | + await context?.close() |
| 92 | + await browser?.close() |
99 | 93 | } |
100 | 94 |
|
101 | | - core.info("Finished 'auth' action"); |
| 95 | + core.info("Finished 'auth' action") |
102 | 96 | } |
0 commit comments