Skip to content

Commit 2d38546

Browse files
committed
💥 Rewrite for v4
1 parent 79c1d49 commit 2d38546

29 files changed

+10290
-2489
lines changed

‎.gitignore‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
cache/
2+
reports/
13

24
# Created by https://www.toptal.com/developers/gitignore/api/node
35
# Edit at https://www.toptal.com/developers/gitignore?templates=node

‎cli.js‎

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* @fileoverview GitHub Actions Reporting CLI - Generates reports on GitHub Actions usage across enterprises,
5+
* organizations, users, and individual repositories. Supports CSV, JSON, and Markdown output formats.
6+
*
7+
* This CLI tool helps organizations audit their GitHub Actions usage by collecting data about workflows,
8+
* secrets, variables, permissions, and action dependencies. It supports GitHub Enterprise Cloud/Server
9+
* and provides caching for improved performance on large datasets.
10+
*
11+
* @author Stefan Stölzle
12+
* @license MIT
13+
*/
14+
15+
import chalk from 'chalk'
16+
import meow from 'meow'
17+
18+
// Report class
19+
import Report from './src/report/report.js'
20+
21+
// Utilities
22+
import cacheInstance from './src/util/cache.js'
23+
import log from './src/util/log.js'
24+
25+
const {blue, bold, dim, yellow} = chalk
26+
27+
/**
28+
* Creates the help text for the CLI application.
29+
* @returns {string} The formatted help text with usage, options, and examples
30+
*/
31+
function createHelpText() {
32+
return `
33+
${bold('Usage')}
34+
${blue(`action-reporting-cli`)} ${yellow(`[options]`)}
35+
36+
${bold('Required options')} ${dim(`[one of]`)}
37+
${yellow(`--enterprise`)}, ${yellow(`-e`)} GitHub Enterprise (Cloud|Server) account slug ${dim(
38+
'(e.g. enterprise)',
39+
)}.
40+
${yellow(`--owner`)}, ${yellow(`-o`)} GitHub organization/user login ${dim('(e.g. owner)')}.
41+
${dim(
42+
`If ${yellow(`--owner`)} is a user, results for the authenticated user (${yellow(
43+
`--token`,
44+
)}) will be returned.`,
45+
)}
46+
${yellow(`--repository`)}, ${yellow(`-r`)} GitHub repository name with owner ${dim('(e.g. owner/repo)')}.
47+
48+
${bold('Additional options')}
49+
${yellow(`--token`)}, ${yellow(`-t`)} GitHub Personal Access Token (PAT) ${dim('(default GITHUB_TOKEN)')}.
50+
${yellow(`--hostname`)} GitHub Enterprise Server ${bold('hostname')} ${dim('(default api.github.com)')}.
51+
${dim(`For example: ${yellow('github.example.com')}`)}
52+
53+
${bold('Report options')}
54+
${yellow(`--all`)} Report all below.
55+
56+
${yellow(`--listeners`)} Report ${bold('on')} listeners used.
57+
${yellow(`--permissions`)} Report ${bold('permissions')} values for GITHUB_TOKEN.
58+
${yellow(`--runs-on`)} Report ${bold('runs-on')} values.
59+
${yellow(`--secrets`)} Report ${bold('secrets')} used.
60+
${yellow(`--uses`)} Report ${bold('uses')} values.
61+
${yellow(`--exclude`)} Exclude GitHub Actions created by GitHub.
62+
${dim(
63+
`From https://github.com/actions and https://github.com/github organizations.
64+
Only applies to ${yellow(`--uses`)}.`,
65+
)}
66+
${yellow(`--unique`)} List unique GitHub Actions.
67+
${dim(
68+
`Possible values are ${yellow('true')}, ${yellow('false')} and ${yellow('both')}.
69+
Only applies to ${yellow(`--uses`)}.`,
70+
)}
71+
${dim(`Will create an additional ${bold('*-unique.{csv,json,md}')} report file.`)}
72+
${yellow(`--vars`)} Report ${bold('vars')} used.
73+
74+
${bold('Output options')}
75+
${yellow(`--csv`)} Path to save CSV output ${dim('(e.g. /path/to/reports/report.csv)')}.
76+
${yellow(`--json`)} Path to save JSON output ${dim('(e.g. /path/to/reports/report.json)')}.
77+
${yellow(`--md`)} Path to save markdown output ${dim('(e.g. /path/to/reports/report.md)')}.
78+
79+
${bold('Helper options')}
80+
${yellow(`--debug`)}, ${yellow(`-d`)} Enable debug mode.
81+
${yellow(`--skipCache`)} Disable caching.
82+
${yellow(`--help`)}, ${yellow(`-h`)} Print action-reporting help.
83+
${yellow(`--version`)}, ${yellow(`-v`)} Print action-reporting version.`
84+
}
85+
86+
/**
87+
* Creates the CLI flags configuration object.
88+
* @returns {object} The CLI flags configuration for meow
89+
*/
90+
const CLI_FLAGS = {
91+
debug: {
92+
type: 'boolean',
93+
default: false,
94+
shortFlag: 'd',
95+
},
96+
skipCache: {
97+
type: 'boolean',
98+
default: false,
99+
},
100+
help: {
101+
type: 'boolean',
102+
shortFlag: 'h',
103+
},
104+
version: {
105+
type: 'boolean',
106+
shortFlag: 'v',
107+
},
108+
enterprise: {
109+
type: 'string',
110+
shortFlag: 'e',
111+
},
112+
owner: {
113+
type: 'string',
114+
shortFlag: 'o',
115+
},
116+
repository: {
117+
type: 'string',
118+
shortFlag: 'r',
119+
},
120+
token: {
121+
type: 'string',
122+
default: process.env.GITHUB_TOKEN || '',
123+
shortFlag: 't',
124+
},
125+
all: {
126+
type: 'boolean',
127+
default: false,
128+
},
129+
listeners: {
130+
type: 'boolean',
131+
default: false,
132+
},
133+
permissions: {
134+
type: 'boolean',
135+
default: false,
136+
},
137+
runsOn: {
138+
type: 'boolean',
139+
default: false,
140+
},
141+
secrets: {
142+
type: 'boolean',
143+
default: false,
144+
},
145+
uses: {
146+
type: 'boolean',
147+
default: false,
148+
},
149+
exclude: {
150+
type: 'boolean',
151+
default: false,
152+
},
153+
unique: {
154+
type: 'string',
155+
default: 'false',
156+
},
157+
vars: {
158+
type: 'boolean',
159+
default: false,
160+
},
161+
cache: {
162+
type: 'boolean',
163+
default: false,
164+
},
165+
hostname: {
166+
type: 'string',
167+
},
168+
csv: {
169+
type: 'string',
170+
},
171+
md: {
172+
type: 'string',
173+
},
174+
json: {
175+
type: 'string',
176+
},
177+
}
178+
179+
const cli = meow(createHelpText(), {
180+
booleanDefault: undefined,
181+
description: false,
182+
hardRejection: false,
183+
allowUnknownFlags: false,
184+
importMeta: import.meta,
185+
inferType: false,
186+
input: [],
187+
flags: CLI_FLAGS,
188+
})
189+
190+
/**
191+
* Main execution function that orchestrates the CLI application.
192+
* Handles input validation, option processing, and delegates to appropriate processing functions.
193+
* @async
194+
* @returns {Promise<void>}
195+
* @throws {Error} When validation fails or processing encounters errors
196+
*/
197+
async function main() {
198+
console.log(`${bold('@stoe/action-reporting-cli')} ${dim(`v${cli.pkg.version}`)}\n`)
199+
200+
const {token, hostname, enterprise, owner, repository, debug, help, version} = cli.flags
201+
const entity = enterprise || owner || repository
202+
const logger = log(entity, token, debug)
203+
const cache = cacheInstance(null, logger)
204+
205+
try {
206+
// Handle help and version flags early exit
207+
if (help) cli.showHelp(0)
208+
if (version) cli.showVersion(0)
209+
210+
const report = new Report(cli.flags, logger, cache)
211+
let results
212+
213+
if (enterprise) {
214+
results = await report.processEnterprise(enterprise, token, hostname, debug)
215+
} else if (owner) {
216+
results = await report.processOwner(owner, token, hostname, debug)
217+
} else if (repository) {
218+
results = await report.processRepository(repository, token, hostname, debug)
219+
}
220+
221+
const reportData = await report.createReport(results)
222+
reportData.length && (await report.saveReports(reportData))
223+
} catch (error) {
224+
logger.fail(error.message)
225+
226+
// Log error stack trace in debug mode
227+
debug && logger.error(error.stack)
228+
}
229+
}
230+
231+
// Execute the main function
232+
main()

0 commit comments

Comments
 (0)