添加cache save缓存go build时的依赖包
All checks were successful
Continuous Integration / GitHub Actions Test (push) Successful in 15s
All checks were successful
Continuous Integration / GitHub Actions Test (push) Successful in 15s
修改打包命令
This commit is contained in:
parent
fb7131260b
commit
40cb2529b5
2
.github/linters/.eslintrc.yml
vendored
2
.github/linters/.eslintrc.yml
vendored
@ -36,6 +36,8 @@ extends:
|
||||
|
||||
rules:
|
||||
{
|
||||
'prefer-const': 'off',
|
||||
'no-shadow': 'off',
|
||||
'camelcase': 'off',
|
||||
'eslint-comments/no-use': 'off',
|
||||
'eslint-comments/no-unused-disable': 'off',
|
||||
|
@ -24,7 +24,11 @@ outputs:
|
||||
go-version:
|
||||
description:
|
||||
'The installed Go version. Useful when given a version range as input.'
|
||||
cache-hit:
|
||||
description: 'A boolean value to indicate if a cache was hit'
|
||||
|
||||
runs:
|
||||
using: node20
|
||||
main: dist/index.js
|
||||
post: 'dist/cache-save/index.js'
|
||||
post-if: success()
|
||||
|
BIN
dist/cache-save/index.js
generated
vendored
Normal file
BIN
dist/cache-save/index.js
generated
vendored
Normal file
Binary file not shown.
BIN
dist/index.js
generated
vendored
BIN
dist/index.js
generated
vendored
Binary file not shown.
BIN
dist/index.js.map
generated
vendored
BIN
dist/index.js.map
generated
vendored
Binary file not shown.
BIN
dist/licenses.txt
generated
vendored
BIN
dist/licenses.txt
generated
vendored
Binary file not shown.
BIN
dist/sourcemap-register.js
generated
vendored
BIN
dist/sourcemap-register.js
generated
vendored
Binary file not shown.
38
package-lock.json
generated
38
package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.2.4",
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/glob": "^0.4.0",
|
||||
"@actions/http-client": "^2.2.1",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^2.0.1"
|
||||
@ -63,6 +64,35 @@
|
||||
"uuid": "^3.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/@actions/glob": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.1.2.tgz",
|
||||
"integrity": "sha512-SclLR7Ia5sEqjkJTPs7Sd86maMDw43p769YxBOxvPvEWuPEhpAnBsQfENOpXjFYMmhCqd127bmf+YdvJqVqR4A==",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.6",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/cache/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
@ -98,11 +128,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/glob": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.1.2.tgz",
|
||||
"integrity": "sha512-SclLR7Ia5sEqjkJTPs7Sd86maMDw43p769YxBOxvPvEWuPEhpAnBsQfENOpXjFYMmhCqd127bmf+YdvJqVqR4A==",
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.4.0.tgz",
|
||||
"integrity": "sha512-+eKIGFhsFa4EBwaf/GMyzCdWrXWymGXfFmZU3FHQvYS8mPcHtTtZONbkcqqUMzw9mJ/pImEBFET1JNifhqGsAQ==",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/core": "^1.9.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
|
@ -30,7 +30,7 @@
|
||||
"format:write": "npx prettier --write .",
|
||||
"format:check": "npx prettier --check .",
|
||||
"lint": "npx eslint . -c ./.github/linters/.eslintrc.yml",
|
||||
"package": "npx ncc build src/index.ts -o dist --source-map --license licenses.txt",
|
||||
"package": "npx ncc build src/index.ts -o dist && npx ncc build -o dist/cache-save src/cache-save.ts",
|
||||
"package:watch": "npm run package -- --watch",
|
||||
"test": "npx jest",
|
||||
"all": "npm run format:write && npm run lint && npm run package",
|
||||
@ -69,6 +69,7 @@
|
||||
"dependencies": {
|
||||
"@actions/cache": "^3.2.4",
|
||||
"@actions/core": "^1.10.1",
|
||||
"@actions/glob": "^0.4.0",
|
||||
"@actions/http-client": "^2.2.1",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^2.0.1"
|
||||
|
65
src/cache-restore.ts
Normal file
65
src/cache-restore.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import * as cache from '@actions/cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as glob from '@actions/glob'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
import { State, Outputs } from './constants'
|
||||
import { PackageManagerInfo } from './package-managers'
|
||||
import { getCacheDirectoryPath, getPackageManagerInfo } from './cache-utils'
|
||||
|
||||
export const restoreCache = async (
|
||||
versionSpec: string,
|
||||
packageManager: string,
|
||||
cacheDependencyPath?: string
|
||||
): Promise<void> => {
|
||||
const packageManagerInfo = await getPackageManagerInfo(packageManager)
|
||||
const platform = process.env.RUNNER_OS
|
||||
|
||||
const cachePaths = await getCacheDirectoryPath(packageManagerInfo)
|
||||
|
||||
const dependencyFilePath = cacheDependencyPath
|
||||
? cacheDependencyPath
|
||||
: findDependencyFile(packageManagerInfo)
|
||||
const fileHash = await glob.hashFiles(dependencyFilePath)
|
||||
|
||||
if (!fileHash) {
|
||||
throw new Error(
|
||||
'Some specified paths were not resolved, unable to cache dependencies.'
|
||||
)
|
||||
}
|
||||
|
||||
const linuxVersion =
|
||||
process.env.RUNNER_OS === 'Linux' ? `${process.env.ImageOS}-` : ''
|
||||
const primaryKey = `setup-go-${platform}-${linuxVersion}go-${versionSpec}-${fileHash}`
|
||||
core.info(`primary key is ${primaryKey}`)
|
||||
|
||||
core.saveState(State.CachePrimaryKey, primaryKey)
|
||||
|
||||
const cacheKey = await cache.restoreCache(cachePaths, primaryKey)
|
||||
core.setOutput(Outputs.CacheHit, Boolean(cacheKey))
|
||||
|
||||
if (!cacheKey) {
|
||||
core.info(`Cache is not found`)
|
||||
core.setOutput(Outputs.CacheHit, false)
|
||||
return
|
||||
}
|
||||
|
||||
core.saveState(State.CacheMatchedKey, cacheKey)
|
||||
core.info(`Cache restored from key: ${cacheKey}`)
|
||||
}
|
||||
|
||||
const findDependencyFile = (packageManager: PackageManagerInfo): string => {
|
||||
const dependencyFile = packageManager.dependencyFilePattern
|
||||
const workspace = process.env.GITHUB_WORKSPACE!
|
||||
const rootContent = fs.readdirSync(workspace)
|
||||
|
||||
const goSumFileExists = rootContent.includes(dependencyFile)
|
||||
if (!goSumFileExists) {
|
||||
throw new Error(
|
||||
`Dependencies file is not found in ${workspace}. Supported file pattern: ${dependencyFile}`
|
||||
)
|
||||
}
|
||||
|
||||
return path.join(workspace, dependencyFile)
|
||||
}
|
93
src/cache-save.ts
Normal file
93
src/cache-save.ts
Normal file
@ -0,0 +1,93 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as cache from '@actions/cache'
|
||||
import fs from 'fs'
|
||||
import { State } from './constants'
|
||||
import { getCacheDirectoryPath, getPackageManagerInfo } from './cache-utils'
|
||||
|
||||
// Catch and log any unhandled exceptions. These exceptions can leak out of the uploadChunk method in
|
||||
// @actions/toolkit when a failed upload closes the file descriptor causing any in-process reads to
|
||||
// throw an uncaught exception. Instead of failing this action, just warn.
|
||||
process.on('uncaughtException', e => {
|
||||
const warningPrefix = '[warning]'
|
||||
core.info(`${warningPrefix}${e.message}`)
|
||||
})
|
||||
|
||||
// Added early exit to resolve issue with slow post action step:
|
||||
// - https://github.com/actions/setup-node/issues/878
|
||||
// https://github.com/actions/cache/pull/1217
|
||||
export async function run(earlyExit?: boolean): Promise<void> {
|
||||
try {
|
||||
const cacheInput = core.getBooleanInput('cache')
|
||||
if (cacheInput) {
|
||||
await cachePackages()
|
||||
|
||||
if (earlyExit) {
|
||||
process.exit(0)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
let message = 'Unknown error!'
|
||||
if (error instanceof Error) {
|
||||
message = error.message
|
||||
}
|
||||
if (typeof error === 'string') {
|
||||
message = error
|
||||
}
|
||||
core.warning(message)
|
||||
}
|
||||
}
|
||||
|
||||
const cachePackages = async (): Promise<void> => {
|
||||
const packageManager = 'default'
|
||||
|
||||
const state = core.getState(State.CacheMatchedKey)
|
||||
const primaryKey = core.getState(State.CachePrimaryKey)
|
||||
|
||||
const packageManagerInfo = await getPackageManagerInfo(packageManager)
|
||||
|
||||
const cachePaths = await getCacheDirectoryPath(packageManagerInfo)
|
||||
|
||||
const nonExistingPaths = cachePaths.filter(
|
||||
cachePath => !fs.existsSync(cachePath)
|
||||
)
|
||||
|
||||
if (nonExistingPaths.length === cachePaths.length) {
|
||||
core.warning('There are no cache folders on the disk')
|
||||
return
|
||||
}
|
||||
|
||||
if (nonExistingPaths.length) {
|
||||
logWarning(
|
||||
`Cache folder path is retrieved but doesn't exist on disk: ${nonExistingPaths.join(
|
||||
', '
|
||||
)}`
|
||||
)
|
||||
}
|
||||
|
||||
if (!primaryKey) {
|
||||
core.info(
|
||||
'Primary key was not generated. Please check the log messages above for more errors or information'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (primaryKey === state) {
|
||||
core.info(
|
||||
`Cache hit occurred on the primary key ${primaryKey}, not saving cache.`
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
const cacheId = await cache.saveCache(cachePaths, primaryKey)
|
||||
if (cacheId === -1) {
|
||||
return
|
||||
}
|
||||
core.info(`Cache saved with the key: ${primaryKey}`)
|
||||
}
|
||||
|
||||
function logWarning(message: string): void {
|
||||
const warningPrefix = '[warning]'
|
||||
core.info(`${warningPrefix}${message}`)
|
||||
}
|
||||
|
||||
run(true)
|
92
src/cache-utils.ts
Normal file
92
src/cache-utils.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import * as cache from '@actions/cache'
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import {
|
||||
supportedPackageManagers,
|
||||
PackageManagerInfo
|
||||
} from './package-managers'
|
||||
|
||||
export const getCommandOutput = async (
|
||||
toolCommand: string
|
||||
): Promise<string> => {
|
||||
let { stdout, stderr, exitCode } = await exec.getExecOutput(
|
||||
toolCommand,
|
||||
undefined,
|
||||
{ ignoreReturnCode: true }
|
||||
)
|
||||
|
||||
if (exitCode) {
|
||||
stderr = !stderr.trim()
|
||||
? `The '${toolCommand}' command failed with exit code: ${exitCode}`
|
||||
: stderr
|
||||
throw new Error(stderr)
|
||||
}
|
||||
|
||||
return stdout.trim()
|
||||
}
|
||||
|
||||
export const getPackageManagerInfo = async (
|
||||
packageManager: string
|
||||
): Promise<PackageManagerInfo> => {
|
||||
if (!supportedPackageManagers[packageManager]) {
|
||||
throw new Error(
|
||||
`It's not possible to use ${packageManager}, please, check correctness of the package manager name spelling.`
|
||||
)
|
||||
}
|
||||
const obtainedPackageManager = supportedPackageManagers[packageManager]
|
||||
|
||||
return obtainedPackageManager
|
||||
}
|
||||
|
||||
export const getCacheDirectoryPath = async (
|
||||
packageManagerInfo: PackageManagerInfo
|
||||
): Promise<string[]> => {
|
||||
const pathOutputs = await Promise.allSettled(
|
||||
packageManagerInfo.cacheFolderCommandList.map(async command =>
|
||||
getCommandOutput(command)
|
||||
)
|
||||
)
|
||||
|
||||
const results = pathOutputs.map(item => {
|
||||
if (item.status === 'fulfilled') {
|
||||
return item.value
|
||||
} else {
|
||||
core.info(`[warning]getting cache directory path failed: ${item.reason}`)
|
||||
}
|
||||
|
||||
return ''
|
||||
})
|
||||
|
||||
const cachePaths = results.filter(item => item)
|
||||
|
||||
if (!cachePaths.length) {
|
||||
throw new Error(`Could not get cache folder paths.`)
|
||||
}
|
||||
|
||||
return cachePaths
|
||||
}
|
||||
|
||||
export function isGhes(): boolean {
|
||||
const ghUrl = new URL(
|
||||
process.env['GITHUB_SERVER_URL'] || 'https://github.com'
|
||||
)
|
||||
return ghUrl.hostname.toUpperCase() !== 'GITHUB.COM'
|
||||
}
|
||||
|
||||
export function isCacheFeatureAvailable(): boolean {
|
||||
if (cache.isFeatureAvailable()) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (isGhes()) {
|
||||
core.warning(
|
||||
'Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not.'
|
||||
)
|
||||
return false
|
||||
}
|
||||
|
||||
core.warning(
|
||||
'The runner was not able to contact the cache service. Caching will be skipped'
|
||||
)
|
||||
return false
|
||||
}
|
8
src/constants.ts
Normal file
8
src/constants.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export enum State {
|
||||
CachePrimaryKey = 'CACHE_KEY',
|
||||
CacheMatchedKey = 'CACHE_RESULT'
|
||||
}
|
||||
|
||||
export enum Outputs {
|
||||
CacheHit = 'cache-hit'
|
||||
}
|
27
src/main.ts
27
src/main.ts
@ -2,10 +2,10 @@ import * as core from '@actions/core'
|
||||
import * as io from '@actions/io'
|
||||
import * as cache from '@actions/cache'
|
||||
import os from 'os'
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import cp from 'child_process'
|
||||
import { getGoFileName, getGoRootPath, getInstalledGoPath } from './install'
|
||||
import { restoreCache } from './cache-restore'
|
||||
|
||||
/**
|
||||
* The main function for the action.
|
||||
@ -41,13 +41,21 @@ export async function run(): Promise<void> {
|
||||
|
||||
// 将go的bin目录添加到PATH
|
||||
const binPath = path.join(installedPath, 'bin')
|
||||
getFiles(binPath)
|
||||
core.addPath(binPath)
|
||||
// 测试输出go的版本
|
||||
const goPath = await io.which('go')
|
||||
const goVersion = (cp.execSync(`${goPath} version`) || '').toString()
|
||||
core.info(`go version cmd result is: ${goVersion}`)
|
||||
|
||||
// 尝试从缓存中恢复
|
||||
const packageManager = 'default'
|
||||
const cacheDependencyPath = core.getInput('cache-dependency-path')
|
||||
try {
|
||||
await restoreCache(version, packageManager, cacheDependencyPath)
|
||||
} catch (error) {
|
||||
core.warning(`Restore cache failed: ${(error as Error).message}`)
|
||||
}
|
||||
|
||||
// 设置输出参数
|
||||
core.setOutput('go-version', goVersion)
|
||||
} catch (error) {
|
||||
@ -56,21 +64,6 @@ export async function run(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
function getFiles(dir: string): void {
|
||||
const stat = fs.statSync(dir)
|
||||
if (stat.isDirectory()) {
|
||||
// 判断是不是目录
|
||||
const dirs = fs.readdirSync(dir)
|
||||
for (const value of dirs) {
|
||||
// 递归调用,处理子目录
|
||||
getFiles(path.join(dir, value))
|
||||
}
|
||||
} else if (stat.isFile()) {
|
||||
// 判断是不是文件
|
||||
core.info(`文件: ${dir}`)
|
||||
}
|
||||
}
|
||||
|
||||
function resolveVersionInput(): string {
|
||||
const version = core.getInput('go-version')
|
||||
|
||||
|
15
src/package-managers.ts
Normal file
15
src/package-managers.ts
Normal file
@ -0,0 +1,15 @@
|
||||
type SupportedPackageManagers = {
|
||||
[prop: string]: PackageManagerInfo
|
||||
}
|
||||
|
||||
export interface PackageManagerInfo {
|
||||
dependencyFilePattern: string
|
||||
cacheFolderCommandList: string[]
|
||||
}
|
||||
|
||||
export const supportedPackageManagers: SupportedPackageManagers = {
|
||||
default: {
|
||||
dependencyFilePattern: 'go.sum',
|
||||
cacheFolderCommandList: ['go env GOMODCACHE', 'go env GOCACHE']
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user