Skip to content

Commit

Permalink
feat(ensureExists): allow action to succeed when file not found
Browse files Browse the repository at this point in the history
  • Loading branch information
FranciscoKloganB committed Jun 13, 2024
1 parent d1cd556 commit e7c0291
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 53 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Log variables after reading from the `.env` file.

Mask values after reading from the `.env` file.

### `ensure-exists`

Fail the action when `.env` file is not found at `path`. Default is `true`.

### `export-variables`

Export values as environment variables in addition to storing them in the output after reading from the `.env` file.
Expand Down
Binary file modified dist/index.js.cache
Binary file not shown.
2 changes: 1 addition & 1 deletion dist/index.js.cache.js

Large diffs are not rendered by default.

35 changes: 26 additions & 9 deletions dotenv_action.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
const fs = require("fs");
const core = require("@actions/core");

let dotenv_action = function (dotenvFile, keysCase) {
if (!fs.existsSync(dotenvFile)) {
throw new Error("file does not exist");
const fs = require("node:fs");

/**
* @param {object} kwargs
* @param {boolean} kwargs.ensureExists ensure that the file exists
* @param {'bypass' | 'lower' | 'upper'} kwargs.keysCase transform keys case or preserve them as they are
* @param {string} kwargs.path a relative path from the repository root
*/
const dotenvAction = ({ path, keysCase, ensureExists }) => {
const exists = fs.existsSync(path);

if (!exists && ensureExists) {
core.info(
"Action will fail as it was unable to load the environment file from the provided path. If you wish to bypass this check, set the 'ensure-exists' option to 'false'.",
);

throw new Error(`Environment file not found at path: '${path}'`);
}

const dotenv = require("dotenv").config({ path: dotenvFile });
const dotenv = require("dotenv").config({ path: path });
const dotenv_expand = require("dotenv-expand").expand(dotenv);
console.log("loading .env file from " + dotenvFile);

core.info(`Loading environment file from path: '${path}'`);

const returnedMap = {};

for (const key in dotenv_expand.parsed) {
const value = dotenv_expand.parsed[key];

if (keysCase == "bypass") {
if (keysCase === "bypass") {
returnedMap[key] = value;
} else if (keysCase == "upper") {
} else if (keysCase === "upper") {
returnedMap[key.toLocaleUpperCase()] = value;
} else {
returnedMap[key.toLocaleLowerCase()] = value;
}
}

return returnedMap;
};

module.exports = dotenv_action;
module.exports = dotenvAction;
42 changes: 23 additions & 19 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,44 @@
const core = require("@actions/core");
const dotenvAction = require("./dotenv_action");

try {
const dotenvFile = core.getInput("path");
const logVariables = core.getInput("log-variables").toLowerCase() === "true";
const maskVariables =
core.getInput("mask-variables").toLowerCase() === "true";
const exportVariables =
core.getInput("export-variables").toLowerCase() === "true";
const ensureExists = core.getInput("ensure-exists").toLowerCase();
const keysCase = core.getInput("keys-case").toLowerCase();
const logVariables = core.getInput("log-variables").toLowerCase();
const maskVariables = core.getInput("mask-variables").toLowerCase();
const exportVariables = core.getInput("export-variables").toLowerCase();

const exportVariablesPrefix = core.getInput("export-variables-prefix");
const keysCase = core
.getInput("keys-case", { required: false })
.toLowerCase();
const variables = dotenvAction(dotenvFile, keysCase, logVariables);
const path = core.getInput("path");

const variables = dotenvAction({
path: path || ".env",
ensureExists: (ensureExists || "true") === "true",
keysCase: keysCase || "lower",
});

if (maskVariables) {
if (maskVariables === "true") {
for (const key in variables) {
const value = variables[key];

core.setSecret(value);
}
}

if (logVariables) {
console.log(variables);
} else {
console.log(
`loaded ${Object.keys(variables).length} values into the environment`,
);
}
core.info(
logVariables === "true"
? JSON.stringify(variables, null, 2)
: `Loaded ${Object.keys(variables).length} values into the environment.`,
);

core.setOutput("generic", "please check for actual outputs");

for (const key in variables) {
const value = variables[key];

core.setOutput(key, value);

if (exportVariables) {
if (exportVariables === "true") {
core.exportVariable(exportVariablesPrefix + key, value);
}
}
Expand Down
86 changes: 62 additions & 24 deletions index.test.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,91 @@
test("test runs with custom path", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.env")).toEqual({ fixtures_1: "123" });
const { it, expect } = require("@jest/globals");

const dotenvAction = require("./dotenv_action");

it("fails when path does not exist and 'ensure-exists' is 'true'", () => {
expect(() =>
dotenvAction({
path: "nosuchfile",
ensureExists: true,
}),
).toThrow(Error);
});

it("runs when path does not exist and 'ensure-exists' is 'false'", () => {
const actual = dotenvAction({
path: "nosuchfile",
ensureExists: false,
});

expect(actual).toEqual({});
});

it("runs with custom path", () => {
const actual = dotenvAction({
path: "fixtures/.env",
});

expect(actual).toEqual({
fixtures_1: "123",
});
});

test("test runs with different path", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.another.env")).toEqual({
it("runs with another custom path", () => {
const actual = dotenvAction({
path: "fixtures/.another.env",
});

expect(actual).toEqual({
fixtures_2: "xyz",
other_key: "this",
});
});

test("test runs with broken path", () => {
const dotenv_action = require("./dotenv_action");
expect(() => {
dotenv_action("nosuchfile");
}).toThrow(Error);
});
it("runs with expanded values", () => {
const actual = dotenvAction({
path: "fixtures/.expand.env",
});

test("test runs with expanded values", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.expand.env")).toEqual({
expect(actual).toEqual({
fixtures_3: "xyz",
expanded: "123-xyz",
expanded_2: "123-xyz",
});
});

test("test runs with bypass case for keys", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.case.env", "bypass")).toEqual({
it("runs with bypass case for keys", () => {
const actual = dotenvAction({
path: "fixtures/.case.env",
keysCase: "bypass",
});

expect(actual).toEqual({
FIXTURES_4: "foo",
fixtures_5: "bar",
Fixtures_6: "abc",
});
});

test("test runs with lower case for keys", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.case.env", "lower")).toEqual({
it("runs with lower case for keys", () => {
const actual = dotenvAction({
path: "fixtures/.case.env",
keysCase: "lower",
});

expect(actual).toEqual({
fixtures_4: "foo",
fixtures_5: "bar",
fixtures_6: "abc",
});
});

test("test runs with upper case for keys", () => {
const dotenv_action = require("./dotenv_action");
expect(dotenv_action("fixtures/.case.env", "upper")).toEqual({
it("runs with upper case for keys", () => {
const actual = dotenvAction({
path: "fixtures/.case.env",
keysCase: "upper",
});

expect(actual).toEqual({
FIXTURES_4: "foo",
FIXTURES_5: "bar",
FIXTURES_6: "abc",
Expand Down

0 comments on commit e7c0291

Please sign in to comment.