Skip to content

added dry run #17

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

Merged
merged 9 commits into from
Apr 28, 2024
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
17 changes: 16 additions & 1 deletion .github/workflows/stackql-exec-test.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: 'stackql query tests'
name: 'stackql-exec tests'

on:
push:
Expand Down Expand Up @@ -114,6 +114,21 @@ jobs:
GOOGLE_PROJECT: ${{ vars.GOOGLE_PROJECT }}
GOOGLE_ZONE: ${{ vars.GOOGLE_ZONE }}

#
# run a query using the `query_file_path`, `data_file_path` and `vars` inputs (dry-run)
#
- name: google query example with query file and data file using vars (dry-run)
id: stackql-query-file-with-data-file-and-vars-dry-run
uses: ./
with:
query_file_path: './stackql_scripts/google-instances-by-status-with-external-data-file.iql'
data_file_path: './stackql_scripts/google-instances-by-status-with-external-data-file.jsonnet'
vars: GOOGLE_PROJECT=${{ env.GOOGLE_PROJECT }},GOOGLE_ZONE=${{ env.GOOGLE_ZONE }}
dry_run: true
env:
GOOGLE_PROJECT: ${{ vars.GOOGLE_PROJECT }}
GOOGLE_ZONE: ${{ vars.GOOGLE_ZONE }}

#
# run a query using the `query_file_path`, `data_file_path` and `vars` inputs
#
Expand Down
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ Github Action as a wrapper for executing a single command in stackql, maps all s
Authentication to StackQL providers is done via environment variables source from GitHub Actions Secrets. To learn more about authentication, see the setup instructions for your provider or providers at the [StackQL Provider Registry Docs](https://stackql.io/registry).

## Inputs
- `query` - stackql query to execute **(need to supply either `query` or `query_file_path`)**
- `query_file_path` - stackql query file to execute **(need to supply either `query` or `query_file_path`)**
- `data_file_path` - (optional) path to data file to pass to the stackql query preprocessor (`json` or `jsonnet`)
- `vars` - (optional) comma delimited list of variables to pass to the stackql query preprocessor (supported with `jsonnet` config blocks or `jsonnet` data files only), accepts `var1=val1,var2=val2`, can be used to source environment variables into stackql queries
- `query_output` - (optional) output format of the stackql exec result, accepts `table`, `csv`, `json` and `text`, defaults to `json`
- `auth_obj_path` - (optional) the path of json file that stores stackql AUTH string **(only required when using non-standard environment variable names)**
- `auth_str` - (optional) stackql AUTH string **(only required when using non-standard environment variable names)**
- `is_command` - (optional defaults to 'false') set to true if the stackql execution is a command that does not return data
- **`query`** - stackql query to execute *(need to supply either __`query`__ or __`query_file_path`__)*
- **`query_file_path`** - stackql query file to execute *(need to supply either __`query`__ or __`query_file_path`__)*
- **`data_file_path`** - (optional) path to data file to pass to the stackql query preprocessor (`json` or `jsonnet`)
- **`dry_run`** - (optional) set to `true` to print the query that would be executed without actually executing it (default is `false`)
- **`vars`** - (optional) comma delimited list of variables to pass to the stackql query preprocessor (supported with `jsonnet` config blocks or `jsonnet` data files only), accepts `var1=val1,var2=val2`, can be used to source environment variables into stackql queries
- **`query_output`** - (optional) output format of the stackql exec result, accepts `table`, `csv`, `json` and `text`, defaults to `json`
- **`auth_obj_path`** - (optional) the path of json file that stores stackql AUTH string *(only required when using non-standard environment variable names)*
- **`auth_str`** - (optional) stackql AUTH string *(only required when using non-standard environment variable names)*
- **`is_command`** - (optional) set to `true` if the stackql execution is a command that does not return data (defaults to `false`)
- **`on_failure`** - (optional) behavior on a failure in query, supported values are `exit` (default) and `continue`

## Outputs
This action uses [setup-stackql](https://github.com/marketplace/actions/stackql-studio-setup-stackql), with use_wrapper set
to `true`, `stdout` and `stderr` are set to `exec-result` and `exec-error`

- `exec-result` - The STDOUT stream of the call to the `stackql` binary.
- `exec-error` - The STDERR stream of the call to the `stackql` binary.
- **`stackql-query-results`** - results from a stackql query (in the format specified)
- **`stackql-command-output`** - text output from a stackql command (a query that does not return data)
- **`stackql-query-error`** - error from a stackql query

## Examples

Expand Down
8 changes: 7 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ inputs:
data_file_path:
description: jsonnet or json data file to be passed to query preprocessor
required: false
dry_run:
description: set to true to print the query that would be executed without actually executing it (default is false)
required: false
default: 'false'
vars:
description: comma delimited list of vars to be passed to query preprocessor (supported with jsonnet config blocks or jsonnet data files only)
required: false
Expand Down Expand Up @@ -91,6 +95,7 @@ runs:
QUERY_FILE_PATH: ${{ inputs.query_file_path }}
QUERY: ${{inputs.query}}
DATA_FILE_PATH: ${{inputs.data_file_path}}
DRY_RUN: ${{inputs.dry_run}}
OUTPUT: ${{inputs.query_output}}
VARS: ${{inputs.vars}}

Expand All @@ -103,9 +108,10 @@ runs:
const utilsPath = path.join(process.env.GITHUB_ACTION_PATH, 'lib', 'utils.js')
const {execStackQLQuery} = require(utilsPath);
const onFailure = process.env.ON_FAILURE || 'exit'; // default to 'exit' if not specified
await execStackQLQuery(core, process.env.STACKQL_COMMAND, process.env.IS_COMMAND === 'true', onFailure);
await execStackQLQuery(core, process.env.STACKQL_COMMAND, process.env.IS_COMMAND === 'true', onFailure, process.env.DRY_RUN === 'true');
env:
IS_COMMAND: ${{ inputs.is_command }}
DRY_RUN: ${{ inputs.dry_run }}
ON_FAILURE: ${{ inputs.on_failure }}

branding:
Expand Down
1 change: 0 additions & 1 deletion lib/tests/failed-result.json

This file was deleted.

1 change: 0 additions & 1 deletion lib/tests/success-result.json

This file was deleted.

1 change: 0 additions & 1 deletion lib/tests/test-auth.json

This file was deleted.

2 changes: 2 additions & 0 deletions lib/tests/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ describe("Utils Functions Tests", () => {
let core;

beforeEach(() => {

core = {
debug: jest.fn().mockImplementation((message) => console.log(`DEBUG: ${message}`)),
setFailed: jest.fn().mockImplementation((message) => console.error(message)),
info: jest.fn().mockImplementation((message) => console.log(message)),
exportVariable: jest.fn(),
Expand Down
38 changes: 28 additions & 10 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@ function setupAuth(core) {

async function getStackqlCommand(core) {

const [query, queryFilePath, auth, output = "json", vars, dataFilePath] = [
const [query, queryFilePath, dry_run, auth, output = "json", vars, dataFilePath] = [
process.env.QUERY,
process.env.QUERY_FILE_PATH,
process.env.DRY_RUN,
process.env.AUTH,
process.env.OUTPUT,
process.env.VARS,
Expand Down Expand Up @@ -94,6 +95,12 @@ async function getStackqlCommand(core) {

args.push(`--output ${output}`);

if (checkEnvVarValid(dry_run)) {
if(dry_run === "true"){
args.push(`--dryrun`);
}
}

if (checkEnvVarValid(auth)) {
args.push(`--auth "${auth}"`);
}
Expand All @@ -107,7 +114,7 @@ async function getStackqlCommand(core) {
try {
const stackQLCommand = `${stackQLExecutable} ${args.join(" ")}`;
core.exportVariable('STACKQL_COMMAND', `${stackQLCommand}`);
core.info(`STACKQL_COMMAND: ${stackQLCommand}`);
core.debug(`STACKQL_COMMAND: ${stackQLCommand}`);
} catch (error) {
core.error(error);
core.setFailed("error when executing stackql");
Expand All @@ -124,16 +131,22 @@ const checkEnvVarValid = (variable) => {
* @param {string} command - The StackQL command to be executed.
* @param {boolean} isCommand - Indicates if the operation is a command (true) or query (false).
* @param {string} onFailure - The action to take if the command fails. Either 'exit' or 'continue'.
* @param {boolean} dryRun - Indicates if the operation is a dry run only.
*/
async function execStackQLQuery(core, command, isCommand, onFailure) {

if (onFailure !== 'exit' && onFailure !== 'continue') {
core.setFailed(`onFailure must be 'exit' or 'continue'. Received: ${onFailure}`);
return;
async function execStackQLQuery(core, command, isCommand, onFailure, dryRun) {

if (dryRun) {
// dry run
core.info(`dry-run enabled, skipping stackql query execution`);
} else {
// real query
if (onFailure !== 'exit' && onFailure !== 'continue') {
core.setFailed(`onFailure must be 'exit' or 'continue'. Received: ${onFailure}`);
return;
}
core.info(`executing stackql query (isCommand: ${isCommand}): ${command}`);
}

core.info(`executing stackql query (isCommand: ${isCommand}): ${command}`);

try {

let { stdout, stderr } = await execAsync(command);
Expand All @@ -156,7 +169,12 @@ async function execStackQLQuery(core, command, isCommand, onFailure) {
core.debug(`STDOUT: ${stdout}`);
if (!isCommand) {
core.setOutput('stackql-query-results', stdout);
core.info(`query output:\n${stdout}`);
if(dryRun){
const json = JSON.parse(stdout);
core.info(`dry-run query:\n${json[0].query}`);
} else {
core.info(`query output:\n${stdout}`);
}
}
} else {
core.debug('STDOUT: <empty>');
Expand Down