Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pbrisbin committed Feb 10, 2024
1 parent b57cfe0 commit 110d54c
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 100 deletions.
4 changes: 4 additions & 0 deletions src/exec-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export class ExecStack {
.concat(args);
}

async upgrade(): Promise<number> {
return await exec.exec("stack", ["upgrade"]);
}

async exec(args: string[], options?: exec.ExecOptions): Promise<number> {
return await exec.exec("stack", this.stackArguments.concat(args), options);
}
Expand Down
70 changes: 46 additions & 24 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import * as path from "path";
import * as core from "@actions/core";

import { ExecStack } from "./exec-stack";
import { getCacheKeys } from "./get-cache-keys";
import { hashProject } from "./hash-project";
import type { Inputs } from "./inputs";
import { getInputs } from "./inputs";
import type { StackPath } from "./parse-stack-path";
import { parseStackPath } from "./parse-stack-path";
import type { StackQuery } from "./parse-stack-query";
import { getLocalStackWorks, parseStackQuery } from "./parse-stack-query";
import { parseStackQuery } from "./parse-stack-query";
import { readStackYamlSync, packagesStackWorks } from "./stack-yaml";
import { DEFAULT_CACHE_OPTIONS, withCache } from "./with-cache";

function setOutputs(stackQuery: StackQuery, stackPath: StackPath): void {
core.setOutput("compiler", stackQuery.compiler.actual);
core.setOutput(
"compiler-version",
stackQuery.compiler.actual.replace(/^ghc-/, ""),
);
}
// function setOutputs(stackQuery: StackQuery, stackPath: StackPath): void {
// core.setOutput("compiler", stackQuery.compiler.actual);
// core.setOutput(
// "compiler-version",
// stackQuery.compiler.actual.replace(/^ghc-/, ""),
// );
// }

async function dependencies(stack: ExecStack, inputs: Inputs): Promise<void> {
await stack.exec(["setup"].concat(inputs.stackSetupArguments));
Expand Down Expand Up @@ -54,28 +52,35 @@ async function run() {
process.chdir(inputs.workingDirectory);
}

const hashes = await hashProject(inputs.stackYaml);
core.info(`Snapshot hash ${hashes.snapshot}`);
core.info(`Package hash ${hashes.package}`);
core.info(`Sources hash ${hashes.sources}`);

const stack = new ExecStack(inputs.stackYaml, inputs.stackArguments);
const stackPath = await stack.parse(["path"], parseStackPath);
const stackQuery = await stack.parse(["query"], parseStackQuery);

setOutputs(stackQuery, stackPath);
await core.group("Stack upgrade", async () => {
await stack.upgrade();
});

const stackWork = path.join(process.cwd(), ".stack-work");
const stackWorks = getLocalStackWorks(stackQuery, [stackWork]);
core.info(`Found .stack-works:\n - ${stackWorks.join("\n - ")}`);
// Only use --stack-root, which (as of stack v2.15) won't load the
// environment and install GHC, etc. It's the only option currently safe to
// make outside of caching.
const stackRoot = (
await stack.parse(["path", "--stack-root]"], parseStackPath)
)["stack-root"];

const hashes = await hashProject(inputs.stackYaml);
const stackYaml = readStackYamlSync(inputs.stackYaml);
const stackWorks = packagesStackWorks(stackYaml);

await core.group("Dependencies", async () => {
const cacheKeys = getCacheKeys([
inputs.cachePrefix("stack-deps", stackQuery.compiler.actual),
inputs.cachePrefix("stack-deps", stackYaml.resolver),
hashes.snapshot,
hashes.package,
]);

const cachePaths = [stackPath["stack-root"], stackPath.programs].concat(
stackWorks,
);
const cachePaths = [stackRoot].concat(stackWorks);

await withCache(cachePaths, cacheKeys, dependencies(stack, inputs), {
...DEFAULT_CACHE_OPTIONS,
Expand All @@ -85,21 +90,38 @@ async function run() {

await core.group("Build", async () => {
const cacheKeys = getCacheKeys([
inputs.cachePrefix("stack-deps", stackQuery.compiler.actual),
inputs.cachePrefix("stack-deps", stackYaml.resolver),
hashes.snapshot,
hashes.package,
hashes.sources,
]);

await withCache(stackWorks, cacheKeys, build(stack, inputs), {
...DEFAULT_CACHE_OPTIONS,
skipOnHit: !inputs.cacheSaveAlways,
skipOnHit: false, // always Build
});
});

if (inputs.test) {
await core.group("Test", async () => await test(stack, inputs));
}

const stackQuery = await stack.parse(
["query", "compiler"],
parseStackQuery,
);

core.setOutput("compiler", stackQuery.compiler.actual);
core.setOutput(
"compiler-version",
stackQuery.compiler.actual.replace(/^ghc-/, ""),
);

const stackPath = await stack.parse(["path"], parseStackPath);

for (const k in stackPath) {
core.setOutput(k, stackPath[k]);
}
} catch (error) {
if (error instanceof Error) {
core.error(error);
Expand Down
24 changes: 1 addition & 23 deletions src/parse-stack-path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,7 @@ import * as yaml from "js-yaml";

export type StackPath = {
[key: string]: string | null;
"snapshot-doc-root": string;
"local-doc-root": string;
"local-hoogle-root": string;
"stack-root": string;
"global-config": string;
"project-root": string;
"config-location": string;
"bin-path": string;
programs: string;
"compiler-exe": string;
"compiler-bin": string;
"compiler-tools-bin": string;
"local-bin": string;
"extra-include-dirs": string | null;
"extra-library-dirs": string | null;
"snapshot-pkg-db": string;
"local-pkg-db": string;
"global-pkg-db": string;
"ghc-package-path": string;
"snapshot-install-root": string;
"local-install-root": string;
"dist-dir": string;
"local-hpc-root": string;
"stack-root": string; // we only require this one
};

export function parseStackPath(stdout: string): StackPath {
Expand Down
29 changes: 1 addition & 28 deletions src/parse-stack-query.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getLocalStackWorks, parseStackQuery } from "./parse-stack-query";
import { parseStackQuery } from "./parse-stack-query";

const EXAMPLE = [
"compiler:",
Expand All @@ -18,33 +18,6 @@ const EXAMPLE = [

test("parseStackQuery", () => {
const stackQuery = parseStackQuery(EXAMPLE);

expect(stackQuery.compiler.actual).toBe("ghc-9.2.7");
expect(stackQuery.compiler.wanted).toBe("ghc-9.2.7");
});

test("getLocalStackWorks", () => {
const stackQuery = parseStackQuery(EXAMPLE);

const stackWorks = getLocalStackWorks(stackQuery, []);

expect(stackWorks).toEqual([
"/home/patrick/code/freckle/megarepo/backend/core/.stack-work",
"/home/patrick/code/freckle/megarepo/backend/entities/.stack-work",
"/home/patrick/code/freckle/megarepo/backend/fancy-api/.stack-work",
]);
});

test("getLocalStackWorks avoids duplicates", () => {
const stackQuery = parseStackQuery(EXAMPLE);

const stackWorks = getLocalStackWorks(stackQuery, [
"/home/patrick/code/freckle/megarepo/backend/core/.stack-work",
]);

expect(stackWorks).toEqual([
"/home/patrick/code/freckle/megarepo/backend/core/.stack-work",
"/home/patrick/code/freckle/megarepo/backend/entities/.stack-work",
"/home/patrick/code/freckle/megarepo/backend/fancy-api/.stack-work",
]);
});
25 changes: 0 additions & 25 deletions src/parse-stack-query.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,14 @@
import * as osPath from "path";
import * as yaml from "js-yaml";

export type StackQuery = {
compiler: Compiler;
locals: Locals;
};

export type Compiler = {
actual: string;
wanted: string;
};

export type Locals = { [key: string]: Local };

export type Local = {
path: string;
version: string;
};

export function parseStackQuery(stdout: string): StackQuery {
return yaml.load(stdout) as StackQuery;
}

export function getLocalStackWorks(
stackQuery: StackQuery,
stackWorks: string[] = [],
): string[] {
for (const k in stackQuery.locals) {
const { path } = stackQuery.locals[k];
const stackWork = osPath.join(path, ".stack-work");

if (!stackWorks.includes(stackWork)) {
stackWorks.push(stackWork);
}
}

return stackWorks;
}
21 changes: 21 additions & 0 deletions src/stack-yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as fs from "fs";
import { join as joinPath } from "path";
import * as yaml from "js-yaml";

export type StackYaml = {
resolver: string;
packages: string[] | null;
};

export function readStackYamlSync(path: string): StackYaml {
const contents = fs.readFileSync(path, { encoding: "utf-8" });
return yaml.load(contents) as StackYaml;
}

export function packagesStackWorks(stackYaml: StackYaml): string[] {
const cwd = process.cwd();

return [".stack-work"]
.concat((stackYaml.packages ?? []).map((p) => joinPath(p, ".stack-work")))
.map((sw) => joinPath(cwd, sw));
}

0 comments on commit 110d54c

Please sign in to comment.