5
0
Fork 0
mirror of https://github.com/hashicorp/vault-action.git synced 2025-11-07 07:06:56 +00:00

update got dependency and convert to esm module (#533)

* update require got to import got

* convert remaining to esm

* wip: replace jest with vitest

* fix test imports and vitest config

* remove dist package.json

* fix import in ent test

* add dist

* move actions/core to prod dependency

* remove unused import that was breaking esm compilation

* simplify imports

* use module.createRequire to import jsonata

* add doc link comment

* add comments on import insanity

* add more comments

* update PR tempalte

* bump got and remove jest deps

* revert debug npm run command

* fix fs import

* simplify vitest config for each test suite
This commit is contained in:
John-Michael Faircloth 2024-03-19 10:42:34 -05:00 committed by GitHub
parent a727ce205a
commit 77efb36ae3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
39 changed files with 12213 additions and 14317 deletions

View file

@ -8,7 +8,6 @@ Relates OR Closes #0000
### Checklist
- [ ] Added [CHANGELOG](https://github.com/hashicorp/vault-action/blob/master/CHANGELOG.md) entry (only for user-facing changes)
- [ ] Did not commit changes to `dist/index.js` (This is only done for releases by vault-action maintainers)
### Community Note

View file

@ -48,14 +48,26 @@ jobs:
token: testtoken
secrets: |
secret/data/test-json-string jsonString;
secret/data/test-json-data jsonData;
- name: Check Secrets
run: |
touch secrets.json
echo "${{ steps.import-secrets.outputs.jsonString }}" >> secrets.json
- uses: actions/github-script@v7
with:
github-token: "foobar"
script: |
const { JSONSTRING, JSONDATA } = process.env
- name: Check json file format
run: |
echo
cat secrets.json
jq -c . < secrets.json
console.log(`string ${JSONSTRING}`)
console.log(`data ${JSONDATA}`)
const str = JSONDATA
let valid = true
try {
JSON.parse(str)
} catch (e) {
valid = false
}
if (valid) {
console.log("valid json")
} else {
console.log("not valid json")
}

22718
dist/index.js vendored

File diff suppressed because one or more lines are too long

3
dist/package.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"type": "module"
}

View file

@ -1,11 +1,12 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
import { vi, describe, test, expect } from 'vitest';
const got = require('got');
const { when } = require('jest-when');
vi.mock('@actions/core');
import core from '@actions/core';
const { exportSecrets } = require('../../src/action');
import got from 'got';
import { when } from 'jest-when'
import { exportSecrets } from '../../src/action.js';
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
@ -102,7 +103,7 @@ describe('authenticate with approle', () => {
});
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('method', expect.anything())

View file

@ -1,11 +1,12 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
import { vi, describe, test, expect } from 'vitest';
const got = require('got');
const { when } = require('jest-when');
vi.mock('@actions/core');
import core from '@actions/core';
const { exportSecrets } = require('../../src/action');
import got from 'got';
import { when } from 'jest-when'
import { exportSecrets } from '../../src/action.js';
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
@ -107,7 +108,7 @@ describe('integration', () => {
});
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('url', expect.anything())

View file

@ -1,3 +0,0 @@
module.exports = {
verbose: true
};

View file

@ -1,17 +1,18 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
const rsasign = require('jsrsasign');
const {
import { vi, describe, test, expect } from 'vitest';
vi.mock('@actions/core');
import core from '@actions/core';
import rsasign from 'jsrsasign';
import {
privateRsaKey,
privateRsaKeyBase64,
publicRsaKey
} = require('./rsa_keys');
} from './rsa_keys.js';
const got = require('got');
const { when } = require('jest-when');
import got from 'got';
import { when } from 'jest-when'
const { exportSecrets } = require('../../src/action');
import { exportSecrets } from '../../src/action.js';
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
@ -139,7 +140,7 @@ describe('jwt auth', () => {
describe('authenticate with private key', () => {
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('url', expect.anything())
@ -189,7 +190,7 @@ describe('jwt auth', () => {
})
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('url', expect.anything())

View file

@ -42,7 +42,7 @@ LrJEY9tZaRF8xraMZiOcBcyAt6S/TS29HttJ6+zlhcWx34fItEZ8jA5gzhTmspOY
-----END PUBLIC KEY-----
`;
module.exports = {
export {
privateRsaKey,
privateRsaKeyBase64,
publicRsaKey

View file

@ -1,11 +1,12 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
import { vi, describe, test, expect } from 'vitest';
const got = require('got');
const { when } = require('jest-when');
vi.mock('@actions/core');
import core from '@actions/core';
const { exportSecrets } = require('../../src/action');
import got from 'got';
import { when } from 'jest-when'
import { exportSecrets } from '../../src/action.js';
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8200'}`;
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
@ -84,7 +85,7 @@ describe('authenticate with userpass', () => {
});
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('method', expect.anything())

View file

@ -0,0 +1,11 @@
import { defineConfig, configDefaults } from 'vitest/config'
export default defineConfig({
test: {
// required to make jest-when work with vitest
globals: true,
include: [
'**/integrationTests/basic/**.{test,spec}.?(c|m)[jt]s?(x)',
],
},
})

View file

@ -1,3 +1,5 @@
import { describe, test, expect } from 'vitest';
describe('e2e-tls', () => {
it('verify', () => {
expect(process.env.SECRET).toBe("SUPERSECRET");

View file

@ -1,3 +0,0 @@
module.exports = {
verbose: true
};

View file

@ -1,5 +1,5 @@
const got = require('got');
const core = require('@actions/core');
import got from 'got';
import core from '@actions/core';
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
const caCertificateRaw = `${process.env.VAULTCA}`;

View file

@ -0,0 +1,11 @@
import { defineConfig, configDefaults } from 'vitest/config'
export default defineConfig({
test: {
// required to make jest-when work with vitest
globals: true,
include: [
'**/integrationTests/e2e-tls/**.{test,spec}.?(c|m)[jt]s?(x)',
],
},
})

View file

@ -1,3 +1,5 @@
import { describe, test, expect } from 'vitest';
describe('e2e', () => {
it('verify', () => {
expect(process.env.SECRET).toBe("SUPERSECRET");

View file

@ -1,3 +0,0 @@
module.exports = {
verbose: true
};

View file

@ -1,4 +1,4 @@
const got = require('got');
import got from 'got';
const vaultUrl = `${process.env.VAULT_HOST}:${process.env.VAULT_PORT}`;
const vaultToken = `${process.env.VAULT_TOKEN}` === undefined ? `${process.env.VAULT_TOKEN}` : "testtoken";

View file

@ -0,0 +1,11 @@
import { defineConfig, configDefaults } from 'vitest/config'
export default defineConfig({
test: {
// required to make jest-when work with vitest
globals: true,
include: [
'**/integrationTests/e2e/**.{test,spec}.?(c|m)[jt]s?(x)',
],
},
})

View file

@ -1,11 +1,12 @@
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
const core = require('@actions/core');
import { vi, describe, test, expect } from 'vitest';
const got = require('got');
const { when } = require('jest-when');
vi.mock('@actions/core');
import core from '@actions/core';
const { exportSecrets } = require('../../src/action');
import got from 'got';
import { when } from 'jest-when'
import { exportSecrets } from '../../src/action.js';
const vaultUrl = `http://${process.env.VAULT_HOST || 'localhost'}:${process.env.VAULT_PORT || '8201'}`;
const vaultToken = `${process.env.VAULT_TOKEN || 'testtoken'}`
@ -41,7 +42,7 @@ describe('integration', () => {
});
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('url', expect.anything())
@ -238,7 +239,7 @@ describe('authenticate with approle', () => {
});
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('method', expect.anything())

View file

@ -1,3 +0,0 @@
module.exports = {
verbose: true
};

View file

@ -0,0 +1,11 @@
import { defineConfig, configDefaults } from 'vitest/config'
export default defineConfig({
test: {
// required to make jest-when work with vitest
globals: true,
include: [
'**/integrationTests/enterprise/**.{test,spec}.?(c|m)[jt]s?(x)',
],
},
})

View file

@ -1,3 +0,0 @@
module.exports = {
testPathIgnorePatterns: ['/node_modules/', '<rootDir>/integrationTests/'],
};

3426
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,14 +2,15 @@
"name": "vault-action",
"version": "0.1.0",
"description": "A Github Action that allows you to consume vault secrets as secure environment variables.",
"type": "module",
"main": "dist/index.js",
"scripts": {
"build": "ncc build src/entry.js -o dist",
"test": "jest",
"test:integration:basic": "jest -c integrationTests/basic/jest.config.js",
"test:integration:enterprise": "jest -c integrationTests/enterprise/jest.config.js",
"test:integration:e2e": "jest -c integrationTests/e2e/jest.config.js",
"test:integration:e2e-tls": "jest -c integrationTests/e2e-tls/jest.config.js"
"test": "vitest run",
"test:integration:basic": "vitest run -c integrationTests/basic/vitest.config.js",
"test:integration:enterprise": "vitest run -c integrationTests/enterprise/vitest.config.js",
"test:integration:e2e": "vitest run -c integrationTests/e2e/vitest.config.js",
"test:integration:e2e-tls": "vitest run -c integrationTests/e2e-tls/vitest.config.js"
},
"files": [
"src/**/*",
@ -34,18 +35,15 @@
},
"homepage": "https://github.com/hashicorp/vault-action#readme",
"dependencies": {
"got": "^11.8.6",
"@actions/core": "^1.10.1",
"got": "^14.2.1",
"jsonata": "^2.0.3",
"jsrsasign": "^11.0.0"
},
"peerDependencies": {
"@actions/core": ">=1 <2"
},
"devDependencies": {
"@actions/core": "^1.10.1",
"@vercel/ncc": "^0.38.1",
"jest": "^29.7.0",
"jest-when": "^3.6.0",
"mock-http-server": "^1.4.5"
"mock-http-server": "^1.4.5",
"vitest": "^1.3.1"
}
}

View file

@ -1,12 +1,14 @@
// @ts-check
const core = require('@actions/core');
const command = require('@actions/core/lib/command');
const got = require('got').default;
const jsonata = require('jsonata');
const { normalizeOutputKey } = require('./utils');
const { WILDCARD } = require('./constants');
import core from '@actions/core';
import got from 'got';
const { auth: { retrieveToken }, secrets: { getSecrets } } = require('./index');
import { normalizeOutputKey } from './utils.js';
import { WILDCARD } from './constants.js';
import { retrieveToken } from './auth.js';
import { getSecrets } from './secrets.js';
// ncc doesn't compile jsonata imports properly, so we must use our own custom require
import require from "./cjs-require.js";
const jsonata = require('jsonata');
const AUTH_METHODS = ['approle', 'token', 'github', 'jwt', 'kubernetes', 'ldap', 'userpass'];
const ENCODING_TYPES = ['base64', 'hex', 'utf8'];
@ -219,9 +221,8 @@ function parseHeadersInput(inputKey, inputOptions) {
}, new Map());
}
module.exports = {
export {
exportSecrets,
parseSecretsInput,
parseHeadersInput,
};
}

View file

@ -1,17 +1,17 @@
jest.mock('got');
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
import { vi, describe, test, expect } from 'vitest';
const command = require('@actions/core/lib/command');
const core = require('@actions/core');
const got = require('got');
const {
vi.mock('got');
vi.mock('@actions/core');
import core from '@actions/core';
import got from 'got';
import {
exportSecrets,
parseSecretsInput,
parseHeadersInput
} = require('./action');
} from './action.js';
const { when } = require('jest-when');
import { when } from 'jest-when'
describe('parseSecretsInput', () => {
it('parses simple secret', () => {
@ -132,7 +132,7 @@ describe('parseHeaders', () => {
describe('exportSecrets', () => {
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('url', expect.anything())

View file

@ -1,8 +1,8 @@
// @ts-check
const core = require('@actions/core');
const rsasign = require('jsrsasign');
const fs = require('fs');
const { default: got } = require('got');
import core from '@actions/core';
import * as fs from 'fs';
import got from 'got';
import rsasign from 'jsrsasign';
const defaultKubernetesTokenPath = '/var/run/secrets/kubernetes.io/serviceaccount/token'
/***
@ -154,6 +154,6 @@ async function getClientToken(client, method, path, payload) {
* }} auth
*/
module.exports = {
export {
retrieveToken,
};

View file

@ -1,22 +1,20 @@
jest.mock('got');
jest.mock('@actions/core');
jest.mock('@actions/core/lib/command');
jest.mock('fs', () => ({
stat: jest.fn().mockResolvedValue(null),
import { vi, describe, test, expect } from 'vitest';
vi.mock('got');
vi.mock('@actions/core');
vi.mock('fs', () => ({
stat: vi.fn().mockResolvedValue(null),
promises: {
access: jest.fn().mockResolvedValue(null),
access: vi.fn().mockResolvedValue(null),
}
}));
const core = require('@actions/core');
const got = require('got');
const fs = require("fs")
const { when } = require('jest-when');
import core from '@actions/core';
import got from 'got'
import * as fs from 'fs';
import { when } from 'jest-when'
const {
retrieveToken
} = require('./auth');
import { retrieveToken } from './auth.js';
function mockInput(name, key) {
@ -27,7 +25,7 @@ function mockInput(name, key) {
function mockApiResponse() {
const response = { body: { auth: { client_token: testToken, renewable: true, policies: [], accessor: "accessor" } } }
got.post = jest.fn()
got.post = vi.fn()
got.post.mockReturnValue(response)
}
const testToken = "testoken";
@ -35,7 +33,7 @@ const testToken = "testoken";
describe("test retrival for token", () => {
beforeEach(() => {
jest.resetAllMocks();
vi.resetAllMocks();
});
it("test retrival with approle", async () => {
@ -76,7 +74,7 @@ describe("test retrival for token", () => {
mockInput("kubernetesTokenPath", testTokenPath)
mockInput("role", testRole)
mockInput("path", testPath)
fs.readFileSync = jest.fn()
fs.readFileSync = vi.fn()
fs.readFileSync.mockReturnValueOnce(jwtToken)
const token = await retrieveToken(method, got)
expect(token).toEqual(testToken)

7
src/cjs-require.js Normal file
View file

@ -0,0 +1,7 @@
// This allows us to use `require` in our ECMAScript module
// See: https://github.com/vercel/ncc/issues/791
// https://nodejs.org/api/module.html#modulecreaterequirefilename
import { createRequire } from "module";
const require = createRequire(import.meta.url);
export default require;

View file

@ -1,5 +1,5 @@
const WILDCARD = '*';
module.exports = {
export {
WILDCARD
};

View file

@ -1,5 +1,5 @@
const core = require('@actions/core');
const { exportSecrets } = require('./action');
import core from '@actions/core';
import { exportSecrets } from './action.js';
(async () => {
try {

View file

@ -1,7 +1,7 @@
const auth = require('./auth');
const secrets = require('./secrets');
import auth from './auth.js';
import secrets from './secrets.js';
module.exports = {
export default {
auth,
secrets
};

View file

@ -1,17 +1,19 @@
jest.mock('@actions/core');
import { vi, describe, test, expect } from 'vitest';
const core = require('@actions/core');
const ServerMock = require("mock-http-server");
const { exportSecrets } = require("./action");
const { when } = require('jest-when');
vi.mock('@actions/core');
import core from '@actions/core';
import ServerMock from 'mock-http-server';
import { exportSecrets } from './action.js';
import { when } from 'jest-when';
describe('exportSecrets retries', () => {
var server = new ServerMock({ host: "127.0.0.1", port: 0 });
var calls = 0;
beforeEach((done) => {
beforeEach(() => new Promise(done => {
calls = 0;
jest.resetAllMocks();
vi.resetAllMocks();
when(core.getInput)
.calledWith('token', expect.anything())
@ -28,11 +30,11 @@ describe('exportSecrets retries', () => {
.mockReturnValueOnce('http://127.0.0.1:' + server.getHttpPort());
done();
});
});
}));
afterEach((done) => {
afterEach(() => new Promise(done => {
server.stop(done);
});
}));
function mockStatusCodes(statusCodes) {
server.on({
@ -51,19 +53,19 @@ describe('exportSecrets retries', () => {
});
}
it('retries on 412 status code', (done) => {
it('retries on 412 status code', () => new Promise(done => {
mockStatusCodes([412, 200])
exportSecrets().then(() => {
expect(calls).toEqual(2);
done();
});
});
}));
it('retries on 500 status code', (done) => {
it('retries on 500 status code', () => new Promise(done => {
mockStatusCodes([500, 200])
exportSecrets().then(() => {
expect(calls).toEqual(2);
done();
});
});
}));
});

View file

@ -1,7 +1,11 @@
const jsonata = require("jsonata");
const { WILDCARD } = require("./constants");
const { normalizeOutputKey } = require("./utils");
const core = require('@actions/core');
import core from '@actions/core';
import { WILDCARD } from './constants.js';
import { normalizeOutputKey } from './utils.js';
// ncc doesn't compile jsonata imports properly, so we must use our own custom require
import require from "./cjs-require.js";
const jsonata = require('jsonata');
/**
* @typedef {Object} SecretRequest
@ -44,7 +48,7 @@ async function getSecrets(secretRequests, client, ignoreNotFound) {
} catch (error) {
const {response} = error;
if (response?.statusCode === 404) {
notFoundMsg = `Unable to retrieve result for "${path}" because it was not found: ${response.body.trim()}`;
let notFoundMsg = `Unable to retrieve result for "${path}" because it was not found: ${response.body.trim()}`;
const ignoreNotFound = (core.getInput('ignoreNotFound', { required: false }) || 'false').toLowerCase() != 'false';
if (ignoreNotFound) {
core.error(`${notFoundMsg}`);
@ -165,7 +169,7 @@ const selectAndAppendResults = async (
];
};
module.exports = {
export {
getSecrets,
selectData
}

View file

@ -14,6 +14,6 @@ function normalizeOutputKey(dataKey, isEnvVar = false) {
return outputKey;
}
module.exports = {
export {
normalizeOutputKey
};

12
vitest.config.js Normal file
View file

@ -0,0 +1,12 @@
import { defineConfig, configDefaults } from 'vitest/config'
export default defineConfig({
test: {
// required to make jest-when work with vitest
globals: true,
exclude:[
...configDefaults.exclude,
'**/integrationTests/**'
]
},
})