-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathindex.ts
More file actions
96 lines (89 loc) · 3.06 KB
/
index.ts
File metadata and controls
96 lines (89 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import type {AuthContextOutput} from './types.d.js'
import process from 'node:process'
import core from '@actions/core'
import playwright from 'playwright'
export default async function () {
core.info("Starting 'auth' action")
let browser: playwright.Browser | undefined
let context: playwright.BrowserContext | undefined
let page: playwright.Page | undefined
try {
// Get inputs
const loginUrl = core.getInput('login_url', {required: true})
const username = core.getInput('username', {required: true})
const password = core.getInput('password', {required: true})
core.setSecret(password)
// Launch a headless browser
browser = await playwright.chromium.launch({
headless: true,
executablePath: process.env.CI ? '/usr/bin/google-chrome' : undefined,
})
context = await browser.newContext({
// Try HTTP Basic authentication
httpCredentials: {
username,
password,
},
})
page = await context.newPage()
// Navigate to login page
core.info('Navigating to login page')
await page.goto(loginUrl)
// Check for a login form.
// If no login form is found, then either HTTP Basic auth succeeded, or the page does not require authentication.
core.info('Checking for login form')
const [usernameField, passwordField] = await Promise.all([
page.getByLabel(/user ?name/i).first(),
page.getByLabel(/password/i).first(),
])
const [usernameFieldExists, passwordFieldExists] = await Promise.all([usernameField.count(), passwordField.count()])
if (usernameFieldExists && passwordFieldExists) {
// Try form authentication
core.info('Filling username')
await usernameField.fill(username)
core.info('Filling password')
await passwordField.fill(password)
core.info('Logging in')
await page
.getByLabel(/password/i)
.locator('xpath=ancestor::form')
.evaluate(form => (form as HTMLFormElement).submit())
} else {
core.info('No login form detected')
// This occurs if HTTP Basic auth succeeded, or if the page does not require authentication.
}
// Output authenticated session state
const {cookies, origins} = await context.storageState()
const authContextOutput: AuthContextOutput = {
username,
password,
cookies,
localStorage: origins.reduce(
(acc, {origin, localStorage}) => {
acc[origin] = localStorage.reduce(
(acc, {name, value}) => {
acc[name] = value
return acc
},
{} as Record<string, string>,
)
return acc
},
{} as Record<string, Record<string, string>>,
),
}
core.setOutput('auth_context', JSON.stringify(authContextOutput))
core.debug("Output: 'auth_context'")
} catch (error) {
if (page) {
core.info(`Errored at page URL: ${page.url()}`)
}
core.setFailed(`${error}`)
process.exit(1)
} finally {
// Clean up
await context?.close()
await browser?.close()
}
core.info("Finished 'auth' action")
}