diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9eea170..02a4290 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,4 +25,9 @@ jobs: uses: ./ with: build-url: "https://github.com/empirical-run/dispatch-action" + auth-key: "1234567890" environment: production + runtime-config: | + foo: bar + baz: qux + eventName: ${{ github.event_name }} diff --git a/action.yml b/action.yml index 873a567..51d31f4 100644 --- a/action.yml +++ b/action.yml @@ -2,7 +2,6 @@ name: "Run Empirical tests" description: "This action dispatches a request to run tests" author: "empirical.run" -# Add your action's branding here. This will appear on the GitHub Marketplace. branding: icon: "send" color: "gray-dark" @@ -10,14 +9,17 @@ branding: # Define your inputs here. inputs: auth-key: - description: "Auth key for the application" - required: false - build-url: - description: "URL to the application to be tested" + description: "API key for Empirical" required: true environment: description: "Environment to run the tests on" required: true + build-url: + description: "URL to the application to be tested" + required: true + runtime-config: + description: "Runtime config for the tests" + required: false runs: using: node20 diff --git a/dist/index.js b/dist/index.js index f47a34b..85902a6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -29361,6 +29361,30 @@ async function getActor() { // https://github.com/actions/toolkit/issues/1143#issuecomment-2193348740 return process.env.GITHUB_TRIGGERING_ACTOR || github.context.actor; } +function parseRuntimeConfig(runtimeConfig) { + return runtimeConfig.reduce((acc, line) => { + if (!line.trim()) { + return acc; + } + if (!line.includes(':')) { + throw new Error(`Invalid runtime config format. Each line must contain a key-value pair separated by colon. Invalid line: "${line}"`); + } + const [key, value] = line.split(':'); + const trimmedKey = key.trim(); + const trimmedValue = value.trim(); + if (!trimmedKey) { + throw new Error(`Invalid runtime config: key cannot be empty in line "${line}"`); + } + if (!trimmedValue) { + throw new Error(`Invalid runtime config: value cannot be empty for key "${trimmedKey}"`); + } + if (acc[trimmedKey]) { + throw new Error(`Invalid runtime config: duplicate key "${trimmedKey}" found`); + } + acc[trimmedKey] = trimmedValue; + return acc; + }, {}); +} async function run() { try { const buildUrl = core.getInput('build-url'); @@ -29370,10 +29394,7 @@ async function run() { else if (!isValidUrl(buildUrl)) { core.setFailed(`Invalid config: build-url must be a valid URL.`); } - const slackWebhookUrl = core.getInput('slack-webhook-url'); - if (slackWebhookUrl) { - console.log(`Warning: slack-webhook-url is not a supported input, and will be ignored.`); - } + // TOOD: Remove platform and only keep environment const platform = core.getInput('platform'); if (platform) { console.warn(`Warning: platform is a deprecated input, you should use environment instead.`); @@ -29383,13 +29404,20 @@ async function run() { core.setFailed(`Missing config parameter: either of "environment" or "platform" (deprecated) needs to passed`); } const authKey = core.getInput('auth-key'); + if (!authKey) { + core.setFailed(`Missing config parameter: auth-key`); + } const headers = { 'Content-Type': 'application/json' }; if (authKey) { - console.log(`Setting an auth header for the request.`); headers['Authorization'] = `Bearer ${authKey}`; } + const runtimeConfig = core.getMultilineInput('runtime-config'); + if (runtimeConfig) { + const config = parseRuntimeConfig(runtimeConfig); + console.log(`Runtime config: ${JSON.stringify(config)}`); + } const branch = await getBranchName(); console.log(`Branch name: ${branch}`); const response = await fetch("https://dispatch.empirical.run/v1/trigger", { @@ -29407,7 +29435,7 @@ async function run() { commit_url: getCommitUrl(), }, platform, - environment, + environment: environment.toLowerCase(), github_actor: await getActor(), }) }); diff --git a/src/main.ts b/src/main.ts index d5d5a77..121b8f1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -150,6 +150,31 @@ async function getActor(): Promise { return process.env.GITHUB_TRIGGERING_ACTOR || github.context.actor; } +function parseRuntimeConfig(runtimeConfig: string[]): Record { + return runtimeConfig.reduce((acc: Record, line: string) => { + if (!line.trim()) { + return acc; + } + if (!line.includes(':')) { + throw new Error(`Invalid runtime config format. Each line must contain a key-value pair separated by colon. Invalid line: "${line}"`); + } + const [key, value] = line.split(':'); + const trimmedKey = key.trim(); + const trimmedValue = value.trim(); + if (!trimmedKey) { + throw new Error(`Invalid runtime config: key cannot be empty in line "${line}"`); + } + if (!trimmedValue) { + throw new Error(`Invalid runtime config: value cannot be empty for key "${trimmedKey}"`); + } + if (acc[trimmedKey]) { + throw new Error(`Invalid runtime config: duplicate key "${trimmedKey}" found`); + } + acc[trimmedKey] = trimmedValue; + return acc; + }, {}); +} + export async function run(): Promise { try { const buildUrl: string = core.getInput('build-url'); @@ -158,29 +183,34 @@ export async function run(): Promise { } else if (!isValidUrl(buildUrl)) { core.setFailed(`Invalid config: build-url must be a valid URL.`) } - const slackWebhookUrl: string = core.getInput('slack-webhook-url'); - if (slackWebhookUrl) { - console.log(`Warning: slack-webhook-url is not a supported input, and will be ignored.`) - } + + // TOOD: Remove platform and only keep environment const platform: string = core.getInput('platform'); if (platform) { console.warn(`Warning: platform is a deprecated input, you should use environment instead.`) } - const environment = core.getInput('environment'); if (!platform && !environment) { core.setFailed(`Missing config parameter: either of "environment" or "platform" (deprecated) needs to passed`) } const authKey = core.getInput('auth-key'); + if (!authKey) { + core.setFailed(`Missing config parameter: auth-key`) + } const headers: Record = { 'Content-Type': 'application/json' }; if (authKey) { - console.log(`Setting an auth header for the request.`); headers['Authorization'] = `Bearer ${authKey}`; } + const runtimeConfig = core.getMultilineInput('runtime-config'); + if (runtimeConfig) { + const config = parseRuntimeConfig(runtimeConfig); + console.log(`Runtime config: ${JSON.stringify(config)}`); + } + const branch = await getBranchName(); console.log(`Branch name: ${branch}`); const response = await fetch("https://dispatch.empirical.run/v1/trigger", { @@ -198,7 +228,7 @@ export async function run(): Promise { commit_url: getCommitUrl(), }, platform, - environment, + environment: environment.toLowerCase(), github_actor: await getActor(), }) });