diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7f059eef0e..abe63e48f6 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,7 +15,13 @@ jobs: npm install npm run all test: # make sure the action works on a clean machine without building - runs-on: ubuntu-latest + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + - windows-latest + runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - uses: ./ diff --git a/README.md b/README.md index 8adee79bc6..f8943775ac 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,8 @@ We use JavaScript-based action. We don't use Docker-based action because: 1. docker pulling is slow currently 2. it's easier to use caching from [@actions/cache](https://github.com/actions/toolkit/tree/master/packages/cache) +We support different platforms, such as `ubuntu`, `macos` and `windows` with `x32` and `x64` archs. + Inside our action we perform 3 steps: 1. Setup environment running in parallel: @@ -95,7 +97,7 @@ Inside our action we perform 3 steps: ### Caching internals 1. We save and restore the following directories: `~/.cache/golangci-lint`, `~/.cache/go-build`, `~/go/pkg`. -2. The primary caching key looks like `golangci-lint.cache-{interval_number}-{go.mod_hash}`. Interval number ensures that we periodically invalidate +2. The primary caching key looks like `golangci-lint.cache-{platform-arch}-{interval_number}-{go.mod_hash}`. Interval number ensures that we periodically invalidate our cache (every 7 days). `go.mod` hash ensures that we invalidate the cache early - as soon as dependencies have changed. 3. We use [restore keys](https://help.github.com/en/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows#matching-a-cache-key): `golangci-lint.cache-{interval_number}-`, `golangci-lint.cache-`. GitHub matches keys by prefix if we have no exact match for the primary cache. diff --git a/dist/post_run/index.js b/dist/post_run/index.js index 743fb1139a..fabf608e33 100644 --- a/dist/post_run/index.js +++ b/dist/post_run/index.js @@ -41407,18 +41407,51 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.installGo = exports.installLint = void 0; const core = __importStar(__webpack_require__(470)); const tc = __importStar(__webpack_require__(533)); +const os_1 = __importDefault(__webpack_require__(87)); const path_1 = __importDefault(__webpack_require__(622)); const main_1 = __webpack_require__(514); +const downloadURL = "https://github.com/golangci/golangci-lint/releases/download"; +const getAssetURL = (versionConfig) => { + let ext = "tar.gz"; + let platform = os_1.default.platform().toString(); + switch (platform) { + case "win32": + platform = "windows"; + ext = "zip"; + break; + } + let arch = os_1.default.arch(); + switch (arch) { + case "x64": + arch = "amd64"; + break; + case "x32": + case "ia32": + arch = "386"; + break; + } + const noPrefix = versionConfig.TargetVersion.slice(1); + return `${downloadURL}/${versionConfig.TargetVersion}/golangci-lint-${noPrefix}-${platform}-${arch}.${ext}`; +}; // The installLint returns path to installed binary of golangci-lint. function installLint(versionConfig) { return __awaiter(this, void 0, void 0, function* () { core.info(`Installing golangci-lint ${versionConfig.TargetVersion}...`); const startedAt = Date.now(); - core.info(`Downloading ${versionConfig.AssetURL} ...`); - const tarGzPath = yield tc.downloadTool(versionConfig.AssetURL); - const extractedDir = yield tc.extractTar(tarGzPath, process.env.HOME); - const urlParts = versionConfig.AssetURL.split(`/`); - const dirName = urlParts[urlParts.length - 1].replace(/\.tar\.gz$/, ``); + const assetURL = getAssetURL(versionConfig); + core.info(`Downloading ${assetURL} ...`); + const archivePath = yield tc.downloadTool(assetURL); + let extractedDir = ""; + let repl = /\.tar\.gz$/; + if (assetURL.endsWith("zip")) { + extractedDir = yield tc.extractZip(archivePath, process.env.HOME); + repl = /\.zip$/; + } + else { + extractedDir = yield tc.extractTar(archivePath, process.env.HOME); + } + const urlParts = assetURL.split(`/`); + const dirName = urlParts[urlParts.length - 1].replace(repl, ``); const lintPath = path_1.default.join(extractedDir, dirName, `golangci-lint`); core.info(`Installed golangci-lint into ${lintPath} in ${Date.now() - startedAt}ms`); return lintPath; @@ -42651,12 +42684,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.restoreCache = void 0; const cache = __importStar(__webpack_require__(638)); const core = __importStar(__webpack_require__(470)); const crypto = __importStar(__webpack_require__(417)); const fs = __importStar(__webpack_require__(747)); +const path_1 = __importDefault(__webpack_require__(622)); const constants_1 = __webpack_require__(694); const utils = __importStar(__webpack_require__(443)); function checksumFile(hashName, path) { @@ -42669,10 +42706,12 @@ function checksumFile(hashName, path) { }); } const pathExists = (path) => __awaiter(void 0, void 0, void 0, function* () { return !!(yield fs.promises.stat(path).catch(() => false)); }); -const getLintCacheDir = () => `${process.env.HOME}/.cache/golangci-lint`; +const getLintCacheDir = () => { + return path_1.default.resolve(`${process.env.HOME}/.cache/golangci-lint`); +}; const getCacheDirs = () => { // Not existing dirs are ok here: it works. - return [getLintCacheDir(), `${process.env.HOME}/.cache/go-build`, `${process.env.HOME}/go/pkg`]; + return [getLintCacheDir(), path_1.default.resolve(`${process.env.HOME}/.cache/go-build`), path_1.default.resolve(`${process.env.HOME}/go/pkg`)]; }; const getIntervalKey = (invalidationIntervalDays) => { const now = new Date(); diff --git a/dist/run/index.js b/dist/run/index.js index 68c3b3bee9..c22bdcdff5 100644 --- a/dist/run/index.js +++ b/dist/run/index.js @@ -41417,18 +41417,51 @@ Object.defineProperty(exports, "__esModule", { value: true }); exports.installGo = exports.installLint = void 0; const core = __importStar(__webpack_require__(470)); const tc = __importStar(__webpack_require__(533)); +const os_1 = __importDefault(__webpack_require__(87)); const path_1 = __importDefault(__webpack_require__(622)); const main_1 = __webpack_require__(514); +const downloadURL = "https://github.com/golangci/golangci-lint/releases/download"; +const getAssetURL = (versionConfig) => { + let ext = "tar.gz"; + let platform = os_1.default.platform().toString(); + switch (platform) { + case "win32": + platform = "windows"; + ext = "zip"; + break; + } + let arch = os_1.default.arch(); + switch (arch) { + case "x64": + arch = "amd64"; + break; + case "x32": + case "ia32": + arch = "386"; + break; + } + const noPrefix = versionConfig.TargetVersion.slice(1); + return `${downloadURL}/${versionConfig.TargetVersion}/golangci-lint-${noPrefix}-${platform}-${arch}.${ext}`; +}; // The installLint returns path to installed binary of golangci-lint. function installLint(versionConfig) { return __awaiter(this, void 0, void 0, function* () { core.info(`Installing golangci-lint ${versionConfig.TargetVersion}...`); const startedAt = Date.now(); - core.info(`Downloading ${versionConfig.AssetURL} ...`); - const tarGzPath = yield tc.downloadTool(versionConfig.AssetURL); - const extractedDir = yield tc.extractTar(tarGzPath, process.env.HOME); - const urlParts = versionConfig.AssetURL.split(`/`); - const dirName = urlParts[urlParts.length - 1].replace(/\.tar\.gz$/, ``); + const assetURL = getAssetURL(versionConfig); + core.info(`Downloading ${assetURL} ...`); + const archivePath = yield tc.downloadTool(assetURL); + let extractedDir = ""; + let repl = /\.tar\.gz$/; + if (assetURL.endsWith("zip")) { + extractedDir = yield tc.extractZip(archivePath, process.env.HOME); + repl = /\.zip$/; + } + else { + extractedDir = yield tc.extractTar(archivePath, process.env.HOME); + } + const urlParts = assetURL.split(`/`); + const dirName = urlParts[urlParts.length - 1].replace(repl, ``); const lintPath = path_1.default.join(extractedDir, dirName, `golangci-lint`); core.info(`Installed golangci-lint into ${lintPath} in ${Date.now() - startedAt}ms`); return lintPath; @@ -42661,12 +42694,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.restoreCache = void 0; const cache = __importStar(__webpack_require__(638)); const core = __importStar(__webpack_require__(470)); const crypto = __importStar(__webpack_require__(417)); const fs = __importStar(__webpack_require__(747)); +const path_1 = __importDefault(__webpack_require__(622)); const constants_1 = __webpack_require__(694); const utils = __importStar(__webpack_require__(443)); function checksumFile(hashName, path) { @@ -42679,10 +42716,12 @@ function checksumFile(hashName, path) { }); } const pathExists = (path) => __awaiter(void 0, void 0, void 0, function* () { return !!(yield fs.promises.stat(path).catch(() => false)); }); -const getLintCacheDir = () => `${process.env.HOME}/.cache/golangci-lint`; +const getLintCacheDir = () => { + return path_1.default.resolve(`${process.env.HOME}/.cache/golangci-lint`); +}; const getCacheDirs = () => { // Not existing dirs are ok here: it works. - return [getLintCacheDir(), `${process.env.HOME}/.cache/go-build`, `${process.env.HOME}/go/pkg`]; + return [getLintCacheDir(), path_1.default.resolve(`${process.env.HOME}/.cache/go-build`), path_1.default.resolve(`${process.env.HOME}/go/pkg`)]; }; const getIntervalKey = (invalidationIntervalDays) => { const now = new Date(); diff --git a/src/cache.ts b/src/cache.ts index 64bfc15e90..6cebe879fc 100644 --- a/src/cache.ts +++ b/src/cache.ts @@ -2,6 +2,7 @@ import * as cache from "@actions/cache" import * as core from "@actions/core" import * as crypto from "crypto" import * as fs from "fs" +import path from "path" import { Events, State } from "./constants" import * as utils from "./utils/actionUtils" @@ -18,11 +19,13 @@ function checksumFile(hashName: string, path: string): Promise { const pathExists = async (path: string): Promise => !!(await fs.promises.stat(path).catch(() => false)) -const getLintCacheDir = (): string => `${process.env.HOME}/.cache/golangci-lint` +const getLintCacheDir = (): string => { + return path.resolve(`${process.env.HOME}/.cache/golangci-lint`) +} const getCacheDirs = (): string[] => { // Not existing dirs are ok here: it works. - return [getLintCacheDir(), `${process.env.HOME}/.cache/go-build`, `${process.env.HOME}/go/pkg`] + return [getLintCacheDir(), path.resolve(`${process.env.HOME}/.cache/go-build`), path.resolve(`${process.env.HOME}/go/pkg`)] } const getIntervalKey = (invalidationIntervalDays: number): string => { diff --git a/src/install.ts b/src/install.ts index 99f46dd6d8..0d6e5174c8 100644 --- a/src/install.ts +++ b/src/install.ts @@ -1,21 +1,55 @@ import * as core from "@actions/core" import * as tc from "@actions/tool-cache" +import os from "os" import path from "path" import { run as setupGo } from "setup-go/lib/main" import { VersionConfig } from "./version" +const downloadURL = "https://github.com/golangci/golangci-lint/releases/download" + +const getAssetURL = (versionConfig: VersionConfig): string => { + let ext = "tar.gz" + let platform = os.platform().toString() + switch (platform) { + case "win32": + platform = "windows" + ext = "zip" + break + } + let arch = os.arch() + switch (arch) { + case "x64": + arch = "amd64" + break + case "x32": + case "ia32": + arch = "386" + break + } + const noPrefix = versionConfig.TargetVersion.slice(1) + + return `${downloadURL}/${versionConfig.TargetVersion}/golangci-lint-${noPrefix}-${platform}-${arch}.${ext}` +} + // The installLint returns path to installed binary of golangci-lint. export async function installLint(versionConfig: VersionConfig): Promise { core.info(`Installing golangci-lint ${versionConfig.TargetVersion}...`) const startedAt = Date.now() + const assetURL = getAssetURL(versionConfig) + core.info(`Downloading ${assetURL} ...`) + const archivePath = await tc.downloadTool(assetURL) + let extractedDir = "" + let repl = /\.tar\.gz$/ + if (assetURL.endsWith("zip")) { + extractedDir = await tc.extractZip(archivePath, process.env.HOME) + repl = /\.zip$/ + } else { + extractedDir = await tc.extractTar(archivePath, process.env.HOME) + } - core.info(`Downloading ${versionConfig.AssetURL} ...`) - const tarGzPath = await tc.downloadTool(versionConfig.AssetURL) - const extractedDir = await tc.extractTar(tarGzPath, process.env.HOME) - - const urlParts = versionConfig.AssetURL.split(`/`) - const dirName = urlParts[urlParts.length - 1].replace(/\.tar\.gz$/, ``) + const urlParts = assetURL.split(`/`) + const dirName = urlParts[urlParts.length - 1].replace(repl, ``) const lintPath = path.join(extractedDir, dirName, `golangci-lint`) core.info(`Installed golangci-lint into ${lintPath} in ${Date.now() - startedAt}ms`) return lintPath