@vidavidorra/create-project
Version:
Interactively create a GitHub project
112 lines • 3.75 kB
JavaScript
import { parse, stringify } from 'yaml';
import { z } from 'zod';
import { File } from './file.js';
const job = (action) => z.object({
uses: z
.string()
.startsWith(`vidavidorra/.github/.github/workflows/${action}@`)
.regex(/.*?@[\da-f]{6,64}$/),
});
const schema = z
.object({
name: z.literal('CI/CD'),
on: z.object({
push: z.object({
branches: z.tuple([
z.literal('main'),
z.literal('beta'),
z.literal('renovate/**'),
]),
}),
// eslint-disable-next-line @typescript-eslint/naming-convention
pull_request: z.null(),
}),
jobs: z
.object({
'lint-commit-messages': job('lint-commit-messages.yml'),
lint: job('node-lint.yml'),
build: job('node-build.yml'),
test: job('node-test.yml'),
'code-coverage': job('node-test-coverage.yml').extend({
needs: z.tuple([
z.literal('lint'),
z.literal('build'),
z.literal('test'),
]),
secrets: z.object({ codecovToken: z.string() }),
}),
release: job('release.yml').extend({
needs: z
.array(z.union([
z.literal('lint-commit-messages'),
z.literal('lint'),
z.literal('build'),
z.literal('test'),
z.literal('code-coverage'),
]))
.length(5),
secrets: z.object({
privateKey: z.string(),
npmToken: z.string(),
}),
}),
})
.strict(),
})
.strict();
class CiCd extends File {
_yaml;
constructor(path, options) {
super(path, { ...options, format: true });
this._yaml = schema.parse(parse(this._content));
}
process() {
const data = schema.deepPartial().parse(this._yaml);
const removeFromRelease = [];
if (!this._options.typescript) {
delete data.jobs?.build;
removeFromRelease.push('build');
}
if (!this._options.typescript || !this._options.testing) {
delete data.jobs?.test;
removeFromRelease.push('test');
}
if (!this._options.typescript ||
!this._options.testing ||
!this._options.reportCodeCoverage) {
delete data.jobs?.['code-coverage'];
removeFromRelease.push('code-coverage');
}
if (data.jobs?.release?.needs !== undefined) {
data.jobs.release.needs = data.jobs.release.needs.filter((action) => !removeFromRelease.includes(action));
}
if (!this._options.public) {
delete data.jobs?.release?.secrets?.npmToken;
}
const { sha, version } = this;
this._content = stringify(data).replaceAll(sha, `${sha}${version}`);
return this;
}
get sha() {
const sha = this._yaml.jobs.lint.uses.split('@').at(1);
if (sha === undefined) {
throw new Error('SHA is required in YAML');
}
return sha;
}
get version() {
const job = 'lint';
const value = this._yaml.jobs[job].uses;
const line = this._content.split('\n').find((line) => line.includes(value));
if (line === undefined) {
throw new Error(`"${job}" job not found in content`);
}
const version = line.replace(new RegExp(`^.*${value}`), '');
if (!/ +# v\d+\.\d+\.\d+$/.test(version)) {
throw new Error(`Version is not in a valid format (version: "${version}")`);
}
return version;
}
}
export { CiCd };
//# sourceMappingURL=ci-cd.js.map