Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
dbb07d7
feat(ci): add automatic e2e tests
nevermarine Apr 2, 2025
0eda30e
change pull_request_target to pull_request
nevermarine Apr 2, 2025
4806728
change token name
nevermarine Apr 2, 2025
0b2a217
add time
nevermarine Apr 2, 2025
35e68fd
verbosity=3
nevermarine Apr 2, 2025
41d428b
move time
nevermarine Apr 2, 2025
a39fb62
remove double d8 install
nevermarine Apr 2, 2025
8f13b9d
add setup
nevermarine Apr 2, 2025
df2f3f4
remove locals
nevermarine Apr 2, 2025
cb77d9d
fix arithmetic
nevermarine Apr 2, 2025
c969980
add bash
nevermarine Apr 3, 2025
53a492a
comment out crane
nevermarine Apr 3, 2025
9e900be
fix var
nevermarine Apr 3, 2025
4b0afef
set context via js
nevermarine Apr 4, 2025
830ecd0
require fs
nevermarine Apr 4, 2025
1debbf1
remove string
nevermarine Apr 4, 2025
4016653
add path
nevermarine Apr 4, 2025
ed2af36
change task
nevermarine Apr 6, 2025
0129476
move e2e to build stage
nevermarine Apr 7, 2025
c9beb68
format yaml
nevermarine Apr 7, 2025
bc072a5
change runner
nevermarine Apr 7, 2025
35dbae6
add cleanup
nevermarine Apr 7, 2025
34f308a
return regexpLogFilter
nevermarine Apr 7, 2025
6673ab1
set runs-on: ubuntu-latest & remove comments
nevermarine Apr 7, 2025
eea9cc8
change order of resource cleanup
nevermarine Apr 7, 2025
b0d79a5
chore
nevermarine Apr 7, 2025
8a44fe3
fix condition
nevermarine Apr 8, 2025
7f0eed8
add project cleanup
nevermarine Apr 8, 2025
0d16b90
add user cluster labels
nevermarine Apr 8, 2025
60a7f2a
run e2e only on pull requests
nevermarine Apr 8, 2025
ad228d0
fix cleanup failing on missing resources
nevermarine Apr 8, 2025
e55b87a
remove comments
nevermarine Apr 8, 2025
295ffda
cleanup constants & move to vars.USER_CLUSTER_LABELS
nevermarine Apr 8, 2025
aa57d4b
add error handling for user cluster labels
nevermarine Apr 9, 2025
5c2c94b
remove old code
nevermarine Apr 10, 2025
9811830
refactor cleanup
nevermarine Apr 10, 2025
fef17e2
move checkout to mpo to Taskfile
nevermarine Apr 10, 2025
ebebdcd
remove unnecessary continue
nevermarine Apr 10, 2025
897cff0
add label removal
nevermarine Apr 10, 2025
66a1d0b
format yaml
nevermarine Apr 10, 2025
19f66d1
format yaml 2
nevermarine Apr 10, 2025
b69ea0e
add deckhouse_ready_status check
nevermarine Apr 10, 2025
89ce205
add working dir to checkout-to-mpo
nevermarine Apr 10, 2025
00e0651
modify `update comment on finish` task
nevermarine Apr 10, 2025
dad836e
move if back
nevermarine Apr 10, 2025
8917517
remove label
nevermarine Apr 10, 2025
271c1b0
remove unnecessary code
nevermarine Apr 10, 2025
bfc1b0a
remove run on unlabeled PR
nevermarine Apr 10, 2025
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
23 changes: 23 additions & 0 deletions .github/scripts/js/ci.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ const reactToComment = async ({github, context, comment_id, content}) => {
});
};
module.exports.reactToComment = reactToComment;

const checkUserClusterLabel = async ({prLabels, userClusterLabels}) => {
const userLabelsInPR = prLabels
.map(label => label.name)
.filter(labelName => userClusterLabels[labelName]);
return userLabelsInPR;
};
module.exports.checkUserClusterLabel = checkUserClusterLabel;

const getClusterUser = async ({context, core, userClusterLabels}) => {
const prLabels = context.payload.pull_request.labels;
let userLabelsInPR = await checkUserClusterLabel({prLabels, userClusterLabels});
if (userLabelsInPR.length === 0) {
core.info('No user labels found in PR, using PR author\'s cluster');
const prAuthorId = context.payload.pull_request.user.id;
core.info(`PR author: ${prAuthorId}`);
return prAuthorId.toString();
} else if (userLabelsInPR.length > 1) {
return core.setFailed(`Error: PR has multiple user labels: ${userLabelsInPR.join(', ')}`);
}
return userClusterLabels[userLabelsInPR].id
};
module.exports.getClusterUser = getClusterUser;

/**
* Start workflow using workflow_dispatch event.
Expand Down
25 changes: 25 additions & 0 deletions .github/scripts/js/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright 2022 Flant JSC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//@ts-check

const skipE2eLabel = 'skip/e2e';
module.exports.skipE2eLabel = skipE2eLabel;

// Labels available for pull requests.
const labels = {
// E2E
'e2e/run': { type: 'e2e-run', provider: 'static' },
// Allow running workflows for external PRs.
'status/ok-to-test': { type: 'ok-to-test' },

};
module.exports.knownLabels = labels;
264 changes: 264 additions & 0 deletions .github/scripts/js/e2e-commit-status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
// Copyright 2022 Flant JSC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const {
sleep
} = require('./time');

/**
* Build workflow run url for add it to commit status target url
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @returns string
*/
function workflowUrl({core, context}) {
core.debug(`workflowUrl context: ${JSON.stringify(context)}`);
const {serverUrl, repo, runId} = context;
const repository = repo.repo;
const owner = repo.owner;
const url = `${serverUrl}/${owner}/${repository}/actions/runs/${runId}`;
core.debug(`workflowUrl url: ${url}`);
return url
}

/**
* Wrap github.rest.repos.createCommitStatus. Returns true if status was set
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {object} inputs.status - A state object for send
* @param {string} inputs.status.state - A state type as 'success' (it is mark in GitHub ui)
* @param {string} inputs.status.description - A description for commit status
* @param {string|undefined} inputs.status.url - A target url for commit status (Details link in GitHub ui)
* @param {string} inputs.status.commitSha - A commit for set status
* @returns Promise<bool>
*/
async function sendCreateCommitStatus({github, context, core, status}) {
const {state, description, url, commitSha} = status
core.debug(`sendCreateCommitStatus target commit: ${commitSha}`);

for(let i = 0; i < 3; i++) {
const response = await github.rest.repos.createCommitStatus({
owner: context.repo.owner,
repo: context.repo.repo,
sha: commitSha,
state: state,
description: description,
target_url: url,
context: 'E2e test'
});

core.debug(`rest.repos.createCommitStatus response: ${JSON.stringify(response)}`);
if (response.status === 201) {
core.debug(`rest.repos.createCommitStatus response status is 201. Returns true`);
return true;
}

// wait 3s for retry request
await sleep(3000);
}

return false
}

/**
* Set `waiting for start e2e` status (pending) Uses with push commit
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {string} inputs.commitSha - sha commit for set status
* @returns Promise<bool>
*/
async function setWait ({github, context, core, commitSha}) {
return sendCreateCommitStatus({
github,
context,
core,
status: {
commitSha,
state: 'pending',
description: 'Waiting for run e2e test'
}
})
}

/**
* Set `e2e was failed` status (failed) when e2e was failed
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {string} inputs.commitSha - sha commit for set status
* @returns Promise<bool>
*/
async function setFail({github, context, core, commitSha}){
return sendCreateCommitStatus({
github,
context,
core,
status: {
commitSha,
state: 'failure',
description: 'E2e test was failed',
url: workflowUrl({core, context}),
}
})
}

/**
* Set `e2e was passed` status (failed) when e2e was failed
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {string} inputs.commitSha - sha commit for set status
* @returns Promise<bool>
*/
function setSuccess ({github, context, core, commitSha}) {
return sendCreateCommitStatus({
github,
context,
core,
status: {
commitSha,
state: 'success',
description: 'E2e test was passed',
url: workflowUrl({core, context}),
}
})
}

/**
* Set `e2e was failed` status (success) when e2e was failed
* Unfortunately we do not have 'skip' status and use 'success'
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {string} inputs.commitSha - sha commit for set status
* @returns Promise<bool>
*/
async function setSkip({github, context, core, commitSha}){
return sendCreateCommitStatus({
github,
context,
core,
status: {
commitSha,
state: 'success',
description: 'E2e test was skipped',
},
})
}

/**
* Set commit status when label set/unset.
* Check label for skipping e2e test and e2e tests should skip set success status
* If status was not set then fail job
*
* Used in build-and-test_dev workflow
*
* Use STATUS_TARGET_COMMIT env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @param {boolean} inputs.labeled - true - PR was labeled, false - unlabeled
* @param {string} inputs.commitSha - sha commit for set status
* @returns Promise<void>
*/
async function onLabeledForSkip({github, context, core, labeled, commitSha}) {
const statusSetFunc = (labeled) ? setSkip : setWait;

const done = await statusSetFunc({github, context, core, commitSha});
if (!done) {
core.setFailed('e2e requirement status was not set.');
}
}

/**
* Set commit status when commit was pushed.
* Check label for skipping e2e test and e2e tests should skip set success status
* If status was not set then fail job
*
* Used in e2e_run* workflow
*
* Use STATUS_TARGET_COMMIT env var as target commit sha
* Use STATUS_TARGET_COMMIT env var as job status
* Use env var as target commit sha
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @returns Promise<void>
*/
async function setStatusAfterE2eRun({github, context, core}) {
const jobStatus = process.env.JOB_STATUS;
const commitSha = process.env.STATUS_TARGET_COMMIT;

let setStateFunc = null;
if (jobStatus === 'failure' || jobStatus === 'cancelled') {
setStateFunc = setFail;
} else if (jobStatus === 'success') {
setStateFunc = await setSuccess;
} else {
core.setFailed(`e2e requirement status was not set. Job status ${jobStat}`)
return
}

const success = setStateFunc({github, context, core, commitSha})
if (!success) {
core.setFailed(`e2e requirement status was not set. Job status ${jobStat}`)
}
}

/**
* Set commit status when commit was pushed.
* Check label for skipping e2e test and e2e tests should skip set success status
* If status was not set then fail job
*
* Used in build-and-test_dev workflow
*
* Use STATUS_TARGET_COMMIT env var as target commit sha
* Use PR_LABELS env var as list of PR labels
* @param {object} inputs
* @param {object} inputs.core - A reference to the '@actions/core' package.
* @param {object} inputs.github - A pre-authenticated octokit/rest.js client with pagination plugins.
* @param {object} inputs.context - A reference to context https://github.com/actions/toolkit/blob/main/packages/github/src/context.ts#L6
* @returns Promise<void>
*/
async function setInitialStatus ({github, context, core}) {
core.info(`Labels json: ${process.env.PR_LABELS}`);

const labels = JSON.parse(process.env.PR_LABELS);
const commitSha = process.env.STATUS_TARGET_COMMIT;

core.debug(`Labels: ${labels ? JSON.stringify(labels.map((l) => l.name)) : 'no labels'}`);

const shouldSkip = labels ? labels.some((l) => l.name === "skip/e2e") : false;
core.debug(`Should skip e2e: ${shouldSkip}`);

return onLabeledForSkip({github, context, core, labeled: shouldSkip, commitSha})
}

module.exports = {
setStatusAfterE2eRun,
setInitialStatus,
onLabeledForSkip
}
14 changes: 14 additions & 0 deletions .github/scripts/js/time.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright 2022 Flant JSC
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

module.exports.sleep = async (ms) => {
return new Promise(resolve => setTimeout(resolve, ms))
}
Loading
Loading