diff --git a/.github/workflows/timeout-test.yml b/.github/workflows/timeout-test.yml
new file mode 100644
index 0000000..64a8f07
--- /dev/null
+++ b/.github/workflows/timeout-test.yml
@@ -0,0 +1,39 @@
+on:
+ issue_comment:
+ types:
+ - created
+jobs:
+ container-tests:
+ runs-on: ubuntu-22.04
+ name: "Timeout test for testing farm as a github action"
+
+ if: |
+ github.event.issue.pull_request
+ && contains(github.event.comment.body, '[test]')
+ && contains(fromJson('["OWNER", "MEMBER"]'), github.event.comment.author_association)
+
+ steps:
+ - name: Checkout repo
+ uses: actions/checkout@v4
+ with:
+ ref: "refs/pull/${{ github.event.issue.number }}/head"
+
+ - name: Run the tests
+ uses: ./
+ id: tf_results
+ with:
+ api_key: ${{ secrets.TF_PUBLIC_API_KEY }}
+ git_ref: "main"
+ tmt_plan_regex: "timeout_plan"
+ pull_request_status_name: "Timeout test"
+ update_pull_request_status: "true"
+ timeout: 10
+
+ - name: Check if log contains exceed limit
+ run: |
+ curl ${{ steps.tf_results.outputs.test_log_url }} > results.log
+ ret_val = $(grep 'duration \"10s\" exceeded' results.log)
+ if [[ $ret_val != 0 ]]; then
+ exit 1
+ fi
+ exit 0
diff --git a/dist/action.js b/dist/action.js
new file mode 100644
index 0000000..f767230
--- /dev/null
+++ b/dist/action.js
@@ -0,0 +1,190 @@
+import { debug, getBooleanInput, getInput, notice, setOutput, summary, } from '@actions/core';
+import TestingFarmAPI from 'testing-farm';
+import { setTimeout } from 'timers/promises';
+import { TFError } from './error';
+import { setTfArtifactUrl, setTfRequestId } from './state';
+import { composeStatusDescription, getSummary } from './util';
+import { pipelineSettingsSchema, envSettingsSchema, tfScopeSchema, timeoutSchema, tmtArtifactsInputSchema, tmtArtifactsSchema, tmtContextInputSchema, tmtContextSchema, tmtEnvSecretsSchema, tmtEnvVarsSchema, tmtPlanRegexSchema, tmtPathSchema, } from './schema/input';
+import { requestDetailsSchema, requestSchema, } from './schema/testing-farm-api';
+async function action(pr) {
+ const tfInstance = getInput('api_url');
+ const api = new TestingFarmAPI(tfInstance);
+ // Get commit SHA value
+ const sha = pr.sha;
+ debug(`SHA: '${sha}'`);
+ // Set artifacts url
+ const tfScopeParsed = tfScopeSchema.safeParse(getInput('tf_scope'));
+ const tfScope = tfScopeParsed.success ? tfScopeParsed.data : 'public';
+ const tfUrl = tfScope === 'public'
+ ? 'https://artifacts.dev.testing-farm.io'
+ : 'http://artifacts.osci.redhat.com/testing-farm';
+ // Generate tmt variables
+ const tmtEnvVarsParsed = tmtEnvVarsSchema.safeParse(getInput('variables'));
+ const tmtEnvVars = tmtEnvVarsParsed.success ? tmtEnvVarsParsed.data : {};
+ // Generate tmt secrets
+ const tmtEnvSecretsParsed = tmtEnvSecretsSchema.safeParse(getInput('secrets'));
+ const tmtEnvSecrets = tmtEnvSecretsParsed.success
+ ? tmtEnvSecretsParsed.data
+ : {};
+ // Generate tmt artifacts
+ const tmtArtifactsParsed = tmtArtifactsInputSchema.safeParse(getInput('copr_artifacts'));
+ const tmtArtifacts = tmtArtifactsParsed.success
+ ? tmtArtifactsSchema.parse(tmtArtifactsParsed.data)
+ : [];
+ // Generate tmt hardware specification
+ // See https://tmt.readthedocs.io/en/stable/spec/plans.html#hardware
+ // https://gitlab.com/testing-farm/docs/root/-/merge_requests/120/diffs?view=inline
+ const rawTmtHardware = getInput('tmt_hardware');
+ let tmtHardware;
+ if (rawTmtHardware) {
+ tmtHardware = JSON.parse(rawTmtHardware);
+ }
+ // Conditionally include the name attribute only if tmt_plan_regex is not null
+ const tmtPathParsed = tmtPathSchema.safeParse(getInput('tmt_path'));
+ const tmtPath = tmtPathParsed.success ? tmtPathParsed.data : '.';
+ // Generate tmt context
+ const tmtContextParsed = tmtContextInputSchema.safeParse(getInput('tmt_context'));
+ const tmtContext = tmtContextParsed.success
+ ? tmtContextSchema.parse(tmtContextParsed.data)
+ : undefined;
+ // Conditionally include the name attribute only if tmt_plan_regex is not null
+ const tmtPlanRegexParsed = tmtPlanRegexSchema.safeParse(getInput('tmt_plan_regex'));
+ const tmtPlanRegex = tmtPlanRegexParsed.success
+ ? { name: tmtPlanRegexParsed.data }
+ : {};
+ // Generate environment settings
+ const envSettingsParsed = envSettingsSchema.safeParse(JSON.parse(getInput('environment_settings')));
+ const envSettings = envSettingsParsed.success ? envSettingsParsed.data : {};
+ const pipelineSettings = pipelineSettingsSchema.parse(JSON.parse(getInput('pipeline_settings')));
+ // Schedule a test on Testing Farm
+ const request = {
+ api_key: getInput('api_key', { required: true }),
+ test: {
+ fmf: Object.assign({ url: getInput('git_url', { required: true }), ref: getInput('git_ref'), path: tmtPath }, tmtPlanRegex),
+ },
+ environments: [
+ {
+ arch: getInput('arch'),
+ os: {
+ compose: getInput('compose'),
+ },
+ variables: tmtEnvVars,
+ settings: envSettings,
+ secrets: tmtEnvSecrets,
+ artifacts: tmtArtifacts,
+ tmt: Object.assign({}, (tmtContext ? { context: tmtContext } : {})),
+ },
+ ],
+ settings: {
+ pipeline: pipelineSettings,
+ },
+ };
+ let tfResponseRaw;
+ if (!rawTmtHardware) {
+ // Use newRequest method in case tmt_hardware is not defined or parameter is not properly formatted
+ tfResponseRaw = await api.newRequest(request, false);
+ }
+ else {
+ // The strict mode should be enabled once https://github.com/redhat-plumbers-in-action/testing-farm/issues/71 is fixed
+ tfResponseRaw = await api.unsafeNewRequest(Object.assign(Object.assign({}, request), { environments: [Object.assign(Object.assign({}, request.environments[0]), { hardware: tmtHardware })] }));
+ }
+ // Remove all secrets from request before printing it
+ delete request.api_key;
+ request.environments.map((env) => delete env.secrets);
+ debug(`Testing Farm request (except api_key and environment[].secrets): ${JSON.stringify(request, null, 2)}`);
+ debug(`Testing Farm response: ${JSON.stringify(tfResponseRaw, null, 2)}`);
+ const tfResponse = requestSchema.parse(tfResponseRaw);
+ const tfArtifactUrl = `${tfUrl}/${tfResponse.id}`;
+ notice(`Testing Farm logs: ${tfArtifactUrl}`);
+ // Set outputs and states
+ debug('Setting outputs and states');
+ setOutput('request_id', tfResponse.id);
+ setOutput('request_url', `${tfInstance}/requests/${tfResponse.id}`);
+ setOutput('test_log_url', tfArtifactUrl);
+ setTfRequestId(tfResponse.id);
+ setTfArtifactUrl(tfArtifactUrl);
+ // Create Pull Request status in state pending
+ await pr.setStatus('pending', 'Build started', `${tfArtifactUrl}`);
+ // Interval of 30 seconds in milliseconds
+ const interval = 30 * 1000;
+ const parsedTimeout = timeoutSchema.safeParse(getInput('timeout'));
+ // set timeout to 960 * 30 seconds ~ 8 hours ; timeout from input is in minutes (hence * 2)
+ let timeout = parsedTimeout.success ? parsedTimeout.data * 2 : 960;
+ let tfResult;
+ // Check if scheduled test is still running
+ // Ask Testing Farm every 30 seconds
+ debug(`Testing Farm - waiting for results (timeout: ${timeout} minutes)`);
+ do {
+ tfResult = requestDetailsSchema.parse(await api.requestDetails(tfResponse.id, false));
+ if (tfResult.state !== 'running' &&
+ tfResult.state !== 'new' &&
+ tfResult.state !== 'pending' &&
+ tfResult.state !== 'queued') {
+ break;
+ }
+ debug(`Testing Farm - state: '${tfResult.state}'`);
+ timeout--;
+ await setTimeout(interval);
+ } while (timeout > 0);
+ if (timeout === 0) {
+ throw new TFError(`Testing Farm - timeout reached. The test is still in state: '${tfResult.state}'`, `${tfArtifactUrl}`);
+ }
+ debug(`response:'${JSON.stringify(tfResult, null, 2)}'`);
+ // Get final state of Testing Farm scheduled request
+ const state = tfResult.state;
+ const result = tfResult.result ? tfResult.result.overall : 'unknown';
+ let finalState = 'success';
+ let infraError = false;
+ let log = '';
+ notice(`State is ${state} and result is: ${result}`);
+ if (state === 'complete') {
+ if (result !== 'passed') {
+ finalState = 'failure';
+ }
+ }
+ else {
+ // Mark job in case of infrastructure issues. Report to Testing Farm team
+ infraError = true;
+ finalState = 'failure';
+ log = 'pipeline.log';
+ }
+ notice(`Final state is: ${finalState}`);
+ notice(`Infra state is: ${infraError ? 'Failed' : 'OK'}`);
+ // Switch Pull Request Status to final state
+ await pr.setStatus(finalState, composeStatusDescription(infraError, getSummary(tfResult.result)), `${tfArtifactUrl}`);
+ // Add comment with Testing Farm request/result to Pull Request
+ if (getBooleanInput('create_issue_comment')) {
+ await pr.addComment(`Testing Farm [request](${tfInstance}/requests/${tfResponse.id}) for ${getInput('compose')}/${getInput('copr_artifacts')} regression testing has been created.` +
+ `Once finished, results should be available [here](${tfArtifactUrl}/).\n` +
+ `[Full pipeline log](${tfArtifactUrl}/pipeline.log).`);
+ }
+ // Create Github Summary
+ if (getBooleanInput('create_github_summary')) {
+ await summary
+ .addHeading('Testing Farm as a GitHub Action summary')
+ .addTable([
+ [
+ { data: 'Compose', header: true },
+ { data: 'Arch', header: true },
+ { data: 'Infrastructure State', header: true },
+ { data: 'Test result', header: true },
+ { data: 'Link to logs', header: true },
+ ],
+ [
+ getInput('compose'),
+ getInput('arch'),
+ infraError ? 'Failed' : 'OK',
+ finalState,
+ `test ` +
+ `pipeline`,
+ ],
+ ])
+ .write();
+ }
+ // Exit with error in case of failure in test
+ if (finalState === 'failure') {
+ throw new TFError(composeStatusDescription(infraError, getSummary(tfResult.result)), `${tfArtifactUrl}`);
+ }
+}
+export default action;
+//# sourceMappingURL=action.js.map
\ No newline at end of file
diff --git a/dist/action.js.map b/dist/action.js.map
new file mode 100644
index 0000000..72389c0
--- /dev/null
+++ b/dist/action.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"action.js","sourceRoot":"","sources":["../src/action.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/dist/error.js b/dist/error.js
new file mode 100644
index 0000000..037b0b2
--- /dev/null
+++ b/dist/error.js
@@ -0,0 +1,12 @@
+/**
+ * Custom error class for TF errors.
+ * @param message - The error message
+ * @param url - The optional URL to link to Testing Farm logs
+ */
+export class TFError extends Error {
+ constructor(message, url) {
+ super(message);
+ this.url = url;
+ }
+}
+//# sourceMappingURL=error.js.map
\ No newline at end of file
diff --git a/dist/error.js.map b/dist/error.js.map
new file mode 100644
index 0000000..876b3ee
--- /dev/null
+++ b/dist/error.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"error.js","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,OAAQ,SAAQ,KAAK;IAChC,YACE,OAAe,EACN,GAAY;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,QAAG,GAAH,GAAG,CAAS;IAGvB,CAAC;CACF"}
\ No newline at end of file
diff --git a/dist/main.js b/dist/main.js
new file mode 100644
index 0000000..f9fa30f
--- /dev/null
+++ b/dist/main.js
@@ -0,0 +1,40 @@
+import { getInput, setFailed } from '@actions/core';
+import { context } from '@actions/github';
+import '@total-typescript/ts-reset';
+import action from './action';
+import { TFError } from './error';
+import { getOctokit } from './octokit';
+import post from './post';
+import { PullRequest } from './pull-request';
+import { isPost } from './state';
+let pr = undefined;
+// All the code should be inside this try block
+try {
+ const octokit = getOctokit(getInput('github_token', { required: true }));
+ pr = await PullRequest.initialize(context.issue.number, octokit);
+ // Check if the script was invoked in the post step
+ if (!isPost) {
+ // Call the action function from action.ts
+ await action(pr);
+ }
+ else {
+ await post(pr);
+ }
+}
+catch (error) {
+ let message;
+ if (error instanceof Error) {
+ message = error.message;
+ }
+ else {
+ message = JSON.stringify(error);
+ }
+ // Set the Pull Request status to error when error occurs
+ if (pr) {
+ const url = error instanceof TFError ? error.url : undefined;
+ await pr.setStatus('error', `${message}`, url);
+ }
+ // Log the error and set the action status to failed
+ setFailed(message);
+}
+//# sourceMappingURL=main.js.map
\ No newline at end of file
diff --git a/dist/main.js.map b/dist/main.js.map
new file mode 100644
index 0000000..675eec9
--- /dev/null
+++ b/dist/main.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,OAAO,4BAA4B,CAAC;AAEpC,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,IAAI,MAAM,QAAQ,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,IAAI,EAAE,GAA4B,SAAS,CAAC;AAE5C,+CAA+C;AAC/C,IAAI,CAAC;IACH,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAEzE,EAAE,GAAG,MAAM,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAEjE,mDAAmD;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,0CAA0C;QAC1C,MAAM,MAAM,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;AACH,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,IAAI,OAAe,CAAC;IAEpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,yDAAyD;IACzD,IAAI,EAAE,EAAE,CAAC;QACP,MAAM,GAAG,GAAG,KAAK,YAAY,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7D,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,oDAAoD;IACpD,SAAS,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC"}
\ No newline at end of file
diff --git a/dist/octokit.js b/dist/octokit.js
new file mode 100644
index 0000000..3427efe
--- /dev/null
+++ b/dist/octokit.js
@@ -0,0 +1,24 @@
+import { info, warning } from '@actions/core';
+import { Octokit } from '@octokit/core';
+import { throttling } from '@octokit/plugin-throttling';
+const CustomOctokit = Octokit.plugin(throttling);
+export function getOctokit(token) {
+ return new CustomOctokit({
+ auth: token,
+ throttle: {
+ onRateLimit: (retryAfter, options, _octokit, retryCount) => {
+ warning(`Request quota exhausted for request ${options.method} ${options.url}`);
+ // Retry once after hitting a rate limit error, then give up
+ if (retryCount < 1) {
+ info(`Retrying after ${retryAfter} seconds!`);
+ return true;
+ }
+ },
+ onSecondaryRateLimit: (_retryAfter, options) => {
+ // When a secondary rate limit is hit, don't retry
+ warning(`SecondaryRateLimit detected for request ${options.method} ${options.url}`);
+ },
+ },
+ });
+}
+//# sourceMappingURL=octokit.js.map
\ No newline at end of file
diff --git a/dist/octokit.js.map b/dist/octokit.js.map
new file mode 100644
index 0000000..693fe0f
--- /dev/null
+++ b/dist/octokit.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"octokit.js","sourceRoot":"","sources":["../src/octokit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAExD,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AAIjD,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,OAAO,IAAI,aAAa,CAAC;QACvB,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE;YACR,WAAW,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE;gBACzD,OAAO,CACL,uCAAuC,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CACvE,CAAC;gBAEF,4DAA4D;gBAC5D,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;oBACnB,IAAI,CAAC,kBAAkB,UAAU,WAAW,CAAC,CAAC;oBAC9C,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YACD,oBAAoB,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE;gBAC7C,kDAAkD;gBAClD,OAAO,CACL,2CAA2C,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,EAAE,CAC3E,CAAC;YACJ,CAAC;SACF;KACF,CAAC,CAAC;AACL,CAAC"}
\ No newline at end of file
diff --git a/dist/post.js b/dist/post.js
new file mode 100644
index 0000000..9235e8e
--- /dev/null
+++ b/dist/post.js
@@ -0,0 +1,24 @@
+import { debug, getInput, notice } from '@actions/core';
+import TestingFarmAPI from 'testing-farm';
+import { getTfArtifactUrl, getTfRequestId } from './state';
+async function post(pr) {
+ const tfInstance = getInput('api_url');
+ const tfRequestId = getTfRequestId();
+ const tfArtifactUrl = getTfArtifactUrl();
+ const api = new TestingFarmAPI(tfInstance);
+ // This should happen really rarely, but it's better to check
+ if (!tfRequestId) {
+ throw new Error('POST: Missing Testing Farm request id');
+ }
+ const request = {
+ api_key: getInput('api_key', { required: true }),
+ };
+ notice(`Cancelling Testing Farm request: ${tfRequestId}`);
+ await api.cancelRequest(tfRequestId, request, false);
+ debug(`Request ${tfRequestId} was cancelled`);
+ // Set status to success when the request was cancelled
+ // It's not a test failure, the request was cancelled by the user
+ await pr.setStatus('success', 'Testing Farm request was cancelled', tfArtifactUrl !== null && tfArtifactUrl !== void 0 ? tfArtifactUrl : undefined);
+}
+export default post;
+//# sourceMappingURL=post.js.map
\ No newline at end of file
diff --git a/dist/post.js.map b/dist/post.js.map
new file mode 100644
index 0000000..4e9a08a
--- /dev/null
+++ b/dist/post.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"post.js","sourceRoot":"","sources":["../src/post.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,cAAc,MAAM,cAAc,CAAC;AAG1C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE3D,KAAK,UAAU,IAAI,CAAC,EAAe;IACjC,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;IAEzC,MAAM,GAAG,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,CAAC;IAE3C,6DAA6D;IAC7D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,OAAO,GAAG;QACd,OAAO,EAAE,QAAQ,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;KACjD,CAAC;IAEF,MAAM,CAAC,oCAAoC,WAAW,EAAE,CAAC,CAAC;IAC1D,MAAM,GAAG,CAAC,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;IACrD,KAAK,CAAC,WAAW,WAAW,gBAAgB,CAAC,CAAC;IAE9C,uDAAuD;IACvD,iEAAiE;IACjE,MAAM,EAAE,CAAC,SAAS,CAChB,SAAS,EACT,oCAAoC,EACpC,aAAa,aAAb,aAAa,cAAb,aAAa,GAAI,SAAS,CAC3B,CAAC;AACJ,CAAC;AAED,eAAe,IAAI,CAAC"}
\ No newline at end of file
diff --git a/dist/pull-request.js b/dist/pull-request.js
new file mode 100644
index 0000000..973dbf9
--- /dev/null
+++ b/dist/pull-request.js
@@ -0,0 +1,53 @@
+import { debug, getBooleanInput, getInput } from '@actions/core';
+import { context } from '@actions/github';
+/**
+ * Class for holding information about a Pull Request and interacting with it via the GitHub API.
+ */
+export class PullRequest {
+ /**
+ * PullRequest constructor, it's not meant to be called directly, use the static initialize method instead.
+ * @param number - The Pull Request number
+ * @param sha - The head sha of the Pull Request
+ * @param octokit - The Octokit instance to use for interacting with the GitHub API
+ */
+ constructor(number, sha, octokit) {
+ this.number = number;
+ this.sha = sha;
+ this.octokit = octokit;
+ }
+ /**
+ * Set the Pull Request status using the GitHub API.
+ * @param state - The state of the status, can be one of error, failure, pending or success
+ * @param description - The description of the status
+ * @param url - The URL to link to from the status
+ */
+ async setStatus(state, description, url) {
+ const usePullRequestStatuses = getBooleanInput('update_pull_request_status');
+ // Don't set the statuses when they are disabled
+ if (!usePullRequestStatuses) {
+ debug('Skipping setting Pull Request Status');
+ return;
+ }
+ const { data } = await this.octokit.request('POST /repos/{owner}/{repo}/statuses/{sha}', Object.assign(Object.assign({}, context.repo), { sha: this.sha, state, context: `Testing Farm - ${getInput('pull_request_status_name')}`, description: description ? description.slice(0, 140) : description, target_url: url }));
+ debug(`Setting Pull Request Status response: ${JSON.stringify(data, null, 2)}`);
+ }
+ /**
+ * Comment on the Pull Request using the GitHub API.
+ * @param body - The body of the comment
+ */
+ async addComment(body) {
+ const { data } = await this.octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', Object.assign(Object.assign({}, context.repo), { issue_number: this.number, body }));
+ debug(`Adding Issue comment response: ${JSON.stringify(data, null, 2)}`);
+ }
+ /**
+ * Initialize a PullRequest instance using data fetched from GitHub API.
+ * @param number - The Pull Request number
+ * @param octokit - The Octokit instance to use for interacting with the GitHub API
+ * @returns A Promise that resolves to a PullRequest instance
+ */
+ static async initialize(number, octokit) {
+ const { data } = await octokit.request('GET /repos/{owner}/{repo}/pulls/{pull_number}', Object.assign(Object.assign({}, context.repo), { pull_number: number }));
+ return new this(data.number, data.head.sha, octokit);
+ }
+}
+//# sourceMappingURL=pull-request.js.map
\ No newline at end of file
diff --git a/dist/pull-request.js.map b/dist/pull-request.js.map
new file mode 100644
index 0000000..57a7bad
--- /dev/null
+++ b/dist/pull-request.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"pull-request.js","sourceRoot":"","sources":["../src/pull-request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAK1C;;GAEG;AACH,MAAM,OAAO,WAAW;IACtB;;;;;OAKG;IACH,YACW,MAAc,EACd,GAAW,EACX,OAAsB;QAFtB,WAAM,GAAN,MAAM,CAAQ;QACd,QAAG,GAAH,GAAG,CAAQ;QACX,YAAO,GAAP,OAAO,CAAe;IAC9B,CAAC;IAEJ;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CACb,KAAoF,EACpF,WAAmB,EACnB,GAAY;QAEZ,MAAM,sBAAsB,GAAG,eAAe,CAC5C,4BAA4B,CAC7B,CAAC;QAEF,gDAAgD;QAChD,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACzC,2CAA2C,kCAEtC,OAAO,CAAC,IAAI,KACf,GAAG,EAAE,IAAI,CAAC,GAAG,EACb,KAAK,EACL,OAAO,EAAE,kBAAkB,QAAQ,CAAC,0BAA0B,CAAC,EAAE,EACjE,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,EAClE,UAAU,EAAE,GAAG,IAElB,CAAC;QAEF,KAAK,CACH,yCAAyC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CACzE,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,IAAY;QAC3B,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CACzC,2DAA2D,kCAEtD,OAAO,CAAC,IAAI,KACf,YAAY,EAAE,IAAI,CAAC,MAAM,EACzB,IAAI,IAEP,CAAC;QAEF,KAAK,CAAC,kCAAkC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,KAAK,CAAC,UAAU,CACrB,MAAc,EACd,OAAsB;QAEtB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CACpC,+CAA+C,kCAE1C,OAAO,CAAC,IAAI,KACf,WAAW,EAAE,MAAM,IAEtB,CAAC;QAEF,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;CACF"}
\ No newline at end of file
diff --git a/dist/schema/input.js b/dist/schema/input.js
new file mode 100644
index 0000000..c47d01b
--- /dev/null
+++ b/dist/schema/input.js
@@ -0,0 +1,78 @@
+import { z } from 'zod';
+export const tfScopeSchema = z.enum(['public', 'private']);
+// Parse string input into object of key-value pairs
+// input: 'REPO_URL=GITHUB_SERVER_URL/GITHUB_REPOSITORY;REPO_NAME=GITHUB_REPOSITORY'
+// output: { REPO_URL: 'GITHUB_SERVER_URL/GITHUB_REPOSITORY', REPO_NAME: 'GITHUB_REPOSITORY' }
+const stringToArraySchema = z.string().transform(str => str.split(';'));
+const keyValueArrayToObjectSchema = stringToArraySchema.transform(arr => {
+ let obj = {};
+ arr.forEach(item => {
+ const [key, ...values] = item.split('=');
+ // ''.split('=') returns [''] ; we have to check for this case
+ if (key === '' && Array.isArray(values) && values.length === 0)
+ return;
+ obj[key] = values.join('=');
+ });
+ return z.record(z.string(), z.string()).parse(obj);
+});
+export const tmtEnvVarsSchema = keyValueArrayToObjectSchema;
+export const tmtEnvSecretsSchema = keyValueArrayToObjectSchema;
+export const tmtArtifactsInputSchema = stringToArraySchema.transform(arr => {
+ let artifacts = [];
+ arr.forEach(item => {
+ if (item === '')
+ return;
+ artifacts.push({ type: 'fedora-copr-build', id: item });
+ });
+ return artifacts;
+});
+export const tmtContextInputSchema = keyValueArrayToObjectSchema;
+// https://api.testing-farm.io/redoc#operation/request_a_new_test_v0_1_requests_post
+export const tmtArtifactsSchema = z
+ .array(z.object({
+ id: z.string().min(1),
+ type: z.string().min(1),
+ packages: z.array(z.string().min(1)).optional(),
+ install: z.boolean().optional(),
+ order: z.number().optional(),
+}))
+ .default([]);
+// https://api.testing-farm.io/redoc#operation/request_a_new_test_v0_1_requests_post
+// https://tmt.readthedocs.io/en/stable/spec/context.html#dimension
+export const tmtContextSchema = z.object({
+ distro: z.string().min(1).optional(),
+ variant: z.string().min(1).optional(),
+ arch: z.string().min(1).optional(),
+ component: z.string().min(1).optional(),
+ collection: z.string().min(1).optional(),
+ module: z.string().min(1).optional(),
+ initiator: z.string().min(1).optional(),
+ trigger: z.string().min(1).optional(),
+});
+export const envSettingsSchema = z
+ .object({
+ pipeline: z
+ .object({
+ skip_guest_setup: z.boolean().optional(),
+ })
+ .optional(),
+ provisioning: z
+ .object({
+ post_install_script: z.string().min(1).optional(),
+ tags: z.record(z.string()).optional(),
+ })
+ .optional(),
+})
+ .optional();
+export const pipelineSettingsSchema = z
+ .object({
+ timeout: z.number().min(1).optional(),
+ type: z.enum(['tmt-multihost']).optional(),
+ 'provision-error-failed-result': z.boolean().optional(),
+ 'parallel-limit': z.number().nonnegative().optional(),
+})
+ .optional();
+export const timeoutSchema = z.coerce.number();
+export const tmtPlanRegexSchema = z.string().min(1);
+export const tmtPathSchema = z.string().min(1);
+//# sourceMappingURL=input.js.map
\ No newline at end of file
diff --git a/dist/schema/input.js.map b/dist/schema/input.js.map
new file mode 100644
index 0000000..d3c34b0
--- /dev/null
+++ b/dist/schema/input.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/schema/input.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAE3D,oDAAoD;AACpD,oFAAoF;AACpF,8FAA8F;AAC9F,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AACxE,MAAM,2BAA2B,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE;IACtE,IAAI,GAAG,GAA8B,EAAE,CAAC;IACxC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACjB,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,8DAA8D;QAC9D,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACvE,GAAG,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,2BAA2B,CAAC;AAC5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,2BAA2B,CAAC;AAC/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,mBAAmB,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE;IACzE,IAAI,SAAS,GAET,EAAE,CAAC;IACP,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACjB,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO;QAExB,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,2BAA2B,CAAC;AAEjE,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC;KAChC,KAAK,CACJ,CAAC,CAAC,MAAM,CAAC;IACP,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC/C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC/B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CACH;KACA,OAAO,CAAC,EAAE,CAAC,CAAC;AAEf,oFAAoF;AACpF,mEAAmE;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IAClC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACxC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC;KAC/B,MAAM,CAAC;IACN,QAAQ,EAAE,CAAC;SACR,MAAM,CAAC;QACN,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;KACzC,CAAC;SACD,QAAQ,EAAE;IACb,YAAY,EAAE,CAAC;SACZ,MAAM,CAAC;QACN,mBAAmB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;QACjD,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;KACtC,CAAC;SACD,QAAQ,EAAE;CACd,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC;KACpC,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,EAAE;IAC1C,+BAA+B,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IACvD,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE;CACtD,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;AAE/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEpD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC"}
\ No newline at end of file
diff --git a/dist/schema/testing-farm-api.js b/dist/schema/testing-farm-api.js
new file mode 100644
index 0000000..4442b0c
--- /dev/null
+++ b/dist/schema/testing-farm-api.js
@@ -0,0 +1,14 @@
+import { z } from 'zod';
+export const requestSchema = z.object({
+ id: z.string(),
+});
+export const requestDetailsSchema = z.object({
+ state: z.string(),
+ result: z
+ .object({
+ summary: z.union([z.string(), z.null()]),
+ overall: z.string(),
+ })
+ .nullable(),
+});
+//# sourceMappingURL=testing-farm-api.js.map
\ No newline at end of file
diff --git a/dist/schema/testing-farm-api.js.map b/dist/schema/testing-farm-api.js.map
new file mode 100644
index 0000000..bfd7dd4
--- /dev/null
+++ b/dist/schema/testing-farm-api.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"testing-farm-api.js","sourceRoot":"","sources":["../../src/schema/testing-farm-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;CACf,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE;IACjB,MAAM,EAAE,CAAC;SACN,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;KACpB,CAAC;SACD,QAAQ,EAAE;CACd,CAAC,CAAC"}
\ No newline at end of file
diff --git a/dist/state.js b/dist/state.js
new file mode 100644
index 0000000..6ebf64f
--- /dev/null
+++ b/dist/state.js
@@ -0,0 +1,23 @@
+// Inspired by action/checkout state handling
+import { getState, saveState } from '@actions/core';
+// Indicates whether the POST action is running
+export const isPost = !!getState('isPost');
+export function setTfRequestId(requestId) {
+ saveState('requestId', requestId);
+}
+export function getTfRequestId() {
+ return getState('requestId');
+}
+export function setTfArtifactUrl(requestUrl) {
+ saveState('artifactUrl', requestUrl);
+}
+export function getTfArtifactUrl() {
+ return getState('artifactUrl');
+}
+// Publish a variable so that when the POST action runs, it can determine it should run the cleanup logic.
+// This is necessary since we don't have a separate entry point.
+// ?NOTE: Post is invoked only when cancelled() is true
+if (!isPost) {
+ saveState('isPost', 'true');
+}
+//# sourceMappingURL=state.js.map
\ No newline at end of file
diff --git a/dist/state.js.map b/dist/state.js.map
new file mode 100644
index 0000000..5d09488
--- /dev/null
+++ b/dist/state.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEpD,+CAA+C;AAC/C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAE3C,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAkB;IACjD,SAAS,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,QAAQ,CAAC,aAAa,CAAC,CAAC;AACjC,CAAC;AAED,0GAA0G;AAC1G,gEAAgE;AAChE,uDAAuD;AACvD,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AAC9B,CAAC"}
\ No newline at end of file
diff --git a/dist/util.js b/dist/util.js
new file mode 100644
index 0000000..b0084e5
--- /dev/null
+++ b/dist/util.js
@@ -0,0 +1,16 @@
+import { z } from 'zod';
+export function composeStatusDescription(infraError, tfSummary) {
+ let description = infraError
+ ? 'Build failed - Infra problems'
+ : 'Build finished';
+ return description + tfSummary;
+}
+export function getSummary(result) {
+ const parsedResult = z
+ .object({
+ summary: z.string().min(1),
+ })
+ .safeParse(result);
+ return parsedResult.success ? ` - ${parsedResult.data.summary}` : '';
+}
+//# sourceMappingURL=util.js.map
\ No newline at end of file
diff --git a/dist/util.js.map b/dist/util.js.map
new file mode 100644
index 0000000..2e9c687
--- /dev/null
+++ b/dist/util.js.map
@@ -0,0 +1 @@
+{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,UAAU,wBAAwB,CACtC,UAAmB,EACnB,SAAiB;IAEjB,IAAI,WAAW,GAAG,UAAU;QAC1B,CAAC,CAAC,+BAA+B;QACjC,CAAC,CAAC,gBAAgB,CAAC;IAErB,OAAO,WAAW,GAAG,SAAS,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAe;IACxC,MAAM,YAAY,GAAG,CAAC;SACnB,MAAM,CAAC;QACN,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC3B,CAAC;SACD,SAAS,CAAC,MAAM,CAAC,CAAC;IAErB,OAAO,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AACvE,CAAC"}
\ No newline at end of file
diff --git a/plans/timeout_plan.fmf b/plans/timeout_plan.fmf
new file mode 100644
index 0000000..094e1b3
--- /dev/null
+++ b/plans/timeout_plan.fmf
@@ -0,0 +1,10 @@
+summary: Basic timeout test
+execute:
+ how: tmt
+ duration: 10s
+ script: |
+ set +x
+ echo "Set sleep time to an hour for sure."
+ sleep 30
+ echo "this should never happened because of timeout"
+ exit 0