cpoach.sh 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +362 -26
- package/package.json +4 -2
- package/.github/workflows/on-push.yml +0 -35
package/index.js
CHANGED
|
@@ -1,7 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
1
2
|
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
2
4
|
const path = require('path');
|
|
5
|
+
const cp = require('child_process');
|
|
6
|
+
const readline = require('readline');
|
|
3
7
|
|
|
8
|
+
const PRE = '# 🍳 ';
|
|
4
9
|
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
//#region UTILS
|
|
14
|
+
// Escape special characters in a string for use in a regular expression.
|
|
15
|
+
function escapeRegExp(pat) {
|
|
16
|
+
return pat.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// Read a text file synchronously and normalize line endings to LF.
|
|
21
|
+
function readTextFileSync(pth) {
|
|
22
|
+
const data = fs.readFileSync(pth, 'utf8');
|
|
23
|
+
return data.replace(/\r?\n|\r/g, '\n');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// Write a text file synchronously and normalize line endings to LF.
|
|
28
|
+
function writeTextFileSync(pth, text) {
|
|
29
|
+
const data = text.replace(/\r?\n|\r/g, os.EOL);
|
|
30
|
+
fs.writeFileSync(pth, data, 'utf8');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// Read a JSON file synchronously and parse it.
|
|
35
|
+
function readJSONFileSync(pth) {
|
|
36
|
+
const text = readTextFileSync(pth);
|
|
37
|
+
return JSON.parse(text);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
// Write a JSON file synchronously and stringify it with indentation.
|
|
42
|
+
function writeJSONFileSync(pth, obj) {
|
|
43
|
+
const text = JSON.stringify(obj, null, 2) + '\n';
|
|
44
|
+
writeTextFileSync(pth, text);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// Prompt the user for input.
|
|
49
|
+
function prompt(query, def='') {
|
|
50
|
+
const rl = readline.createInterface({
|
|
51
|
+
input: process.stdin,
|
|
52
|
+
output: process.stdout
|
|
53
|
+
});
|
|
54
|
+
return new Promise(resolve => {
|
|
55
|
+
let q = def? `${query} [${def}]: ` : `${query}: `;
|
|
56
|
+
rl.question(q, answer => {
|
|
57
|
+
rl.close();
|
|
58
|
+
resolve(answer.trim()? answer : def);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
//#region SECTION COMMANDS
|
|
68
|
+
// Remove excess section gaps (> 2).
|
|
69
|
+
function sectionTrim(data, prefix) {
|
|
70
|
+
const pre = escapeRegExp(prefix);
|
|
71
|
+
const re = new RegExp(`^${pre}endregion\n{4,}${pre}region.*?`, 'gm');
|
|
72
|
+
return data.replace(re, `${prefix}endregion\n\n\n${prefix}region`).trim() + '\n';
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// Extract a section from a text file based on region markers.
|
|
77
|
+
function sectionExtract(data, prefix, name) {
|
|
78
|
+
const pre = escapeRegExp(prefix);
|
|
79
|
+
const re = new RegExp(`^${pre}region ${name}$([\\s\\S]*?)^${pre}endregion$`, 'g');
|
|
80
|
+
const m = re.exec(data);
|
|
81
|
+
return m? m[1].trim() : null;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
// Remove a section from a text file based on region markers.
|
|
86
|
+
function sectionRemove(data, prefix, name) {
|
|
87
|
+
const pre = escapeRegExp(prefix);
|
|
88
|
+
const re = new RegExp(`^${pre}region ${name}$[\\s\\S]*?^${pre}endregion$`, 'g');
|
|
89
|
+
return data.replace(re, '');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// Add a section to a text file based on region markers (if it doesn't already exist).
|
|
94
|
+
function sectionAdd(data, prefix, name, content) {
|
|
95
|
+
if (sectionExists(data, prefix, name)) return data;
|
|
96
|
+
return data.trim() +
|
|
97
|
+
`\n\n\n` +
|
|
98
|
+
`${prefix}region ${name}\n` +
|
|
99
|
+
`${content.trim()}\n` +
|
|
100
|
+
`${prefix}endregion\n`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
// Replace a section in a text file based on region markers.
|
|
105
|
+
function sectionReplace(data, prefix, name, content) {
|
|
106
|
+
const pre = escapeRegExp(prefix);
|
|
107
|
+
const re = new RegExp(`^${pre}region ${name}$[\\s\\S]*?^${pre}endregion$`, 'g');
|
|
108
|
+
return data.replace(re,
|
|
109
|
+
`${prefix}region ${name}\n` +
|
|
110
|
+
`${content.trim()}\n` +
|
|
111
|
+
`${prefix}endregion\n`
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
//#region VERSION COMMAND
|
|
120
|
+
// Fetch the current version of the tool from package.json.
|
|
121
|
+
function fetchVersion() {
|
|
122
|
+
const p = readJSONFileSync(path.join(__dirname, 'package.json'));
|
|
123
|
+
return p.version || '0.0.0';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
// Run the `version` command, which displays the current version of the tool.
|
|
128
|
+
function runVersion() {
|
|
129
|
+
console.error(`cpoach version ${fetchVersion()}\n`);
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
//#region HELP COMMAND
|
|
137
|
+
// Run the help command, which displays usage information.
|
|
138
|
+
function runHelp() {
|
|
139
|
+
console.error(
|
|
140
|
+
`cpoach - A C/C++ package manager using the npm registry (v${fetchVersion()})\n` +
|
|
141
|
+
`\n` +
|
|
142
|
+
`Usage: cpoach [command] [options]\n` +
|
|
143
|
+
`\n` +
|
|
144
|
+
`Commands:\n` +
|
|
145
|
+
` init Initialize a new C/C++ project.\n` +
|
|
146
|
+
` install Install dependencies.\n` +
|
|
147
|
+
` build Build the project.\n` +
|
|
148
|
+
` run Run the executable.\n` +
|
|
149
|
+
` config Configure dependencies.\n` +
|
|
150
|
+
` format Format code.\n` +
|
|
151
|
+
` sanitize Run sanitizers.\n` +
|
|
152
|
+
` lint Lint code.\n` +
|
|
153
|
+
` i | includes Generate compiler flags for include paths.\n` +
|
|
154
|
+
`\n` +
|
|
155
|
+
`Options:\n` +
|
|
156
|
+
` --compiler [name] Specify the compiler (msvc, gcc, clang). Default is gcc.\n` +
|
|
157
|
+
` --msvc Shortcut for --compiler msvc.\n` +
|
|
158
|
+
` --gcc Shortcut for --compiler gcc.\n` +
|
|
159
|
+
` --clang Shortcut for --compiler clang.\n`
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
//#endregion
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
//#region INCLUDES COMMAND
|
|
5
168
|
// Run the `includes` command, which generates compiler flags for include paths.
|
|
6
169
|
function runIncludes(opt) {
|
|
7
170
|
const includes = [];
|
|
@@ -14,40 +177,205 @@ function runIncludes(opt) {
|
|
|
14
177
|
const FLAG = opt.compiler==='msvc'? '/I' : '-I';
|
|
15
178
|
console.log(includes.map(pth => `${FLAG}"${pth}"`).join(' ').trim());
|
|
16
179
|
}
|
|
180
|
+
//#endregion
|
|
17
181
|
|
|
18
182
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
183
|
+
|
|
184
|
+
//#region INIT COMMAND
|
|
185
|
+
// Get the Git repository URL from the current directory, if it exists.
|
|
186
|
+
function gitRepoUrl() {
|
|
187
|
+
try { return cp.execSync('git config --get remote.origin.url', {encoding: 'utf8'}).trim(); }
|
|
188
|
+
catch { return ''; }
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
// Initialize .gitignore to ignore dependencies and build artifacts.
|
|
193
|
+
function initGitignore(cwd) {
|
|
194
|
+
const pth = path.join(cwd, '.gitignore');
|
|
195
|
+
let data = fs.existsSync(pth)? readTextFileSync(pth) : '';
|
|
196
|
+
if (!/node_modules\//.test(data)) data = sectionAdd(data, PRE, 'Dependencies', `node_modules/`);
|
|
197
|
+
if (!/build\//.test(data)) data = sectionAdd(data, PRE, 'Build', `build/`);
|
|
198
|
+
writeTextFileSync(pth, sectionTrim(data));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
// Initialize .npmignore to ignore dependencies and build artifacts.
|
|
203
|
+
function initNpmignore(cwd) {
|
|
204
|
+
const pth = path.join(cwd, '.npmignore');
|
|
205
|
+
let data = fs.existsSync(pth)? readTextFileSync(pth) : '';
|
|
206
|
+
if (!/build\//.test(data)) data = sectionAdd(data, PRE, 'Build', `build/`);
|
|
207
|
+
writeTextFileSync(pth, sectionTrim(data));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
// Initialize source files based on package.json.
|
|
212
|
+
function initSourceFiles(cwd, pkg) {
|
|
213
|
+
const p = pkg;
|
|
214
|
+
const files = p.sourceFiles || ['main.cxx'];
|
|
215
|
+
let main = null;
|
|
216
|
+
for (const file of files) {
|
|
217
|
+
const pth = path.join(cwd, file);
|
|
218
|
+
const dir = path.dirname(pth);
|
|
219
|
+
if (!/\?|\*/.test(dir)) fs.mkdirSync(dir, {recursive: true});
|
|
220
|
+
if ( /\?|\*/.test(file)) continue;
|
|
221
|
+
if (fs.existsSync(pth)) continue;
|
|
222
|
+
if (/main\.(c|cxx|cpp|cc)$/.test(file)) main = main || pth;
|
|
223
|
+
fs.writeFileSync(pth, '');
|
|
224
|
+
}
|
|
225
|
+
if (!main) return;
|
|
226
|
+
const data = readTextFileSync(main);
|
|
227
|
+
if (data.trim()) return;
|
|
228
|
+
writeTextFileSync(main,
|
|
229
|
+
`#include <iostream>\n` +
|
|
26
230
|
`\n` +
|
|
27
|
-
`
|
|
28
|
-
`
|
|
29
|
-
`
|
|
30
|
-
`
|
|
31
|
-
` --clang Shortcut for --compiler clang.\n`
|
|
231
|
+
`int main() {\n` +
|
|
232
|
+
` std::cout << "Hello, world!\\n";\n` +
|
|
233
|
+
` return 0;\n` +
|
|
234
|
+
`}\n`
|
|
32
235
|
);
|
|
33
236
|
}
|
|
34
237
|
|
|
35
238
|
|
|
36
|
-
//
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
|
|
239
|
+
// Initialize CMakeLists.txt based on package.json.
|
|
240
|
+
function initCMakeLists(cwd, pkg) {
|
|
241
|
+
const p = pkg;
|
|
242
|
+
const projectName = p.name;
|
|
243
|
+
const isExecutable = p.type === 'executable';
|
|
244
|
+
const cxxStandard = p.cmake.options.CMAKE_CXX_STANDARD || '17';
|
|
245
|
+
const generator = p.cmake.generator || null;
|
|
246
|
+
const pth = path.join(cwd, 'CMakeLists.txt');
|
|
247
|
+
let data = fs.existsSync(pth)? readTextFileSync(pth) : '';
|
|
248
|
+
if (!/cmake_minimum_required/.test(data)) {
|
|
249
|
+
data = sectionReplace(data, PRE, 'Project details',
|
|
250
|
+
`cmake_minimum_required(VERSION ${p.cmake.minVersion || '3.15'})\n` +
|
|
251
|
+
`project(${projectName} VERSION ${p.version} LANGUAGES CXX)\n`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
data = sectionReplace(data, PRE, 'Include dependencies',
|
|
255
|
+
`include(dependencies.cmake OPTIONAL)`
|
|
256
|
+
);
|
|
257
|
+
if (!/set\(CMAKE_CXX_STANDARD\s/.test(data)) {
|
|
258
|
+
data = sectionReplace(data, PRE, 'Set C++ standard',
|
|
259
|
+
`set(CMAKE_CXX_STANDARD ${cxxStandard})\n` +
|
|
260
|
+
`set(CMAKE_CXX_STANDARD_REQUIRED ON)`
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
if (isExecutable) {
|
|
264
|
+
data = sectionReplace(data, PRE, 'Define executable target',
|
|
265
|
+
`add_executable(${projectName} main.cxx)\n` +
|
|
266
|
+
`target_include_directories(${projectName} PRIVATE include)`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
data = sectionReplace(data, PRE, 'Define library target',
|
|
271
|
+
`add_library(${projectName} main.cxx)\n` +
|
|
272
|
+
`target_include_directories(${projectName} PUBLIC include)`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
data = sectionReplace(data, PRE, 'Link dependencies',
|
|
276
|
+
`# target_link_libraries(${projectName} PRIVATE dependencies)`
|
|
277
|
+
);
|
|
278
|
+
data = sectionReplace(data, PRE, 'Link system dependencies',
|
|
279
|
+
`# find_package(OpenSSL REQUIRED)\n` +
|
|
280
|
+
`# target_link_libraries(${projectName} PRIVATE OpenSSL::SSL)`
|
|
281
|
+
);
|
|
282
|
+
writeTextFileSync(pth, sectionTrim(data));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
async function runInit() {
|
|
287
|
+
const cwd = process.cwd();
|
|
288
|
+
const pth = path.join(cwd, 'package.json');
|
|
289
|
+
if (fs.existsSync(pth)) {
|
|
290
|
+
const overwrite = await prompt('package.json already exists. Overwrite? (y/N) ');
|
|
291
|
+
if (overwrite.toLowerCase() !== 'y') { console.error('Aborted.'); return; }
|
|
292
|
+
}
|
|
293
|
+
// Gather project info
|
|
294
|
+
const name = await prompt('Project name', path.basename(cwd));
|
|
295
|
+
const version = await prompt('Version', '1.0.0');
|
|
296
|
+
const description = await prompt('Description', '');
|
|
297
|
+
const type = await prompt('Project type (executable/library)', 'executable');
|
|
298
|
+
const sourceFiles = await prompt('Source files (A; B)', 'main.cxx');
|
|
299
|
+
const cxxStandard = await prompt('C++ standard (11/14/17/20)', '17');
|
|
300
|
+
// const generator = await prompt('CMake generator (Ninja/Makefiles/VS)', 'Ninja');
|
|
301
|
+
const testCommand = await prompt('Test command', 'echo "No tests defined"');
|
|
302
|
+
const gitRepo = await prompt('Git repository URL', gitRepoUrl());
|
|
303
|
+
const keywords = await prompt('Keywords (A; B)', '');
|
|
304
|
+
const author = await prompt('Author', '');
|
|
305
|
+
const license = await prompt('License', 'MIT');
|
|
306
|
+
// Create package.json
|
|
307
|
+
const pkg = {}, p = pkg;
|
|
308
|
+
p.name = name;
|
|
309
|
+
p.version = version;
|
|
310
|
+
p.description = description;
|
|
311
|
+
p.type = type === 'executable'? 'executable' : 'library';
|
|
312
|
+
p.sourceFiles = sourceFiles.split(';').map(s => s.trim()).filter(s => s);
|
|
313
|
+
if (testCommand) p.scripts = {test: testCommand};
|
|
314
|
+
if (gitRepo) {
|
|
315
|
+
p.homepage = `${gitRepo}#readme`;
|
|
316
|
+
p.bugs = {url: `${gitRepo}/issues`};
|
|
317
|
+
p.repository = {
|
|
318
|
+
type: 'git',
|
|
319
|
+
url: gitRepo
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
p.keywords = keywords.split(';').map(s => s.trim()).filter(s => s);
|
|
323
|
+
if (author) p.author = author;
|
|
324
|
+
if (license) p.license = license;
|
|
325
|
+
p.dependencies = {};
|
|
326
|
+
p.devDependencies = {};
|
|
327
|
+
p.systemDependencies = {
|
|
328
|
+
linux: [],
|
|
329
|
+
darwin: [],
|
|
330
|
+
win32: []
|
|
331
|
+
};
|
|
332
|
+
p.cmake = {};
|
|
333
|
+
p.cmake.minVersion = '3.15';
|
|
334
|
+
if (generator) p.cmake.generator = generator;
|
|
335
|
+
p.cmake.options = {
|
|
336
|
+
CMAKE_CXX_STANDARD: cxxStandard,
|
|
337
|
+
BUILD_SHARED_LIBS: 'OFF'
|
|
338
|
+
}
|
|
339
|
+
// Default target same as name.
|
|
340
|
+
p.targets = [name];
|
|
341
|
+
writeJSONFileSync(pth, pkg);
|
|
342
|
+
initCMakeLists(cwd, pkg);
|
|
343
|
+
initGitignore(cwd);
|
|
344
|
+
initNpmignore(cwd);
|
|
345
|
+
initSourceFiles(cwd, pkg);
|
|
346
|
+
console.log('✓ Project initialized!\n');
|
|
40
347
|
}
|
|
348
|
+
//#endregion
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
|
|
41
352
|
|
|
353
|
+
//#region PARSE ARG
|
|
42
354
|
// Parse a single command-line argument.
|
|
43
355
|
function parseArg(opt, argv, k, i) {
|
|
44
356
|
if (k==='--help') opt.help = true;
|
|
45
|
-
else if (k==='--
|
|
46
|
-
|
|
47
|
-
else if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
357
|
+
else if (k==='--version') opt.version = true;
|
|
358
|
+
// Parse command name.
|
|
359
|
+
else if (!opt.command) switch (k.toLowerCase()) {
|
|
360
|
+
case 'i': opt.command = 'includes'; break;
|
|
361
|
+
case 'includes': opt.command = 'includes'; break;
|
|
362
|
+
case 'init': opt.command = 'init'; break;
|
|
363
|
+
default: opt.error = `Unknown command: ${k}`; break;
|
|
364
|
+
}
|
|
365
|
+
// Parse command options.
|
|
366
|
+
else switch (opt.command) {
|
|
367
|
+
// Parse options for `includes` command.
|
|
368
|
+
case 'includes':
|
|
369
|
+
if (k==='--compiler') opt.compiler = argv[++i];
|
|
370
|
+
else if (k==='--msvc') opt.compiler = 'msvc';
|
|
371
|
+
else if (k==='--gcc') opt.compiler = 'gcc';
|
|
372
|
+
else if (k==='--clang') opt.compiler = 'clang';
|
|
373
|
+
else opt.error = `Unknown option: ${k}`;
|
|
374
|
+
break;
|
|
375
|
+
// Parse options for `init` command.
|
|
376
|
+
case 'init':
|
|
377
|
+
break;
|
|
378
|
+
}
|
|
51
379
|
return i;
|
|
52
380
|
}
|
|
53
381
|
|
|
@@ -56,15 +384,20 @@ function parseArgs(argv) {
|
|
|
56
384
|
const opt = {
|
|
57
385
|
error: null,
|
|
58
386
|
help: false,
|
|
59
|
-
|
|
387
|
+
version: false,
|
|
388
|
+
command: '',
|
|
60
389
|
compiler: 'gcc'
|
|
61
390
|
};
|
|
62
391
|
for (let i=2; i<argv.length; i++)
|
|
63
392
|
i = parseArg(opt, argv, argv[i], i);
|
|
64
393
|
return opt;
|
|
65
394
|
}
|
|
395
|
+
//#endregion
|
|
396
|
+
|
|
66
397
|
|
|
67
398
|
|
|
399
|
+
|
|
400
|
+
//#region MAIN
|
|
68
401
|
// Main entry point.
|
|
69
402
|
function main(argv) {
|
|
70
403
|
const opt = parseArgs(argv);
|
|
@@ -77,13 +410,16 @@ function main(argv) {
|
|
|
77
410
|
runHelp();
|
|
78
411
|
process.exit(0);
|
|
79
412
|
}
|
|
413
|
+
if (opt.version) {
|
|
414
|
+
runVersion();
|
|
415
|
+
process.exit(0);
|
|
416
|
+
}
|
|
80
417
|
switch (opt.command) {
|
|
81
418
|
case 'includes': runIncludes(opt); break;
|
|
82
|
-
|
|
83
|
-
console.error(`Unknown command: ${opt.command}`);
|
|
84
|
-
process.exit(1);
|
|
419
|
+
case 'init': runInit(opt); break;
|
|
85
420
|
}
|
|
86
421
|
}
|
|
87
422
|
|
|
88
423
|
// Run the main entry point.
|
|
89
424
|
main(process.argv);
|
|
425
|
+
//#endregion
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cpoach.sh",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "A C/C++ package manager using the npm registry.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"c",
|
|
7
7
|
"c++",
|
|
8
8
|
"cpoach",
|
|
9
|
+
"package",
|
|
10
|
+
"manager",
|
|
9
11
|
"includes",
|
|
10
12
|
"support",
|
|
11
13
|
"tool",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
name: On Push
|
|
2
|
-
on:
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- main
|
|
6
|
-
- master
|
|
7
|
-
tags:
|
|
8
|
-
- '!*' # Do not execute on tags
|
|
9
|
-
env:
|
|
10
|
-
NAME: ${{vars.NAME}}
|
|
11
|
-
EMAIL: ${{vars.EMAIL}}
|
|
12
|
-
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
|
|
13
|
-
GITHUB_TOKEN: ${{secrets.GH_TOKEN}}
|
|
14
|
-
FORCE_COLOR: 1
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
jobs:
|
|
18
|
-
publish:
|
|
19
|
-
name: Publish packages
|
|
20
|
-
runs-on: ubuntu-latest
|
|
21
|
-
steps:
|
|
22
|
-
- uses: actions/checkout@v6
|
|
23
|
-
- uses: actions/setup-node@v6
|
|
24
|
-
with:
|
|
25
|
-
node-version: 24.x
|
|
26
|
-
- uses: nodef/npm-config.action@v1.2.0
|
|
27
|
-
with:
|
|
28
|
-
credentials: auto
|
|
29
|
-
entries: access=public
|
|
30
|
-
env:
|
|
31
|
-
GITHUB_TOKEN: ${{env.GITHUB_TOKEN}}
|
|
32
|
-
NPM_TOKEN: ${{env.NPM_TOKEN}}
|
|
33
|
-
- run: npm publish
|
|
34
|
-
env:
|
|
35
|
-
NODE_AUTH_TOKEN: ${{env.NPM_TOKEN}}
|