From 90dd015618309aa189348eb13859e0e2e5ef6ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dennis=20Gl=C3=A4ser?= <dennis.glaeser@iws.uni-stuttgart.de> Date: Mon, 31 May 2021 09:53:26 +0200 Subject: [PATCH] [ci][getpipelineinfo] allow exlusion of pls with certain jobs --- .gitlab-ci.yml | 6 +-- .gitlab-ci/default.yml | 9 ++-- .gitlab-ci/getpipelineinfo.py | 82 +++++++++++++++++++++++++++-------- 3 files changed, 68 insertions(+), 29 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bd9e089373..92b668c017 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,11 +30,7 @@ check-pipeline-status: when: always script: - | - curl --header "token=$CI_JOB_TOKEN" \ - "https://git.iws.uni-stuttgart.de/api/v4/projects/31/pipelines/?status=success" \ - > pipeline_status.json - - | - if ! python3 .gitlab-ci/getpipelineinfo.py --status-file pipeline_status.json \ + if ! python3 .gitlab-ci/getpipelineinfo.py --access-token $CI_JOB_TOKEN \ --look-for HEAD \ --print-format pipeline-id; then echo "No successful pipeline found. Triggering new pipeline..." diff --git a/.gitlab-ci/default.yml b/.gitlab-ci/default.yml index 71ddf0f1d3..9d3183db81 100644 --- a/.gitlab-ci/default.yml +++ b/.gitlab-ci/default.yml @@ -23,7 +23,7 @@ select tests: - | getLastSuccesful() { python3 .gitlab-ci/getpipelineinfo.py \ - --status-file $1 \ + --access-token $CI_JOB_TOKEN \ --look-for latest \ --print-format commit-sha } @@ -43,15 +43,12 @@ select tests: elif [ -n $TEST_AGAINST_LAST_SUCCESSFUL ]; then echo "Determining sha of the last successful pipeline to test against" - curl --header "token=$CI_JOB_TOKEN" \ - "https://git.iws.uni-stuttgart.de/api/v4/projects/31/pipelines/?status=success" \ - > pipeline_status.json - if ! getLastSuccesful pipeline_status.json; then + if ! getLastSuccesful; then echo "Could not find a successful pipeline, will build/run all tests" touch affectedtests.json else - COMMIT_SHA=$(getLastSuccesful pipeline_status.json) + COMMIT_SHA=$(getLastSuccesful) echo "Comparing against sha $COMMIT_SHA" python3 bin/testing/getchangedfiles.py --outfile changedfiles.txt \ --source-tree HEAD \ diff --git a/.gitlab-ci/getpipelineinfo.py b/.gitlab-ci/getpipelineinfo.py index 498f25b994..ec59a08633 100644 --- a/.gitlab-ci/getpipelineinfo.py +++ b/.gitlab-ci/getpipelineinfo.py @@ -11,11 +11,36 @@ except Exception: sys.exit('Could not import common module') -def findPipeline(pipelineFile, predicate): - with open(pipelineFile) as pipeLines: - for pipeLine in json.load(pipeLines): - if predicate(pipeLine): - return pipeLine +def performApiQuery(command, err='API query unsuccessful'): + return runCommand(command, suppressTraceBack=True, errorMessage=err) + + +def getPipeLinesApiURL(apiURL): + return apiURL.rstrip('/') + '/pipelines/' + + +def getPipelines(apiURL, token, filter=''): + queryURL = getPipeLinesApiURL(apiURL) + filter + queryCmd = 'curl --header "token={}" "{}"'.format(token, queryURL) + pl = performApiQuery(queryCmd, 'Could not retrieve pipelines') + return json.loads(pl) + + +def getPipelineInfo(apiURL, token, pipeLineId, infoString): + queryURL = getPipeLinesApiURL(apiURL) + str(pipeLineId) + '/' + infoString + queryCmd = 'curl --header "token={}" "{}"'.format(token, queryURL) + pl = performApiQuery(queryCmd, 'Could not retrieve pipeline info') + return json.loads(pl) + + +def getPipeLineJobs(apiURL, token, pipeLineId): + return getPipelineInfo(apiURL, token, pipeLineId, 'jobs') + + +def findPipeline(pipeLines, predicate): + for pipeLine in pipeLines: + if predicate(pipeLine): + return pipeLine return None @@ -23,20 +48,32 @@ parser = ArgumentParser( description='Find and print information on a previously run pipeline' ) -parser.add_argument('-s', '--status', - required=False, default='success', - help='Define the status of the pipeline to be found') parser.add_argument('-p', '--print-format', required=True, choices=['pipeline-id', 'commit-sha'], help='Switch between reporting the pipeline-id/commit-sha') parser.add_argument('-l', '--look-for', required=True, choices=['latest', 'HEAD'], help='Define how to search for pipelines') -parser.add_argument('-f', '--status-file', +parser.add_argument('-t', '--access-token', required=True, - help='The .json file with the latest pipeline statuses') + help='The token to post read requests to the GitLab API') +parser.add_argument('-u', '--project-api-url', + required=False, + default='https://git.iws.uni-stuttgart.de/api/v4/projects/31/', + help='The token to post read requests to the GitLab API') +parser.add_argument('-f', '--filter', + required=False, default='?status=success', + help='Pipeline query filter (default: "?status=success"') +parser.add_argument('-e', '--exclude-jobs', + required=False, nargs='*', + default=['check-pipeline-status'], + help='Exclude pipelines that contain the given jobs') args = vars(parser.parse_args()) +apiURL = args['project_api_url'] +token = args['access_token'] +pipeLines = getPipelines(apiURL, token, args['filter']) + currentBranch = runCommand('git branch --show-current').strip('\n') currentCommitInfo = runCommand('git show HEAD').split('\n') headIsMergeCommit = 'Merge:' in currentCommitInfo[1] @@ -44,25 +81,34 @@ headIsMergeCommit = 'Merge:' in currentCommitInfo[1] headSHA = runCommand('git rev-list HEAD --max-count=1').strip('\n') if headIsMergeCommit: preSHA = runCommand('git rev-list HEAD --max-count=2').split('\n')[1] - mrSha = currentCommitInfo[1].split()[2] + mrSHA = currentCommitInfo[1].split()[2] + + +def checkBranch(pipeLine): + return pipeLine['ref'] == currentBranch -def checkCommitSHA(pipeLine): +def checkCommit(pipeLine): sha = pipeLine['sha'] if headIsMergeCommit: - return sha == headSHA or sha == preSHA or mrSha in sha + return sha == headSHA or sha == preSHA or mrSHA in sha return sha == headSHA -def checkStatus(pipeLine): return pipeLine['status'] == args['status'] -def checkBranch(pipeLine): return pipeLine['ref'] == currentBranch -def find(predicate): return findPipeline(args['status_file'], predicate) +def skip(pipeLine): + jobs = getPipeLineJobs(apiURL, token, pipeLine['id']) + jobNames = [j['name'] for j in jobs] + return any(j in jobNames for j in args['exclude_jobs']) if args['look_for'] == 'HEAD': - pipeLine = find(lambda p: checkStatus(p) and checkCommitSHA(p)) + pipeLine = findPipeline( + pipeLines, lambda p: checkCommit(p) and not skip(p) + ) elif args['look_for'] == 'latest': - pipeLine = find(lambda p: checkStatus(p) and checkBranch(p)) + pipeLine = findPipeline( + pipeLines, lambda p: checkBranch(p) and not skip(p) + ) if pipeLine is not None: if args['print_format'] == 'pipeline-id': -- GitLab