-
Notifications
You must be signed in to change notification settings - Fork 17
/
utils.ts
146 lines (125 loc) · 4.6 KB
/
utils.ts
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import * as github from '@actions/github';
import * as fs from 'fs';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import Ajv from 'ajv';
import * as path from 'path';
import JSON from 'json5';
import { promisify } from 'util';
import { GitHubMetadata } from './contracts/collection';
import devContainerFeatureSchema from './schemas/devContainerFeature.schema.json';
export const readLocalFile = promisify(fs.readFile);
export const writeLocalFile = promisify(fs.writeFile);
export const mkdirLocal = promisify(fs.mkdir);
export const renameLocal = promisify(fs.rename);
export const readdirLocal = promisify(fs.readdir);
export function getGitHubMetadata() {
// Insert github repo metadata
const ref = github.context.ref;
let metadata: GitHubMetadata = {
owner: github.context.repo.owner,
repo: github.context.repo.repo,
ref,
sha: github.context.sha
};
// Add tag if parseable
if (ref.includes('refs/tags/')) {
const tag = ref.replace('refs/tags/', '');
metadata = { ...metadata, tag };
}
return metadata;
}
export async function isDevcontainerCliAvailable(cliDebugMode = false): Promise<boolean> {
try {
let cmd = 'devcontainer';
let args = ['--version'];
if (cliDebugMode) {
cmd = 'npx';
args = ['-y', './devcontainer.tgz', ...args];
}
const res = await exec.getExecOutput(cmd, args, {
ignoreReturnCode: true,
silent: true
});
core.info(`Devcontainer CLI version '${res.stdout}' is installed.`);
return res.exitCode === 0;
} catch (err) {
return false;
}
}
export async function addRepoTagForPublishedTag(type: string, id: string, version: string): Promise<boolean> {
const octokit = github.getOctokit(process.env.GITHUB_TOKEN || '');
const tag = `${type}_${id}_${version}`;
core.info(`Adding repo tag '${tag}'...`);
try {
await octokit.rest.git.createRef({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
ref: `refs/tags/${tag}`,
sha: github.context.sha
});
await octokit.rest.git.createTag({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
tag,
message: `${tag}`,
object: github.context.sha,
type: 'commit'
});
} catch (err) {
core.warning(`Failed to automatically add repo tag, manually tag with: 'git tag ${tag} ${github.context.sha}'`);
core.debug(`${err}`);
return false;
}
core.info(`Tag '${tag}' added.`);
return true;
}
export async function ensureDevcontainerCliPresent(cliDebugMode = false): Promise<boolean> {
if (await isDevcontainerCliAvailable(cliDebugMode)) {
return true;
}
if (cliDebugMode) {
core.error('Cannot remotely fetch CLI in debug mode');
return false;
}
// Unless this override is set,
// we'll fetch the latest version of the CLI published to NPM
const cliVersion = core.getInput('devcontainer-cli-version');
let cli = '@devcontainers/cli';
if (cliVersion) {
core.info(`Manually overriding CLI version to '${cliVersion}'`);
cli = `${cli}@${cliVersion}`;
}
try {
core.info('Fetching the latest @devcontainer/cli...');
const res = await exec.getExecOutput('npm', ['install', '-g', cli], {
ignoreReturnCode: true,
silent: true
});
return res.exitCode === 0;
} catch (err) {
core.error(`Failed to fetch @devcontainer/cli: ${err}`);
return false;
}
}
export async function validateFeatureSchema(pathToAFeatureDir: string): Promise<boolean> {
const ajv = new Ajv();
ajv.addSchema(devContainerFeatureSchema);
const validate = ajv.compile(devContainerFeatureSchema);
const devContainerFeaturePath = path.join(pathToAFeatureDir, 'devcontainer-feature.json');
// Read this Feature's devcontainer-feature.json
if (!fs.existsSync(devContainerFeaturePath)) {
core.error(`(!) ERR: devcontainer-feature.json not found at path '${devContainerFeaturePath}'.`);
return false;
}
const featureJson = await readLocalFile(devContainerFeaturePath, 'utf8');
const isValid = validate(JSON.parse(featureJson));
if (!isValid) {
core.error(`(!) ERR: '${devContainerFeaturePath}' is not valid:`);
const output = JSON.stringify(validate.errors, undefined, 4);
core.info(output);
return false;
}
// No parse errors.
return true;
}