feat: auto push store paths and add CI (#1)
* feat: add flake devShell * chore: add prettier * fix: respect cache input during configure * feat: auto push paths * feat: add test workflow * chore: update index.js * refactors * pnpm lock * more refactors * remove copying --------- Co-authored-by: Ryan Cao <70191398+ryanccn@users.noreply.github.com>
This commit is contained in:
11
src/index.ts
11
src/index.ts
@@ -1,12 +1,9 @@
|
||||
import { install } from "./stages/install";
|
||||
import { configure } from "./stages/configure";
|
||||
import { push } from "./stages/push";
|
||||
|
||||
(async () => {
|
||||
const main = async () => {
|
||||
await install();
|
||||
await configure();
|
||||
await push();
|
||||
})().catch((e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
||||
};
|
||||
|
||||
main();
|
||||
|
||||
7
src/post.ts
Normal file
7
src/post.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { push } from "./stages/push";
|
||||
|
||||
const main = async () => {
|
||||
await push();
|
||||
};
|
||||
|
||||
main();
|
||||
@@ -1,11 +1,24 @@
|
||||
import { getInput, startGroup, endGroup } from "@actions/core";
|
||||
import * as core from "@actions/core";
|
||||
import { exec } from "@actions/exec";
|
||||
import { getStorePaths } from "../utils";
|
||||
|
||||
export const configure = async () => {
|
||||
startGroup("Configure attic");
|
||||
const endpoint = getInput("endpoint");
|
||||
const token = getInput("token");
|
||||
core.startGroup("Configure attic");
|
||||
|
||||
await exec("attic", ["login", "--set-default", "ci", endpoint, token]);
|
||||
endGroup();
|
||||
try {
|
||||
const endpoint = core.getInput("endpoint");
|
||||
const cache = core.getInput("cache");
|
||||
const token = core.getInput("token");
|
||||
|
||||
core.info("Logging in to attic cache");
|
||||
await exec("attic", ["login", "--set-default", cache, endpoint, token]);
|
||||
|
||||
core.info("Collecting store paths before build");
|
||||
const paths = await getStorePaths();
|
||||
core.saveState("initial-paths", JSON.stringify(paths));
|
||||
} catch (e) {
|
||||
core.setFailed(`Action failed with error: ${e}`);
|
||||
}
|
||||
|
||||
core.endGroup();
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { startGroup, endGroup } from "@actions/core";
|
||||
import * as core from "@actions/core";
|
||||
import { exec } from "@actions/exec";
|
||||
import { fetch } from "ofetch";
|
||||
|
||||
@@ -7,23 +7,31 @@ import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
export const install = async () => {
|
||||
startGroup("Install attic");
|
||||
core.startGroup("Install attic");
|
||||
|
||||
core.info("Installing attic");
|
||||
const installScript = await fetch(
|
||||
"https://raw.githubusercontent.com/zhaofengli/attic/main/.github/install-attic-ci.sh"
|
||||
).then((r) => {
|
||||
if (!r.ok)
|
||||
throw new Error(
|
||||
`Failed to fetch install script: ${r.status} ${r.statusText}`
|
||||
);
|
||||
if (!r.ok) {
|
||||
core.setFailed(`Action failed with error: ${r.statusText}`);
|
||||
core.endGroup();
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return r.text();
|
||||
});
|
||||
|
||||
const installScriptPath = join(tmpdir(), "install-attic-ci.sh");
|
||||
try {
|
||||
const installScriptPath = join(tmpdir(), "install-attic-ci.sh");
|
||||
|
||||
await writeFile(installScriptPath, installScript);
|
||||
await exec("bash", [installScriptPath]);
|
||||
await writeFile(installScriptPath, installScript);
|
||||
core.info("Running install script");
|
||||
await exec("bash", [installScriptPath]);
|
||||
} catch (e) {
|
||||
core.setFailed(`Action failed with error: ${e}`);
|
||||
}
|
||||
|
||||
endGroup();
|
||||
core.endGroup();
|
||||
};
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
import { getInput, getMultilineInput } from "@actions/core";
|
||||
import * as core from "@actions/core";
|
||||
import { exec } from "@actions/exec";
|
||||
import { getStorePaths } from "../utils";
|
||||
|
||||
export const push = async () => {
|
||||
const cache = getInput("cache");
|
||||
const paths = getMultilineInput("paths");
|
||||
core.startGroup("Push to Attic");
|
||||
|
||||
await exec("attic", ["push", cache, ...paths]);
|
||||
try {
|
||||
const skipPush = core.getInput("skip-push");
|
||||
if (skipPush === "true") {
|
||||
core.info("Pushing to cache is disabled by skip-push");
|
||||
} else {
|
||||
const cache = core.getInput("cache");
|
||||
|
||||
core.info("Pushing to cache");
|
||||
const oldPaths = JSON.parse(core.getState("initial-paths")) as string[];
|
||||
const newPaths = await getStorePaths();
|
||||
const addedPaths = newPaths.filter((p) => !oldPaths.includes(p));
|
||||
|
||||
await exec("attic", ["push", cache, ...addedPaths]);
|
||||
}
|
||||
} catch (e) {
|
||||
core.setFailed(`Action failed with error: ${e}`);
|
||||
}
|
||||
|
||||
core.endGroup();
|
||||
};
|
||||
|
||||
21
src/utils.ts
Normal file
21
src/utils.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { exec } from "@actions/exec";
|
||||
import { Writable } from "node:stream";
|
||||
|
||||
const streamToString = (stream: Writable): Promise<string> => {
|
||||
const chunks: Buffer[] = [];
|
||||
return new Promise((resolve, reject) => {
|
||||
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
||||
stream.on("error", (err) => reject(err));
|
||||
stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
||||
});
|
||||
};
|
||||
|
||||
export const getStorePaths = async () => {
|
||||
const outStream = new Writable();
|
||||
await exec("nix", ["path-info", "--all"], { outStream });
|
||||
const paths = await streamToString(outStream)
|
||||
.then((res) => res.split("\n"))
|
||||
.then((paths) => paths.filter(Boolean));
|
||||
|
||||
return paths;
|
||||
};
|
||||
Reference in New Issue
Block a user