Merge pull request #2 from arduino/massi/arduino-cli
Add arduino cli setup action
This commit is contained in:
+4
@@ -23,6 +23,10 @@ jobs:
|
||||
working-directory: ./setup-taskfile
|
||||
run: npm install
|
||||
|
||||
- name: npm lint
|
||||
working-directory: ./setup-taskfile
|
||||
run: npm run format-check
|
||||
|
||||
- name: npm test
|
||||
working-directory: ./setup-taskfile
|
||||
run: npm test
|
||||
+44
-47
@@ -1,55 +1,53 @@
|
||||
import io = require('@actions/io');
|
||||
import path = require('path');
|
||||
import os = require('os');
|
||||
import fs = require('fs');
|
||||
import nock = require('nock');
|
||||
import io = require("@actions/io");
|
||||
import path = require("path");
|
||||
import os = require("os");
|
||||
import fs = require("fs");
|
||||
import nock = require("nock");
|
||||
|
||||
const toolDir = path.join(__dirname, 'runner', 'tools');
|
||||
const tempDir = path.join(__dirname, 'runner', 'temp');
|
||||
const dataDir = path.join(__dirname, 'testdata');
|
||||
const IS_WINDOWS = process.platform === 'win32';
|
||||
const toolDir = path.join(__dirname, "runner", "tools");
|
||||
const tempDir = path.join(__dirname, "runner", "temp");
|
||||
const dataDir = path.join(__dirname, "testdata");
|
||||
const IS_WINDOWS = process.platform === "win32";
|
||||
|
||||
process.env['RUNNER_TEMP'] = tempDir;
|
||||
process.env['RUNNER_TOOL_CACHE'] = toolDir;
|
||||
import * as installer from '../src/installer';
|
||||
process.env["RUNNER_TEMP"] = tempDir;
|
||||
process.env["RUNNER_TOOL_CACHE"] = toolDir;
|
||||
import * as installer from "../src/installer";
|
||||
|
||||
|
||||
describe('installer tests', () => {
|
||||
|
||||
beforeEach(async function () {
|
||||
await io.rmRF(toolDir)
|
||||
await io.rmRF(tempDir)
|
||||
await io.mkdirP(toolDir)
|
||||
await io.mkdirP(tempDir)
|
||||
})
|
||||
describe("installer tests", () => {
|
||||
beforeEach(async function() {
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
await io.mkdirP(toolDir);
|
||||
await io.mkdirP(tempDir);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await io.rmRF(toolDir);
|
||||
await io.rmRF(tempDir);
|
||||
} catch {
|
||||
console.log('Failed to remove test directories');
|
||||
console.log("Failed to remove test directories");
|
||||
}
|
||||
});
|
||||
|
||||
it('Downloads version of Task if no matching version is installed', async () => {
|
||||
await installer.getTask('2.6.0');
|
||||
const taskDir = path.join(toolDir, 'task', '2.6.0', os.arch());
|
||||
it("Downloads version of Task if no matching version is installed", async () => {
|
||||
await installer.getTask("2.6.0");
|
||||
const taskDir = path.join(toolDir, "task", "2.6.0", os.arch());
|
||||
|
||||
expect(fs.existsSync(`${taskDir}.complete`)).toBe(true);
|
||||
|
||||
if (IS_WINDOWS) {
|
||||
expect(fs.existsSync(path.join(taskDir, 'bin', 'task.exe'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskDir, "bin", "task.exe"))).toBe(true);
|
||||
} else {
|
||||
expect(fs.existsSync(path.join(taskDir, 'bin', 'task'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskDir, "bin", "task"))).toBe(true);
|
||||
}
|
||||
}, 100000);
|
||||
|
||||
describe('Gets the latest release of Task', () => {
|
||||
describe("Gets the latest release of Task", () => {
|
||||
beforeEach(() => {
|
||||
nock('https://api.github.com')
|
||||
.get('/repos/go-task/task/git/refs/tags')
|
||||
.replyWithFile(200, path.join(dataDir, 'tags.json'));
|
||||
nock("https://api.github.com")
|
||||
.get("/repos/go-task/task/git/refs/tags")
|
||||
.replyWithFile(200, path.join(dataDir, "tags.json"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -57,41 +55,40 @@ describe('installer tests', () => {
|
||||
nock.enableNetConnect();
|
||||
});
|
||||
|
||||
it('Gets the latest version of Task 2.5 using 2.5 and no matching version is installed', async () => {
|
||||
await installer.getTask('2.5');
|
||||
const taskDir = path.join(toolDir, 'task', '2.5.2', os.arch());
|
||||
it("Gets the latest version of Task 2.5 using 2.5 and no matching version is installed", async () => {
|
||||
await installer.getTask("2.5");
|
||||
const taskDir = path.join(toolDir, "task", "2.5.2", os.arch());
|
||||
|
||||
expect(fs.existsSync(`${taskDir}.complete`)).toBe(true);
|
||||
if (IS_WINDOWS) {
|
||||
expect(fs.existsSync(path.join(taskDir, 'bin', 'task.exe'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskDir, "bin", "task.exe"))).toBe(true);
|
||||
} else {
|
||||
expect(fs.existsSync(path.join(taskDir, 'bin', 'task'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskDir, "bin", "task"))).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Gets latest version of Task using 2.x and no matching version is installed', async () => {
|
||||
await installer.getTask('2.x');
|
||||
const taskdir = path.join(toolDir, 'task', '2.6.0', os.arch());
|
||||
it("Gets latest version of Task using 2.x and no matching version is installed", async () => {
|
||||
await installer.getTask("2.x");
|
||||
const taskdir = path.join(toolDir, "task", "2.6.0", os.arch());
|
||||
|
||||
expect(fs.existsSync(`${taskdir}.complete`)).toBe(true);
|
||||
if (IS_WINDOWS) {
|
||||
expect(fs.existsSync(path.join(taskdir, 'bin', 'task.exe'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskdir, "bin", "task.exe"))).toBe(true);
|
||||
} else {
|
||||
expect(fs.existsSync(path.join(taskdir, 'bin', 'task'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskdir, "bin", "task"))).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('Gets preview version of Task using 3.x and no matching version is installed', async () => {
|
||||
await installer.getTask('3.x');
|
||||
const taskdir = path.join(toolDir, 'task', '3.0.0-preview1', os.arch());
|
||||
it("Gets preview version of Task using 3.x and no matching version is installed", async () => {
|
||||
await installer.getTask("3.x");
|
||||
const taskdir = path.join(toolDir, "task", "3.0.0-preview1", os.arch());
|
||||
|
||||
expect(fs.existsSync(`${taskdir}.complete`)).toBe(true);
|
||||
if (IS_WINDOWS) {
|
||||
expect(fs.existsSync(path.join(taskdir, 'bin', 'task.exe'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskdir, "bin", "task.exe"))).toBe(true);
|
||||
} else {
|
||||
expect(fs.existsSync(path.join(taskdir, 'bin', 'task'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(taskdir, "bin", "task"))).toBe(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+1
-1
@@ -39,4 +39,4 @@
|
||||
"ts-jest": "^24.0.2",
|
||||
"typescript": "^3.5.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+129
-134
@@ -1,189 +1,184 @@
|
||||
// Load tempDirectory before it gets wiped by tool-cache
|
||||
let tempDirectory = process.env['RUNNER_TEMP'] || '';
|
||||
let tempDirectory = process.env["RUNNER_TEMP"] || "";
|
||||
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as restm from 'typed-rest-client/RestClient';
|
||||
import * as semver from 'semver';
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as util from "util";
|
||||
import * as restm from "typed-rest-client/RestClient";
|
||||
import * as semver from "semver";
|
||||
|
||||
if (!tempDirectory) {
|
||||
let baseLocation;
|
||||
if (process.platform === 'win32') {
|
||||
// On windows use the USERPROFILE env variable
|
||||
baseLocation = process.env['USERPROFILE'] || 'C:\\';
|
||||
let baseLocation;
|
||||
if (process.platform === "win32") {
|
||||
// On windows use the USERPROFILE env variable
|
||||
baseLocation = process.env["USERPROFILE"] || "C:\\";
|
||||
} else {
|
||||
if (process.platform === "darwin") {
|
||||
baseLocation = "/Users";
|
||||
} else {
|
||||
if (process.platform === 'darwin') {
|
||||
baseLocation = '/Users';
|
||||
} else {
|
||||
baseLocation = '/home';
|
||||
}
|
||||
baseLocation = "/home";
|
||||
}
|
||||
tempDirectory = path.join(baseLocation, 'actions', 'temp');
|
||||
}
|
||||
tempDirectory = path.join(baseLocation, "actions", "temp");
|
||||
}
|
||||
|
||||
import * as core from '@actions/core';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import io = require('@actions/io');
|
||||
import * as core from "@actions/core";
|
||||
import * as tc from "@actions/tool-cache";
|
||||
import io = require("@actions/io");
|
||||
|
||||
let osPlat: string = os.platform();
|
||||
let osArch: string = os.arch();
|
||||
|
||||
interface ITaskRef {
|
||||
ref: string;
|
||||
ref: string;
|
||||
}
|
||||
|
||||
export async function getTask(version: string) {
|
||||
// resolve the version number
|
||||
const targetVersion = await computeVersion(version)
|
||||
if (targetVersion) {
|
||||
version = targetVersion;
|
||||
}
|
||||
// resolve the version number
|
||||
const targetVersion = await computeVersion(version);
|
||||
if (targetVersion) {
|
||||
version = targetVersion;
|
||||
}
|
||||
|
||||
// look if the binary is cached
|
||||
let toolPath: string;
|
||||
toolPath = tc.find('task', version);
|
||||
// look if the binary is cached
|
||||
let toolPath: string;
|
||||
toolPath = tc.find("task", version);
|
||||
|
||||
// if not: download, extract and cache
|
||||
if (!toolPath) {
|
||||
toolPath = await downloadRelease(version);
|
||||
core.debug('Task cached under ' + toolPath);
|
||||
}
|
||||
// if not: download, extract and cache
|
||||
if (!toolPath) {
|
||||
toolPath = await downloadRelease(version);
|
||||
core.debug("Task cached under " + toolPath);
|
||||
}
|
||||
|
||||
toolPath = path.join(toolPath, 'bin');
|
||||
core.addPath(toolPath);
|
||||
toolPath = path.join(toolPath, "bin");
|
||||
core.addPath(toolPath);
|
||||
}
|
||||
|
||||
async function downloadRelease(version: string): Promise<string> {
|
||||
// Download
|
||||
let fileName: string = getFileName();
|
||||
let downloadUrl: string = util.format(
|
||||
'https://github.com/go-task/task/releases/download/%s/%s',
|
||||
version,
|
||||
fileName
|
||||
);
|
||||
let downloadPath: string | null = null;
|
||||
try {
|
||||
downloadPath = await tc.downloadTool(downloadUrl);
|
||||
} catch (error) {
|
||||
core.debug(error);
|
||||
throw `Failed to download version ${version}: ${error}`;
|
||||
}
|
||||
// Download
|
||||
let fileName: string = getFileName();
|
||||
let downloadUrl: string = util.format(
|
||||
"https://github.com/go-task/task/releases/download/%s/%s",
|
||||
version,
|
||||
fileName
|
||||
);
|
||||
let downloadPath: string | null = null;
|
||||
try {
|
||||
downloadPath = await tc.downloadTool(downloadUrl);
|
||||
} catch (error) {
|
||||
core.debug(error);
|
||||
throw `Failed to download version ${version}: ${error}`;
|
||||
}
|
||||
|
||||
// Extract
|
||||
let extPath: string | null = null;
|
||||
if (osPlat == 'win32') {
|
||||
extPath = await tc.extractZip(downloadPath);
|
||||
// Create a bin/ folder and move `task` there
|
||||
await io.mkdirP(path.join(extPath, 'bin'))
|
||||
await io.mv(path.join(extPath, 'task.exe'), path.join(extPath, 'bin'))
|
||||
} else {
|
||||
extPath = await tc.extractTar(downloadPath);
|
||||
// Create a bin/ folder and move `task` there
|
||||
await io.mkdirP(path.join(extPath, 'bin'))
|
||||
await io.mv(path.join(extPath, 'task'), path.join(extPath, 'bin'))
|
||||
}
|
||||
// Extract
|
||||
let extPath: string | null = null;
|
||||
if (osPlat == "win32") {
|
||||
extPath = await tc.extractZip(downloadPath);
|
||||
// Create a bin/ folder and move `task` there
|
||||
await io.mkdirP(path.join(extPath, "bin"));
|
||||
await io.mv(path.join(extPath, "task.exe"), path.join(extPath, "bin"));
|
||||
} else {
|
||||
extPath = await tc.extractTar(downloadPath);
|
||||
// Create a bin/ folder and move `task` there
|
||||
await io.mkdirP(path.join(extPath, "bin"));
|
||||
await io.mv(path.join(extPath, "task"), path.join(extPath, "bin"));
|
||||
}
|
||||
|
||||
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||
return await tc.cacheDir(extPath, 'task', version);
|
||||
// Install into the local tool cache - node extracts with a root folder that matches the fileName downloaded
|
||||
return await tc.cacheDir(extPath, "task", version);
|
||||
}
|
||||
|
||||
function getFileName() {
|
||||
const platform: string = osPlat == 'win32' ? 'windows' : osPlat;
|
||||
const arch: string = osArch == 'x64' ? 'amd64' : '386';
|
||||
const ext: string = osPlat == 'win32' ? 'zip' : 'tar.gz';
|
||||
const filename: string = util.format(
|
||||
'task_%s_%s.%s',
|
||||
platform,
|
||||
arch,
|
||||
ext
|
||||
);
|
||||
const platform: string = osPlat == "win32" ? "windows" : osPlat;
|
||||
const arch: string = osArch == "x64" ? "amd64" : "386";
|
||||
const ext: string = osPlat == "win32" ? "zip" : "tar.gz";
|
||||
const filename: string = util.format("task_%s_%s.%s", platform, arch, ext);
|
||||
|
||||
return filename;
|
||||
return filename;
|
||||
}
|
||||
|
||||
// Retrieve a list of versions scraping tags from the Github API
|
||||
async function fetchVersions(): Promise<string[]> {
|
||||
let rest: restm.RestClient = new restm.RestClient('setup-taskfile');
|
||||
let tags: ITaskRef[] =
|
||||
(await rest.get<ITaskRef[]>(
|
||||
'https://api.github.com/repos/go-task/task/git/refs/tags'
|
||||
)).result || [];
|
||||
let rest: restm.RestClient = new restm.RestClient("setup-taskfile");
|
||||
let tags: ITaskRef[] =
|
||||
(await rest.get<ITaskRef[]>(
|
||||
"https://api.github.com/repos/go-task/task/git/refs/tags"
|
||||
)).result || [];
|
||||
|
||||
return tags
|
||||
.filter(tag => tag.ref.match(/v\d+\.[\w\.]+/g))
|
||||
.map(tag => tag.ref.replace('refs/tags/v', ''));
|
||||
return tags
|
||||
.filter(tag => tag.ref.match(/v\d+\.[\w\.]+/g))
|
||||
.map(tag => tag.ref.replace("refs/tags/v", ""));
|
||||
}
|
||||
|
||||
// Compute an actual version starting from the `version` configuration param.
|
||||
async function computeVersion(version: string): Promise<string> {
|
||||
// strip leading `v` char (will be re-added later)
|
||||
if (version.startsWith('v')) {
|
||||
version = version.slice(1, version.length);
|
||||
}
|
||||
// strip leading `v` char (will be re-added later)
|
||||
if (version.startsWith("v")) {
|
||||
version = version.slice(1, version.length);
|
||||
}
|
||||
|
||||
// strip trailing .x chars
|
||||
if (version.endsWith('.x')) {
|
||||
version = version.slice(0, version.length - 2);
|
||||
}
|
||||
// strip trailing .x chars
|
||||
if (version.endsWith(".x")) {
|
||||
version = version.slice(0, version.length - 2);
|
||||
}
|
||||
|
||||
const allVersions = await fetchVersions();
|
||||
const possibleVersions = allVersions.filter(v => v.startsWith(version));
|
||||
const allVersions = await fetchVersions();
|
||||
const possibleVersions = allVersions.filter(v => v.startsWith(version));
|
||||
|
||||
const versionMap = new Map();
|
||||
possibleVersions.forEach(v => versionMap.set(normalizeVersion(v), v));
|
||||
const versionMap = new Map();
|
||||
possibleVersions.forEach(v => versionMap.set(normalizeVersion(v), v));
|
||||
|
||||
const versions = Array.from(versionMap.keys())
|
||||
.sort(semver.rcompare)
|
||||
.map(v => versionMap.get(v));
|
||||
const versions = Array.from(versionMap.keys())
|
||||
.sort(semver.rcompare)
|
||||
.map(v => versionMap.get(v));
|
||||
|
||||
core.debug(`evaluating ${versions.length} versions`);
|
||||
core.debug(`evaluating ${versions.length} versions`);
|
||||
|
||||
if (versions.length === 0) {
|
||||
throw new Error('unable to get latest version');
|
||||
}
|
||||
if (versions.length === 0) {
|
||||
throw new Error("unable to get latest version");
|
||||
}
|
||||
|
||||
core.debug(`matched: ${versions[0]}`);
|
||||
core.debug(`matched: ${versions[0]}`);
|
||||
|
||||
return 'v' + versions[0];
|
||||
return "v" + versions[0];
|
||||
}
|
||||
|
||||
// Make partial versions semver compliant.
|
||||
function normalizeVersion(version: string): string {
|
||||
const preStrings = ['beta', 'rc', 'preview']
|
||||
const preStrings = ["beta", "rc", "preview"];
|
||||
|
||||
const versionPart = version.split('.');
|
||||
if (versionPart[1] == null) {
|
||||
//append minor and patch version if not available
|
||||
// e.g. 2 -> 2.0.0
|
||||
return version.concat('.0.0');
|
||||
} else {
|
||||
// handle beta and rc
|
||||
// e.g. 1.10beta1 -? 1.10.0-beta1, 1.10rc1 -> 1.10.0-rc1
|
||||
if (preStrings.some(el => versionPart[1].includes(el))) {
|
||||
versionPart[1] = versionPart[1]
|
||||
.replace('beta', '.0-beta')
|
||||
.replace('rc', '.0-rc')
|
||||
.replace('preview', '.0-preview');
|
||||
return versionPart.join('.');
|
||||
}
|
||||
const versionPart = version.split(".");
|
||||
if (versionPart[1] == null) {
|
||||
//append minor and patch version if not available
|
||||
// e.g. 2 -> 2.0.0
|
||||
return version.concat(".0.0");
|
||||
} else {
|
||||
// handle beta and rc
|
||||
// e.g. 1.10beta1 -? 1.10.0-beta1, 1.10rc1 -> 1.10.0-rc1
|
||||
if (preStrings.some(el => versionPart[1].includes(el))) {
|
||||
versionPart[1] = versionPart[1]
|
||||
.replace("beta", ".0-beta")
|
||||
.replace("rc", ".0-rc")
|
||||
.replace("preview", ".0-preview");
|
||||
return versionPart.join(".");
|
||||
}
|
||||
}
|
||||
|
||||
if (versionPart[2] == null) {
|
||||
//append patch version if not available
|
||||
// e.g. 2.1 -> 2.1.0
|
||||
return version.concat('.0');
|
||||
} else {
|
||||
// handle beta and rc
|
||||
// e.g. 1.8.5beta1 -> 1.8.5-beta1, 1.8.5rc1 -> 1.8.5-rc1
|
||||
if (preStrings.some(el => versionPart[2].includes(el))) {
|
||||
versionPart[2] = versionPart[2]
|
||||
.replace('beta', '-beta')
|
||||
.replace('rc', '-rc')
|
||||
.replace('preview', '-preview');
|
||||
return versionPart.join('.');
|
||||
}
|
||||
if (versionPart[2] == null) {
|
||||
//append patch version if not available
|
||||
// e.g. 2.1 -> 2.1.0
|
||||
return version.concat(".0");
|
||||
} else {
|
||||
// handle beta and rc
|
||||
// e.g. 1.8.5beta1 -> 1.8.5-beta1, 1.8.5rc1 -> 1.8.5-rc1
|
||||
if (preStrings.some(el => versionPart[2].includes(el))) {
|
||||
versionPart[2] = versionPart[2]
|
||||
.replace("beta", "-beta")
|
||||
.replace("rc", "-rc")
|
||||
.replace("preview", "-preview");
|
||||
return versionPart.join(".");
|
||||
}
|
||||
}
|
||||
|
||||
return version;
|
||||
return version;
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,11 +1,11 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as installer from './installer';
|
||||
import * as core from "@actions/core";
|
||||
import * as installer from "./installer";
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
let version = core.getInput('version');
|
||||
let version = core.getInput("version");
|
||||
if (!version) {
|
||||
version = '2.x';
|
||||
version = "2.x";
|
||||
}
|
||||
|
||||
if (version) {
|
||||
|
||||
Reference in New Issue
Block a user