mirror of
https://github.com/DeterminateSystems/magic-nix-cache-action.git
synced 2024-12-23 13:32:03 +01:00
Merge pull request #41 from DeterminateSystems/detsys-ts
Rebase on detsys-ts and get rid of bun
This commit is contained in:
commit
a094b05eb7
13 changed files with 94402 additions and 7151 deletions
73
.eslintrc.json
Normal file
73
.eslintrc.json
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"extends": ["plugin:github/recommended"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 9,
|
||||||
|
"sourceType": "module",
|
||||||
|
"project": "./tsconfig.json"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"import/resolver": {
|
||||||
|
"typescript": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"i18n-text/no-en": "off",
|
||||||
|
"eslint-comments/no-use": "off",
|
||||||
|
"import/no-namespace": "off",
|
||||||
|
"no-unused-vars": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/explicit-member-accessibility": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"accessibility": "no-public"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-require-imports": "error",
|
||||||
|
"@typescript-eslint/array-type": "error",
|
||||||
|
"@typescript-eslint/await-thenable": "error",
|
||||||
|
"@typescript-eslint/ban-ts-comment": "error",
|
||||||
|
"camelcase": "off",
|
||||||
|
"@typescript-eslint/consistent-type-assertions": "error",
|
||||||
|
"@typescript-eslint/explicit-function-return-type": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowExpressions": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||||
|
"@typescript-eslint/no-array-constructor": "error",
|
||||||
|
"@typescript-eslint/no-empty-interface": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
"@typescript-eslint/no-floating-promises": "error",
|
||||||
|
"@typescript-eslint/no-extraneous-class": "error",
|
||||||
|
"@typescript-eslint/no-for-in-array": "error",
|
||||||
|
"@typescript-eslint/no-inferrable-types": "error",
|
||||||
|
"@typescript-eslint/no-misused-new": "error",
|
||||||
|
"@typescript-eslint/no-namespace": "error",
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||||
|
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||||
|
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||||
|
"@typescript-eslint/no-useless-constructor": "error",
|
||||||
|
"@typescript-eslint/no-var-requires": "error",
|
||||||
|
"@typescript-eslint/prefer-for-of": "warn",
|
||||||
|
"@typescript-eslint/prefer-function-type": "warn",
|
||||||
|
"@typescript-eslint/prefer-includes": "error",
|
||||||
|
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||||
|
"@typescript-eslint/promise-function-async": "error",
|
||||||
|
"@typescript-eslint/require-array-sort-compare": "error",
|
||||||
|
"@typescript-eslint/restrict-plus-operands": "error",
|
||||||
|
"@typescript-eslint/type-annotation-spacing": "error",
|
||||||
|
"@typescript-eslint/unbound-method": "error"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"node": true,
|
||||||
|
"es6": true
|
||||||
|
}
|
||||||
|
}
|
32
.github/workflows/ci.yml
vendored
32
.github/workflows/ci.yml
vendored
|
@ -13,27 +13,23 @@ jobs:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install Nix
|
- name: Install Nix
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@main
|
||||||
- name: Record existing bundle hash
|
- uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
run: |
|
|
||||||
echo "BUNDLE_HASH=$(sha256sum <dist/index.js | sed 's/ -//')" >>$GITHUB_ENV
|
|
||||||
- name: Check shell scripts
|
- name: Check shell scripts
|
||||||
run: |
|
run: |
|
||||||
nix develop --command shellcheck ./.github/workflows/cache-test.sh
|
nix develop --command shellcheck ./.github/workflows/cache-test.sh
|
||||||
- name: Build action
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
run: |
|
- name: Install pnpm dependencies
|
||||||
nix develop --command just build
|
run: nix develop --command pnpm install
|
||||||
- name: Check bundle consistency
|
- name: Check formatting
|
||||||
run: |
|
run: nix develop --command pnpm run format
|
||||||
NEW_BUNDLE_HASH=$(sha256sum <dist/index.js | sed 's/ -//')
|
- name: Lint
|
||||||
if [[ "$BUNDLE_HASH" != "$NEW_BUNDLE_HASH" ]]; then
|
run: nix develop --command pnpm run lint
|
||||||
>&2 echo "The committed dist/index.js is out-of-date!"
|
- name: Build
|
||||||
>&2 echo
|
run: nix develop --command pnpm run build
|
||||||
>&2 echo " Committed: $BUNDLE_HASH"
|
- name: Package
|
||||||
>&2 echo " Built: $NEW_BUNDLE_HASH"
|
run: nix develop --command pnpm run package
|
||||||
>&2 echo
|
- run: git status --porcelain=v1
|
||||||
>&2 echo 'Run `just build` then commit the resulting dist/index.js'
|
- run: test $(git status --porcelain=v1 2>/dev/null | wc -l) -eq 0
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
run-x86_64-linux:
|
run-x86_64-linux:
|
||||||
name: Run x86_64 Linux
|
name: Run x86_64 Linux
|
||||||
|
|
BIN
bun.lockb
BIN
bun.lockb
Binary file not shown.
1
dist/index.d.ts
generated
vendored
Normal file
1
dist/index.d.ts
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export {};
|
96658
dist/index.js
generated
vendored
96658
dist/index.js
generated
vendored
File diff suppressed because one or more lines are too long
3
dist/package.json
generated
vendored
Normal file
3
dist/package.json
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
|
@ -18,11 +18,12 @@
|
||||||
devShells = forAllSystems ({ pkgs }: {
|
devShells = forAllSystems ({ pkgs }: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
bun
|
|
||||||
jq
|
jq
|
||||||
act
|
|
||||||
just
|
|
||||||
shellcheck
|
shellcheck
|
||||||
|
nodejs_latest
|
||||||
|
nixpkgs-fmt
|
||||||
|
nodePackages_latest.pnpm
|
||||||
|
nodePackages_latest.typescript-language-server
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
21
justfile
21
justfile
|
@ -1,21 +0,0 @@
|
||||||
# A creds.json can be specified to test auto-caching locally.
|
|
||||||
# See <https://github.com/DeterminateSystems/magic-nix-cache> for
|
|
||||||
# instructions on how to obtain this file.
|
|
||||||
github_creds_json := env_var_or_default('GITHUB_CREDS_JSON', '')
|
|
||||||
|
|
||||||
# List available recipes
|
|
||||||
default:
|
|
||||||
@just --list --unsorted --justfile {{justfile()}}
|
|
||||||
|
|
||||||
# Install dependencies
|
|
||||||
install:
|
|
||||||
bun i --no-summary --ignore-scripts
|
|
||||||
|
|
||||||
# Build the action
|
|
||||||
build: install
|
|
||||||
bun run build
|
|
||||||
|
|
||||||
# Run CI locally
|
|
||||||
act job='run-x86_64-linux': build
|
|
||||||
act -j {{job}} -P ubuntu-22.04=catthehacker/ubuntu:act-22.04 \
|
|
||||||
{{ if github_creds_json != '' { "--env-file <(jq -r '. | to_entries[] | .key + \"=\" + .value' " + github_creds_json + ")" } else { '' } }}
|
|
53
package.json
53
package.json
|
@ -1,25 +1,52 @@
|
||||||
{
|
{
|
||||||
"name": "magic-nix-cache",
|
"name": "magic-nix-cache-action",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "dist/index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c"
|
"build": "tsc",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"lint": "eslint src/**/*.ts",
|
||||||
|
"package": "ncc build",
|
||||||
|
"all": "pnpm run format && pnpm run lint && pnpm run build && pnpm run package"
|
||||||
},
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/DeterminateSystems/magic-nix-cache-action.git"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
"license": "LGPL",
|
"license": "LGPL",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/DeterminateSystems/magic-nix-cache-action/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/DeterminateSystems/magic-nix-cache-action#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.1",
|
||||||
"got": "^12.6.0",
|
"@actions/exec": "^1.1.1",
|
||||||
"tail": "^2.2.6",
|
"@actions/github": "^5.1.1",
|
||||||
"tslib": "^2.5.2"
|
"@actions/tool-cache": "^2.0.1",
|
||||||
|
"detsys-ts": "github:DeterminateSystems/detsys-ts#mnc-nits",
|
||||||
|
"fetch-retry": "^5.0.6",
|
||||||
|
"got": "^14.2.1",
|
||||||
|
"string-argv": "^0.3.2",
|
||||||
|
"tail": "^2.2.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@rollup/plugin-commonjs": "^25.0.0",
|
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.2",
|
"@types/node": "^20.12.7",
|
||||||
"@rollup/plugin-typescript": "^11.1.1",
|
"@types/tail": "^2.2.3",
|
||||||
"@types/node": "^20.11.17",
|
"@types/uuid": "^9.0.8",
|
||||||
"rollup": "^3.22.0",
|
"@typescript-eslint/eslint-plugin": "^7.6.0",
|
||||||
"typescript": "^5.0.4"
|
"@vercel/ncc": "^0.38.1",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
|
"eslint-plugin-github": "^4.10.2",
|
||||||
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"typescript": "^5.4.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4374
pnpm-lock.yaml
Normal file
4374
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,47 +0,0 @@
|
||||||
import * as path from 'node:path';
|
|
||||||
import { fileURLToPath } from 'node:url';
|
|
||||||
|
|
||||||
import typescript from '@rollup/plugin-typescript';
|
|
||||||
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
||||||
import commonjs from '@rollup/plugin-commonjs';
|
|
||||||
|
|
||||||
const nodeModules = path.dirname(fileURLToPath(import.meta.url)) + '/node_modules';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
input: './src/index.ts',
|
|
||||||
output: {
|
|
||||||
file: './dist/index.js',
|
|
||||||
format: 'es',
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
typescript({
|
|
||||||
noEmitOnError: true,
|
|
||||||
}),
|
|
||||||
nodeResolve({
|
|
||||||
exportConditions: ['node', 'default', 'module', 'require'],
|
|
||||||
}),
|
|
||||||
commonjs(),
|
|
||||||
],
|
|
||||||
onwarn(warning, warn) {
|
|
||||||
const allowlist = {
|
|
||||||
'CIRCULAR_DEPENDENCY': [
|
|
||||||
// core.ts -> oidc-utils.ts -> core.ts
|
|
||||||
nodeModules + '/@actions/core/lib/',
|
|
||||||
],
|
|
||||||
'THIS_IS_UNDEFINED': [
|
|
||||||
// __classPrivateField{Get,Set} generated by TypeScript
|
|
||||||
nodeModules + '/form-data-encoder/lib/',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
if (allowlist.hasOwnProperty(warning.code)) {
|
|
||||||
for (const exception of allowlist[warning.code]) {
|
|
||||||
const ids = warning.ids || [ warning.id ];
|
|
||||||
if (ids.filter(p => !p.startsWith(exception)).length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
warn(warning);
|
|
||||||
},
|
|
||||||
};
|
|
267
src/index.ts
267
src/index.ts
|
@ -1,94 +1,69 @@
|
||||||
// Main
|
import * as fs from "node:fs/promises";
|
||||||
|
import * as os from "node:os";
|
||||||
|
import * as path from "node:path";
|
||||||
|
import { spawn, exec, SpawnOptions } from "node:child_process";
|
||||||
|
import { openSync, readFileSync } from "node:fs";
|
||||||
|
import { inspect, promisify } from "node:util";
|
||||||
|
import * as http from "http";
|
||||||
|
|
||||||
import * as fs from 'node:fs/promises';
|
import * as core from "@actions/core";
|
||||||
import * as os from 'node:os';
|
import { Tail } from "tail";
|
||||||
import * as path from 'node:path';
|
|
||||||
import { spawn, exec, SpawnOptions } from 'node:child_process';
|
|
||||||
import { openSync, readFileSync } from 'node:fs';
|
|
||||||
import { inspect, promisify } from 'node:util';
|
|
||||||
import * as http from 'http';
|
|
||||||
|
|
||||||
import * as core from '@actions/core';
|
|
||||||
import { Tail } from 'tail';
|
|
||||||
import got from "got";
|
import got from "got";
|
||||||
|
import { IdsToolbox } from "detsys-ts";
|
||||||
|
|
||||||
const ENV_CACHE_DAEMONDIR = 'MAGIC_NIX_CACHE_DAEMONDIR';
|
const ENV_CACHE_DAEMONDIR = "MAGIC_NIX_CACHE_DAEMONDIR";
|
||||||
|
|
||||||
const gotClient = got.extend({
|
const gotClient = got.extend({
|
||||||
retry: {
|
retry: {
|
||||||
limit: 1,
|
limit: 1,
|
||||||
methods: [ 'POST', 'GET', 'PUT', 'HEAD', 'DELETE', 'OPTIONS', 'TRACE' ],
|
methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"],
|
||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeRetry: [
|
beforeRetry: [
|
||||||
(error, retryCount) => {
|
(error, retryCount) => {
|
||||||
core.info(`Retrying after error ${error.code}, retry #: ${retryCount}`);
|
core.info(`Retrying after error ${error.code}, retry #: ${retryCount}`);
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function fetchAutoCacher(toolbox: IdsToolbox): Promise<string> {
|
||||||
function getCacherUrl() : string {
|
const closurePath = await toolbox.fetch();
|
||||||
const runnerArch = process.env.RUNNER_ARCH;
|
toolbox.recordEvent("load_closure");
|
||||||
const runnerOs = process.env.RUNNER_OS;
|
const { stdout } = await promisify(exec)(
|
||||||
const binarySuffix = `${runnerArch}-${runnerOs}`;
|
`cat "${closurePath}" | xz -d | nix-store --import`,
|
||||||
const urlPrefix = `https://install.determinate.systems/magic-nix-cache-closure`;
|
);
|
||||||
if (core.getInput('source-url')) {
|
|
||||||
return core.getInput('source-url');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (core.getInput('source-tag')) {
|
|
||||||
return `${urlPrefix}/tag/${core.getInput('source-tag')}/${binarySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (core.getInput('source-pr')) {
|
|
||||||
return `${urlPrefix}/pr/${core.getInput('source-pr')}/${binarySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (core.getInput('source-branch')) {
|
|
||||||
return `${urlPrefix}/branch/${core.getInput('source-branch')}/${binarySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (core.getInput('source-revision')) {
|
|
||||||
return `${urlPrefix}/rev/${core.getInput('source-revision')}/${binarySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${urlPrefix}/stable/${binarySuffix}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchAutoCacher() {
|
|
||||||
const binary_url = getCacherUrl();
|
|
||||||
core.info(`Fetching the Magic Nix Cache from ${binary_url}`);
|
|
||||||
|
|
||||||
const { stdout } = await promisify(exec)(`curl -L "${binary_url}" | xz -d | nix-store --import`);
|
|
||||||
|
|
||||||
const paths = stdout.split(os.EOL);
|
const paths = stdout.split(os.EOL);
|
||||||
|
|
||||||
// Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).
|
// Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).
|
||||||
const last_path = paths.at(-2);
|
const last_path = paths.at(-2);
|
||||||
|
|
||||||
return `${last_path}/bin/magic-nix-cache`;
|
return `${last_path}/bin/magic-nix-cache`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function tailLog(daemonDir) {
|
function tailLog(daemonDir: string): Tail {
|
||||||
const log = new Tail(path.join(daemonDir, 'daemon.log'));
|
const log = new Tail(path.join(daemonDir, "daemon.log"));
|
||||||
core.debug(`tailing daemon.log...`);
|
core.debug(`tailing daemon.log...`);
|
||||||
log.on('line', (line) => {
|
log.on("line", (line) => {
|
||||||
core.info(line);
|
core.info(line);
|
||||||
});
|
});
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setUpAutoCache() {
|
async function setUpAutoCache(toolbox: IdsToolbox): Promise<void> {
|
||||||
const tmpdir = process.env['RUNNER_TEMP'] || os.tmpdir();
|
const tmpdir = process.env["RUNNER_TEMP"] || os.tmpdir();
|
||||||
const required_env = ['ACTIONS_CACHE_URL', 'ACTIONS_RUNTIME_URL', 'ACTIONS_RUNTIME_TOKEN'];
|
const required_env = [
|
||||||
|
"ACTIONS_CACHE_URL",
|
||||||
|
"ACTIONS_RUNTIME_URL",
|
||||||
|
"ACTIONS_RUNTIME_TOKEN",
|
||||||
|
];
|
||||||
|
|
||||||
var anyMissing = false;
|
let anyMissing = false;
|
||||||
for (const n of required_env) {
|
for (const n of required_env) {
|
||||||
if (!process.env.hasOwnProperty(n)) {
|
if (!process.env.hasOwnProperty(n)) {
|
||||||
anyMissing = true;
|
anyMissing = true;
|
||||||
core.warning(`Disabling automatic caching since required environment ${n} isn't available`);
|
core.warning(
|
||||||
|
`Disabling automatic caching since required environment ${n} isn't available`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,37 +71,37 @@ async function setUpAutoCache() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
core.debug(`GitHub Action Cache URL: ${process.env['ACTIONS_CACHE_URL']}`);
|
core.debug(`GitHub Action Cache URL: ${process.env["ACTIONS_CACHE_URL"]}`);
|
||||||
|
|
||||||
const daemonDir = await fs.mkdtemp(path.join(tmpdir, 'magic-nix-cache-'));
|
const daemonDir = await fs.mkdtemp(path.join(tmpdir, "magic-nix-cache-"));
|
||||||
|
|
||||||
var daemonBin: string;
|
let daemonBin: string;
|
||||||
if (core.getInput('source-binary')) {
|
if (core.getInput("source-binary")) {
|
||||||
daemonBin = core.getInput('source-binary');
|
daemonBin = core.getInput("source-binary");
|
||||||
} else {
|
} else {
|
||||||
daemonBin = await fetchAutoCacher();
|
daemonBin = await fetchAutoCacher(toolbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
var runEnv;
|
let runEnv;
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
runEnv = {
|
runEnv = {
|
||||||
RUST_LOG: "trace,magic_nix_cache=debug,gha_cache=debug",
|
RUST_LOG: "trace,magic_nix_cache=debug,gha_cache=debug",
|
||||||
RUST_BACKTRACE: "full",
|
RUST_BACKTRACE: "full",
|
||||||
...process.env
|
...process.env,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
runEnv = process.env;
|
runEnv = process.env;
|
||||||
}
|
}
|
||||||
|
|
||||||
const notifyPort = core.getInput('startup-notification-port');
|
const notifyPort = core.getInput("startup-notification-port");
|
||||||
|
|
||||||
const notifyPromise = new Promise<Promise<void>>((resolveListening) => {
|
const notifyPromise = new Promise<Promise<void>>((resolveListening) => {
|
||||||
const promise = new Promise<void>(async (resolveQuit) => {
|
const promise = new Promise<void>(async (resolveQuit) => {
|
||||||
const notifyServer = http.createServer((req, res) => {
|
const notifyServer = http.createServer((req, res) => {
|
||||||
if (req.method === 'POST' && req.url === '/') {
|
if (req.method === "POST" && req.url === "/") {
|
||||||
core.debug(`Notify server shutting down.`);
|
core.debug(`Notify server shutting down.`);
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { "Content-Type": "application/json" });
|
||||||
res.end('{}');
|
res.end("{}");
|
||||||
notifyServer.close(() => {
|
notifyServer.close(() => {
|
||||||
resolveQuit();
|
resolveQuit();
|
||||||
});
|
});
|
||||||
|
@ -142,33 +117,44 @@ async function setUpAutoCache() {
|
||||||
|
|
||||||
// Start tailing the daemon log.
|
// Start tailing the daemon log.
|
||||||
const outputPath = `${daemonDir}/daemon.log`;
|
const outputPath = `${daemonDir}/daemon.log`;
|
||||||
const output = openSync(outputPath, 'a');
|
const output = openSync(outputPath, "a");
|
||||||
const log = tailLog(daemonDir);
|
const log = tailLog(daemonDir);
|
||||||
const netrc = await netrcPath();
|
const netrc = await netrcPath();
|
||||||
const nixConfPath = `${process.env["HOME"]}/.config/nix/nix.conf`;
|
const nixConfPath = `${process.env["HOME"]}/.config/nix/nix.conf`;
|
||||||
|
|
||||||
const daemonCliFlags: string[] = [
|
const daemonCliFlags: string[] = [
|
||||||
'--startup-notification-url', `http://127.0.0.1:${notifyPort}`,
|
"--startup-notification-url",
|
||||||
'--listen', core.getInput('listen'),
|
`http://127.0.0.1:${notifyPort}`,
|
||||||
'--upstream', core.getInput('upstream-cache'),
|
"--listen",
|
||||||
'--diagnostic-endpoint', core.getInput('diagnostic-endpoint'),
|
core.getInput("listen"),
|
||||||
'--nix-conf', nixConfPath
|
"--upstream",
|
||||||
].concat(
|
core.getInput("upstream-cache"),
|
||||||
core.getBooleanInput('use-flakehub') ? [
|
"--diagnostic-endpoint",
|
||||||
'--use-flakehub',
|
core.getInput("diagnostic-endpoint"),
|
||||||
'--flakehub-cache-server', core.getInput('flakehub-cache-server'),
|
"--nix-conf",
|
||||||
'--flakehub-api-server', core.getInput('flakehub-api-server'),
|
nixConfPath,
|
||||||
'--flakehub-api-server-netrc', netrc,
|
]
|
||||||
'--flakehub-flake-name', core.getInput('flakehub-flake-name'),
|
.concat(
|
||||||
] : []).concat(
|
core.getBooleanInput("use-flakehub")
|
||||||
core.getBooleanInput('use-gha-cache') ? [
|
? [
|
||||||
'--use-gha-cache'
|
"--use-flakehub",
|
||||||
] : []);
|
"--flakehub-cache-server",
|
||||||
|
core.getInput("flakehub-cache-server"),
|
||||||
|
"--flakehub-api-server",
|
||||||
|
core.getInput("flakehub-api-server"),
|
||||||
|
"--flakehub-api-server-netrc",
|
||||||
|
netrc,
|
||||||
|
"--flakehub-flake-name",
|
||||||
|
core.getInput("flakehub-flake-name"),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
)
|
||||||
|
.concat(core.getBooleanInput("use-gha-cache") ? ["--use-gha-cache"] : []);
|
||||||
|
|
||||||
const opts: SpawnOptions = {
|
const opts: SpawnOptions = {
|
||||||
stdio: ['ignore', output, output],
|
stdio: ["ignore", output, output],
|
||||||
env: runEnv,
|
env: runEnv,
|
||||||
detached: true
|
detached: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Display the final command for debugging purposes
|
// Display the final command for debugging purposes
|
||||||
|
@ -178,16 +164,22 @@ async function setUpAutoCache() {
|
||||||
// Start the server. Once it is ready, it will notify us via the notification server.
|
// Start the server. Once it is ready, it will notify us via the notification server.
|
||||||
const daemon = spawn(daemonBin, daemonCliFlags, opts);
|
const daemon = spawn(daemonBin, daemonCliFlags, opts);
|
||||||
|
|
||||||
const pidFile = path.join(daemonDir, 'daemon.pid');
|
const pidFile = path.join(daemonDir, "daemon.pid");
|
||||||
await fs.writeFile(pidFile, `${daemon.pid}`);
|
await fs.writeFile(pidFile, `${daemon.pid}`);
|
||||||
|
|
||||||
core.info("Waiting for magic-nix-cache to start...");
|
core.info("Waiting for magic-nix-cache to start...");
|
||||||
|
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
notifyPromise.then((value) => {
|
notifyPromise
|
||||||
resolve();
|
// eslint-disable-next-line github/no-then
|
||||||
});
|
.then((_value) => {
|
||||||
daemon.on('exit', async (code, signal) => {
|
resolve();
|
||||||
|
})
|
||||||
|
// eslint-disable-next-line github/no-then
|
||||||
|
.catch((err) => {
|
||||||
|
reject(new Error(`error in notifyPromise: ${err}`));
|
||||||
|
});
|
||||||
|
daemon.on("exit", async (code, signal) => {
|
||||||
if (signal) {
|
if (signal) {
|
||||||
reject(new Error(`Daemon was killed by signal ${signal}`));
|
reject(new Error(`Daemon was killed by signal ${signal}`));
|
||||||
} else if (code) {
|
} else if (code) {
|
||||||
|
@ -200,13 +192,13 @@ async function setUpAutoCache() {
|
||||||
|
|
||||||
daemon.unref();
|
daemon.unref();
|
||||||
|
|
||||||
core.info('Launched Magic Nix Cache');
|
core.info("Launched Magic Nix Cache");
|
||||||
core.exportVariable(ENV_CACHE_DAEMONDIR, daemonDir);
|
core.exportVariable(ENV_CACHE_DAEMONDIR, daemonDir);
|
||||||
|
|
||||||
log.unwatch();
|
log.unwatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function notifyAutoCache() {
|
async function notifyAutoCache(): Promise<void> {
|
||||||
const daemonDir = process.env[ENV_CACHE_DAEMONDIR];
|
const daemonDir = process.env[ENV_CACHE_DAEMONDIR];
|
||||||
|
|
||||||
if (!daemonDir) {
|
if (!daemonDir) {
|
||||||
|
@ -215,9 +207,10 @@ async function notifyAutoCache() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core.debug(`Indicating workflow start`);
|
core.debug(`Indicating workflow start`);
|
||||||
const res: any = await gotClient.post(`http://${core.getInput('listen')}/api/workflow-start`).json();
|
const res: Response = await gotClient
|
||||||
core.debug(`back from post`);
|
.post(`http://${core.getInput("listen")}/api/workflow-start`)
|
||||||
core.debug(res);
|
.json();
|
||||||
|
core.debug(`back from post: ${res}`);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
core.info(`Error marking the workflow as started:`);
|
core.info(`Error marking the workflow as started:`);
|
||||||
core.info(inspect(e));
|
core.info(inspect(e));
|
||||||
|
@ -225,26 +218,31 @@ async function notifyAutoCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function netrcPath(): Promise<string> {
|
||||||
async function netrcPath() {
|
const expectedNetrcPath = path.join(
|
||||||
const expectedNetrcPath = path.join(process.env['RUNNER_TEMP'], 'determinate-nix-installer-netrc')
|
process.env["RUNNER_TEMP"] || os.tmpdir(),
|
||||||
|
"determinate-nix-installer-netrc",
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
await fs.access(expectedNetrcPath)
|
await fs.access(expectedNetrcPath);
|
||||||
return expectedNetrcPath;
|
return expectedNetrcPath;
|
||||||
} catch {
|
} catch {
|
||||||
// `nix-installer` was not used, the user may be registered with FlakeHub though.
|
// `nix-installer` was not used, the user may be registered with FlakeHub though.
|
||||||
const destinedNetrcPath = path.join(process.env['RUNNER_TEMP'], 'magic-nix-cache-netrc')
|
const destinedNetrcPath = path.join(
|
||||||
|
process.env["RUNNER_TEMP"] || os.tmpdir(),
|
||||||
|
"magic-nix-cache-netrc",
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
await flakehub_login(destinedNetrcPath);
|
await flakehub_login(destinedNetrcPath);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
core.info("FlakeHub cache disabled.");
|
core.info("FlakeHub cache disabled.");
|
||||||
core.debug(`Error while logging into FlakeHub: ${e}`)
|
core.debug(`Error while logging into FlakeHub: ${e}`);
|
||||||
}
|
}
|
||||||
return destinedNetrcPath;
|
return destinedNetrcPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function flakehub_login(netrc: string) {
|
async function flakehub_login(netrc: string): Promise<void> {
|
||||||
const jwt = await core.getIDToken("api.flakehub.com");
|
const jwt = await core.getIDToken("api.flakehub.com");
|
||||||
|
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
|
@ -259,16 +257,16 @@ async function flakehub_login(netrc: string) {
|
||||||
core.info("Logged in to FlakeHub.");
|
core.info("Logged in to FlakeHub.");
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tearDownAutoCache() {
|
async function tearDownAutoCache(): Promise<void> {
|
||||||
const daemonDir = process.env[ENV_CACHE_DAEMONDIR];
|
const daemonDir = process.env[ENV_CACHE_DAEMONDIR];
|
||||||
|
|
||||||
if (!daemonDir) {
|
if (!daemonDir) {
|
||||||
core.debug('magic-nix-cache not started - Skipping');
|
core.debug("magic-nix-cache not started - Skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const pidFile = path.join(daemonDir, 'daemon.pid');
|
const pidFile = path.join(daemonDir, "daemon.pid");
|
||||||
const pid = parseInt(await fs.readFile(pidFile, { encoding: 'ascii' }));
|
const pid = parseInt(await fs.readFile(pidFile, { encoding: "ascii" }));
|
||||||
core.debug(`found daemon pid: ${pid}`);
|
core.debug(`found daemon pid: ${pid}`);
|
||||||
if (!pid) {
|
if (!pid) {
|
||||||
throw new Error("magic-nix-cache did not start successfully");
|
throw new Error("magic-nix-cache did not start successfully");
|
||||||
|
@ -278,9 +276,10 @@ async function tearDownAutoCache() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core.debug(`about to post to localhost`);
|
core.debug(`about to post to localhost`);
|
||||||
const res: any = await gotClient.post(`http://${core.getInput('listen')}/api/workflow-finish`).json();
|
const res: Response = await gotClient
|
||||||
core.debug(`back from post`);
|
.post(`http://${core.getInput("listen")}/api/workflow-finish`)
|
||||||
core.debug(res);
|
.json();
|
||||||
|
core.debug(`back from post: ${res}`);
|
||||||
} finally {
|
} finally {
|
||||||
core.debug(`unwatching the daemon log`);
|
core.debug(`unwatching the daemon log`);
|
||||||
log.unwatch();
|
log.unwatch();
|
||||||
|
@ -288,40 +287,32 @@ async function tearDownAutoCache() {
|
||||||
|
|
||||||
core.debug(`killing`);
|
core.debug(`killing`);
|
||||||
try {
|
try {
|
||||||
process.kill(pid, 'SIGTERM');
|
process.kill(pid, "SIGTERM");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code !== 'ESRCH') {
|
if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (core.isDebug()) {
|
if (core.isDebug()) {
|
||||||
core.info("Entire log:");
|
core.info("Entire log:");
|
||||||
const log = readFileSync(path.join(daemonDir, 'daemon.log'));
|
const entireLog = readFileSync(path.join(daemonDir, "daemon.log"));
|
||||||
core.info(log.toString());
|
core.info(entireLog.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isPost = !!process.env['STATE_isPost'];
|
const idslib = new IdsToolbox({
|
||||||
|
name: "magic-nix-cache",
|
||||||
|
fetchStyle: "gh-env-style",
|
||||||
|
idsProjectName: "magic-nix-cache-closure",
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
idslib.onMain(async () => {
|
||||||
if (!isPost) {
|
await setUpAutoCache(idslib);
|
||||||
core.saveState('isPost', 'true');
|
await notifyAutoCache();
|
||||||
await setUpAutoCache();
|
});
|
||||||
await notifyAutoCache();
|
idslib.onPost(async () => {
|
||||||
} else {
|
await tearDownAutoCache();
|
||||||
await tearDownAutoCache();
|
});
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
core.info(`got an exception:`);
|
|
||||||
core.info(e);
|
|
||||||
|
|
||||||
if (!isPost) {
|
idslib.execute();
|
||||||
core.setFailed(e.message);
|
|
||||||
throw e;
|
|
||||||
} else {
|
|
||||||
core.info("not considering this a failure: finishing the upload is optional, anyway.");
|
|
||||||
process.exit();
|
|
||||||
}}
|
|
||||||
|
|
||||||
core.debug(`rip`);
|
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es2020",
|
"target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
|
||||||
"module": "es2020",
|
"module": "Node16",
|
||||||
"noUnusedLocals": true
|
"moduleResolution": "NodeNext",
|
||||||
|
"outDir": "./dist",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"strict": true /* Enable all strict type-checking options. */,
|
||||||
|
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||||
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"declaration": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"]
|
"exclude": ["node_modules", "**/*.test.ts", "dist"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue