knip
Version:
Find unused files, dependencies and exports in your TypeScript and JavaScript projects
54 lines (53 loc) • 2.55 kB
JavaScript
import { _firstGlob } from '../../util/glob.js';
import { isDeferResolveEntry, toEntry } from '../../util/input.js';
import { findByKeyDeep } from '../../util/object.js';
import { join, relative } from '../../util/path.js';
const title = 'GitHub Actions';
const enablers = 'This plugin is enabled when a `.yml` or `.yaml` file is found in the `.github/workflows` folder.';
const isEnabled = async ({ cwd }) => Boolean(await _firstGlob({ cwd, patterns: ['.github/workflows/*.{yml,yaml}'] }));
const isRootOnly = true;
const config = ['.github/workflows/*.{yml,yaml}', '.github/**/action.{yml,yaml}'];
const isString = (value) => typeof value === 'string';
const getActionDependencies = (config, options) => {
const { configFileDir, configFileName } = options;
const isActionManifest = configFileName === 'action.yml' || configFileName === 'action.yaml';
if (!(isActionManifest && config?.runs?.using?.startsWith('node')))
return [];
const runs = config.runs;
const scripts = [runs.pre, runs.main, runs.post].filter(isString);
return scripts.map(script => join(configFileDir, script));
};
const resolveConfig = async (config, options) => {
const { rootCwd, getInputsFromScripts, isProduction } = options;
const inputs = new Set();
const jobs = findByKeyDeep(config, 'steps');
for (const steps of jobs) {
if (!Array.isArray(steps.steps))
continue;
const action = steps.steps.find(step => step.uses?.startsWith('actions/checkout@') && typeof step.with?.path === 'string' && !step.with.repository);
const path = action?.with?.path;
for (const step of steps.steps) {
const workingDir = step['working-directory'];
const dir = join(rootCwd, path && workingDir ? relative(workingDir, path) : workingDir ? workingDir : '.');
if (step.run) {
for (const input of getInputsFromScripts([step.run], { knownBinsOnly: true })) {
if (isDeferResolveEntry(input) && path && !workingDir) {
input.specifier = relative(join(dir, path), join(rootCwd, input.specifier));
}
if (isProduction)
Object.assign(input, { optional: true });
inputs.add({ ...input, dir });
}
}
}
}
return [...inputs, ...getActionDependencies(config, options).map(toEntry)];
};
export default {
title,
enablers,
isEnabled,
isRootOnly,
config,
resolveConfig,
};