diff --git a/.github/workflows/stackql-assert.yml b/.github/workflows/stackql-assert.yml index 368c0f2..a4b2152 100644 --- a/.github/workflows/stackql-assert.yml +++ b/.github/workflows/stackql-assert.yml @@ -7,7 +7,10 @@ on: pull_request: jobs: stackql-exec-google-example: - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{matrix.os}} name: 'Assert test ' steps: @@ -15,7 +18,18 @@ jobs: uses: actions/checkout@v3 + - name: Prep Google Creds (Windows) + if: ${{ matrix.os == 'windows-latest'}} + run: | ## use the secret to create json file + $GoogleCreds = [System.Environment]::GetEnvironmentVariable("GOOGLE_CREDS_ENV") + $GoogleCredsDecoded = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($GoogleCreds)) + Write-Output $GoogleCredsDecoded | Set-Content sa-key.json + shell: pwsh + env: + GOOGLE_CREDS_ENV: ${{ secrets.GOOGLE_CREDS }} + - name: Prep Google Creds (bash) + if: ${{ matrix.os != 'windows-latest' }} shell: bash run: | ## use the base64 encoded secret to create json file sudo echo ${{ secrets.GOOGLE_CREDS }} | base64 -d > sa-key.json diff --git a/action.yml b/action.yml index 6e910ee..10fb424 100644 --- a/action.yml +++ b/action.yml @@ -1,4 +1,4 @@ -name: 'StackQL Studios - stackql-assert' +name: 'StackQL Studios - StackQL Assert' description: 'run StackQL query to test and audit your infrastructure.' author: 'Yuncheng Yang, StackQL Studios' inputs: @@ -55,18 +55,23 @@ runs: AUTH_FILE_PATH: ${{ inputs.auth_obj_path }} AUTH_STR: ${{inputs.auth_str}} - - name: Execute query - id: exec-query + - name: get stackql command uses: actions/github-script@v6 with: script: | - const {executeStackql} = require('./lib/utils.js') - await executeStackql(core, exec) + const {getStackqlCommand} = require('./lib/utils.js') + getStackqlCommand(core) env: QUERY_FILE_PATH: ${{ inputs.test_query_file_path }} QUERY: ${{inputs.test_query}} OUTPUT: 'json' + - name: execute stackql command + id: exec-query + shell: bash + run: | + ${{ env.STACKQL_COMMAND }} + - name: Check results uses: actions/github-script@v6 with: diff --git a/lib/tests/utils.test.js b/lib/tests/utils.test.js index 03ec29b..404458d 100644 --- a/lib/tests/utils.test.js +++ b/lib/tests/utils.test.js @@ -1,9 +1,9 @@ -const { setupAuth, executeStackql } = require("../utils"); +const { setupAuth, getStackqlCommand, setOutput } = require("../utils"); describe("util", () => { let core; - let exec; - const expectedAuth = '{ "google": { "type": "service_account", "credentialsfilepath": "sa-key.json" }}' + const expectedAuth = + '{ "google": { "type": "service_account", "credentialsfilepath": "sa-key.json" }}'; beforeEach(() => { core = { @@ -18,10 +18,6 @@ describe("util", () => { console.error(message); }), }; - - exec = { - exec: jest.fn().mockResolvedValue(true), - }; }); describe("setupAuth", () => { @@ -30,7 +26,6 @@ describe("util", () => { AUTH_FILE_PATH: "./lib/tests/test-auth.json", }; - beforeEach(() => { jest.resetModules(); process.env = { ...AUTH_ENV }; @@ -43,41 +38,41 @@ describe("util", () => { it("should throw error when neither AUTH_STR or AUTH_FILE_PATH is set", () => { process.env.AUTH_STR = undefined; process.env.AUTH_FILE_PATH = undefined; - - setupAuth(core) + + setupAuth(core); expect(core.setFailed).toBeCalledWith( "Either AUTH_FILE_PATH or AUTH_STR must be set." ); }); it("should set AUTH environment variable when AUTH_STR is set", () => { - process.env.AUTH_FILE_PATH = undefined; + process.env.AUTH_FILE_PATH = undefined; + + setupAuth(core); - setupAuth(core); - - expect(core.exportVariable).toBeCalledWith("AUTH", expectedAuth); + expect(core.exportVariable).toBeCalledWith("AUTH", expectedAuth); }); it("should set AUTH environment variable when AUTH_FILE_PATH is set", () => { - process.env.AUTH_STR = undefined; - - setupAuth(core); - - expect(core.exportVariable).toBeCalledWith("AUTH", expectedAuth); + process.env.AUTH_STR = undefined; + + setupAuth(core); + + expect(core.exportVariable).toBeCalledWith("AUTH", expectedAuth); }); it("should throw error when AUTH_FILE_PATH is set but file does not exist", () => { process.env.AUTH_STR = undefined; process.env.AUTH_FILE_PATH = "./failed-test-auth.json"; - - setupAuth(core) + + setupAuth(core); expect(core.setFailed).toBeCalledWith( `Cannot find auth file ${process.env.AUTH_FILE_PATH}` ); }); }); - describe("executeStackql", () => { + describe("getStackqlCommand", () => { const EXECUTE_ENV = { QUERY: "test", QUERY_FILE_PATH: "test-query.json", @@ -91,56 +86,52 @@ describe("util", () => { afterEach(() => { process.env = EXECUTE_ENV; + jest.clearAllMocks(); }); it("should return error when there is neither query or query file path", async () => { process.env = { ...EXECUTE_ENV }; process.env.QUERY = undefined; process.env.QUERY_FILE_PATH = undefined; - - await executeStackql(core, exec); + + getStackqlCommand(core); expect(core.setFailed).toBeCalledWith( - "Either test_query or test_query_file_path need to be set" + "Either query or query_file_path need to be set" ); }); - it("should return error when there is no AUTH", async() => { + it("should return error when there is no AUTH", async () => { process.env = { ...EXECUTE_ENV }; process.env.AUTH = undefined; - await executeStackql(core, exec); + getStackqlCommand(core); - expect(core.setFailed).toHaveBeenCalledWith("Cannot find AUTH environment variable when executing stackql"); + expect(core.setFailed).toHaveBeenCalledWith( + "Cannot find AUTH environment variable when executing stackql" + ); }); it("should execute stackql with query file path", async () => { process.env = { ...EXECUTE_ENV }; process.env.QUERY = undefined; - await executeStackql(core, exec); + getStackqlCommand(core); - expect(exec.exec).toHaveBeenCalledWith("stackql", [ - "exec", - "-i", - "test-query.json", - "--auth=test-auth", - "--output=json", - ]); + expect(core.exportVariable).toBeCalledWith( + "STACKQL_COMMAND", "stackql exec -i test-query.json --auth='test-auth' --output='json'" + ); }); it("should execute stackql with query", async () => { process.env = { ...EXECUTE_ENV }; process.env.QUERY_FILE_PATH = undefined; - await executeStackql(core, exec); + getStackqlCommand(core); - expect(exec.exec).toHaveBeenCalledWith("stackql", [ - "exec", - "test", - "--auth=test-auth", - "--output=json", - ]); + expect(core.exportVariable).toBeCalledWith( + "STACKQL_COMMAND", "stackql exec \"test\" --auth='test-auth' --output='json'" + ); }); }); }); diff --git a/lib/utils.js b/lib/utils.js index b93cb3d..9e94b23 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,3 +1,4 @@ + function setupAuth(core) { const fs = require("fs"); let auth; @@ -27,7 +28,8 @@ function setupAuth(core) { core.exportVariable("AUTH", auth); } -async function executeStackql(core, exec) { +async function getStackqlCommand(core) { + if (!checkEnvVarValid(process.env.AUTH)) { core.setFailed("Cannot find AUTH environment variable when executing stackql"); return; @@ -42,7 +44,7 @@ async function executeStackql(core, exec) { if (!checkEnvVarValid(query) && !checkEnvVarValid(queryFilePath)) { - core.setFailed("Either test_query or test_query_file_path need to be set"); + core.setFailed("Either query or query_file_path need to be set"); return; } @@ -52,16 +54,15 @@ async function executeStackql(core, exec) { "exec", "-i", queryFilePath, - "--auth=" + auth, - "--output=" + output, + `--auth='${auth}'`, + `--output='${output}'` ]; } if (query) { - args = ["exec", query, "--auth=" + auth, "--output=" + output]; + args = ["exec", `"${query}"`, `--auth='${auth}'`, `--output='${output}'`]; } - try { - await exec.exec("stackql", args); + core.exportVariable('STACKQL_COMMAND', `stackql ${args.join(" ")}`) } catch (error) { core.error(error); core.setFailed("Error when executing stackql"); @@ -81,5 +82,5 @@ const checkEnvVarValid = (variable) => { module.exports = { setupAuth, - executeStackql, + getStackqlCommand, };