Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start preflighting to see if Nix is installed #15

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dist/main.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

44 changes: 44 additions & 0 deletions dist/main.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions dist/test-run.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

65 changes: 65 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const FACT_FINAL_EXCEPTION = "final_exception";

export type FetchSuffixStyle = "nix-style" | "gh-env-style" | "universal";
export type ExecutionPhase = "main" | "post";
export type NixRequirementHandling = "fail" | "warn" | "ignore";

export type ActionOptions = {
// Name of the project generally, and the name of the binary on disk.
Expand All @@ -49,6 +50,11 @@ export type ActionOptions = {
// Users who configure legacySourcePrefix will get warnings asking them to change to `source-*`.
legacySourcePrefix?: string;

// Check if Nix is installed before running this action.
// If Nix isn't installed, this action will not fail, and will instead do nothing.
// The action will emit a user-visible warning instructing them to install Nix.
requireNix: NixRequirementHandling;

// The URL to send diagnostics events to.
// Specifically:
// * `undefined` -> Attempt to read the `diagnostic-enpdoint` action input, and calculate the default diagnostics URL for IDS from there.
Expand All @@ -64,6 +70,7 @@ type ConfidentActionOptions = {
eventPrefix: string;
fetchStyle: FetchSuffixStyle;
legacySourcePrefix?: string;
requireNix: NixRequirementHandling;
diagnosticsUrl?: URL;
};

Expand Down Expand Up @@ -193,6 +200,11 @@ export class IdsToolbox {
this.getCorrelationHashes(),
);

if (!(await this.preflightRequireNix())) {
this.recordEvent("preflight-require-nix-denied");
return;
}

if (this.executionPhase === "main" && this.hookMain) {
await this.hookMain();
} else if (this.executionPhase === "post" && this.hookPost) {
Expand Down Expand Up @@ -411,6 +423,58 @@ export class IdsToolbox {
}
}

private async preflightRequireNix(): Promise<boolean> {
let nixLocation: string | undefined;

const pathParts = (process.env["PATH"] || "").split(":");
for (const location of pathParts) {
const candidateNix = path.join(location, "nix");

try {
await fs.access(candidateNix, fs.constants.X_OK);
actionsCore.debug(`Found Nix at ${candidateNix}`);
nixLocation = candidateNix;
} catch {
actionsCore.debug(`Nix not at ${candidateNix}`);
}
}
this.addFact("nix_location", nixLocation || "");

if (this.actionOptions.requireNix === "ignore") {
return true;
}

const currentNotFoundState = actionsCore.getState(
"idstoolbox_nix_not_found",
);
if (currentNotFoundState === "not-found") {
// It was previously not found, so don't run subsequent actions
return false;
}

if (nixLocation !== undefined) {
return true;
}
actionsCore.saveState("idstoolbox_nix_not_found", "not-found");

switch (this.actionOptions.requireNix) {
case "fail":
actionsCore.setFailed(
"This action can only be used when Nix is installed." +
" Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow.",
);
break;
case "warn":
actionsCore.warning(
"This action is in no-op mode because Nix is not installed." +
" Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow.",
);
break;
}

return false;
}

private async submitEvents(): Promise<void> {
if (!this.actionOptions.diagnosticsUrl) {
actionsCore.debug(
Expand Down Expand Up @@ -453,6 +517,7 @@ function makeOptionsConfident(
eventPrefix: actionOptions.eventPrefix || "action:",
fetchStyle: actionOptions.fetchStyle,
legacySourcePrefix: actionOptions.legacySourcePrefix,
requireNix: actionOptions.requireNix,
diagnosticsUrl: determineDiagnosticsUrl(
idsProjectName,
actionOptions.diagnosticsUrl,
Expand Down
2 changes: 2 additions & 0 deletions src/test-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ async function main(): Promise<void> {
const toolbox = new IdsToolbox({
name: "nix-installer",
fetchStyle: "nix-style",
requireNix: "warn",
});

toolbox.onMain(async () => {
Expand All @@ -32,6 +33,7 @@ async function main(): Promise<void> {
const toolbox = new IdsToolbox({
name: "magic-nix-cache",
fetchStyle: "gh-env-style",
requireNix: "warn",
});

toolbox.onMain(async () => {
Expand Down