Skip to content
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
2 changes: 1 addition & 1 deletion .gitlab/config/dynamic_pipeline.yml.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ child_pipeline_{branch}:
include:
- project: 'ci/ums029/dev/adios2'
ref: '{branch}'
file: '.gitlab/gitlab-ci-crusher.yml'
file: '.gitlab/gitlab-ci-frontier.yml'
112 changes: 72 additions & 40 deletions .gitlab/config/generate_pipelines.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
import time
import re
import urllib3
import git
import gitdb

# Remove annoying warning about insecure connection (self-signed cert).
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

Expand All @@ -35,7 +38,7 @@ def __call__(self, fn, *args, **kwargs):


def http_get_request(*args, **kwargs):
kwargs['verify'] = False
kwargs["verify"] = False
return requests.get(*args, **kwargs)


Expand All @@ -48,95 +51,124 @@ def request_as_list(url, *args, **kwargs):

header = response.headers
current_url = None
if 'link' in header:
if "link" in header:
links = re.search(
r'(?<=\<)([\S]*)(?=>; rel="next")', header['link'], flags=re.IGNORECASE)
r'(?<=\<)([\S]*)(?=>; rel="next")', header["link"], flags=re.IGNORECASE
)
if links is not None:
current_url = links.group(0)

return body_json


def add_timestamp(branch):
date_str = branch['commit']['committed_date']
date_str = branch["commit"]["committed_date"]
# We ignore the TZ since Gitlab/GitHub always reports in UTC
branch['dt'] = int(
datetime.strptime(date_str.split(".")[0],
'%Y-%m-%dT%H:%M:%S').timestamp())
branch["dt"] = int(datetime.strptime(date_str.split(".")[0], "%Y-%m-%dT%H:%M:%S").timestamp())
return branch


def is_descendant_of_root(branch, root_commit, repo):
if root_commit is None:
return True
try:
commit_sha = branch["commit"]["id"]
repo.commit(commit_sha)
merge_base = repo.merge_base(args.root_commit, commit_sha)
if len(merge_base) >= 1 and str(merge_base[0]) == args.root_commit:
return True
except gitdb.exc.BadObject:
return False


def is_recent(branch):
deadline_sec = int(time.time()) - (args.days * 86400)
return branch['dt'] > deadline_sec
return branch["dt"] > deadline_sec


def has_no_status(branch):
gh_commit_sha = branch['commit']['id']
gh_commit_sha = branch["commit"]["id"]
# Backported branches use the merge head
if re.fullmatch(r'^pr\d+_.*$', branch['name']):
gh_commit_sha = branch['commit']['parent_ids'][1]
if re.fullmatch(r"^pr\d+_.*$", branch["name"]):
gh_commit_sha = branch["commit"]["parent_ids"][1]

# Query GitHub for the status of this commit
response = http_get_request(
gh_url + '/commits/' + gh_commit_sha + '/status')
if int(response.headers['x-ratelimit-remaining']) <= 0:
response = http_get_request(gh_url + "/commits/" + gh_commit_sha + "/status")
if int(response.headers["x-ratelimit-remaining"]) <= 0:
raise ConnectionError(response.json())

commit = response.json()
if commit is None or 'sha' not in commit:
if commit is None or "sha" not in commit:
return False

for status in commit['statuses']:
if status['context'] == args.gh_context:
for status in commit["statuses"]:
if status["context"] == args.gh_context:
return False

return True


parser = argparse.ArgumentParser(
prog='generate_pipeline.py',
description='Generate Dynamic pipelines for Gitlab')
prog="generate_pipeline.py", description="Generate Dynamic pipelines for Gitlab"
)
parser.add_argument(
"-u",
"--gl-url",
required=True,
help="Base URL for Gitlab remote. Ex: https://code.olcf.ornl.gov/",
)
parser.add_argument(
'-u', '--gl-url', required=True,
help='Base URL for Gitlab remote. Ex: https://code.olcf.ornl.gov/')
"-n", "--gh-name", required=True, help="Full name of the GitHub project. Ex: ornladios/ADIOS2"
)
parser.add_argument(
'-n', '--gh-name', required=True,
help='Full name of the GitHub project. Ex: ornladios/ADIOS2')
"-p", "--project_id", required=True, help="Gitlab internal project ID of the project."
)
parser.add_argument(
'-p', '--project_id', required=True,
help='Gitlab internal project ID of the project.')
"-c",
"--gh-context",
default="OLCF Frontier",
help="Name of the status in GitHub (A.K.A context)",
)
parser.add_argument(
'-c', '--gh-context', default='OLCF Crusher (Frontier)',
help='Name of the status in GitHub (A.K.A context)')
"-d", "--days", type=int, default=1, help="How many days back to search for commits"
)
parser.add_argument(
'-d', '--days', type=int, default=1,
help='How many days back to search for commits')
"-m", "--max", type=int, default=2, help="Maximum amount of pipelines computed"
)
parser.add_argument(
'-m', '--max', type=int, default=2,
help='Maximum amount of pipelines computed')
"-r",
"--root-commit",
default=None,
type=str,
help="Template file of the pipeline `{branch}` will be substituted",
)
parser.add_argument(
'-f', '--template_file', required=True,
help='Template file of the pipeline `{branch}` will be substituted')
"-f",
"--template_file",
required=True,
help="Template file of the pipeline `{branch}` will be substituted",
)
args = parser.parse_args()


gl_url = args.gl_url + '/api/v4/projects/' + str(args.project_id)
gh_url = 'https://api.github.com/repos/' + args.gh_name
gl_url = args.gl_url + "/api/v4/projects/" + str(args.project_id)
gh_url = "https://api.github.com/repos/" + args.gh_name

with open(args.template_file, 'r') as fd:
with open(args.template_file, "r") as fd:
template_str = fd.read()

branches = request_as_list(gl_url + '/repository/branches')
repo = git.Repo(".", odbt=git.GitDB)

branches = request_as_list(gl_url + "/repository/branches")
branches = [b for b in branches if is_descendant_of_root(b, args.root_commit, repo)]
branches = [add_timestamp(branch) for branch in branches]
branches = [b for b in branches if is_recent(b)]
branches = sorted(branches, key=lambda x: x['dt'])
branches = sorted(branches, key=lambda x: x["dt"])

# Skip running (and return true) has_no_status after returning True args.max times.
# We need this not to hog the Github Rest API draconian ratelimit.
run_n_times = skip_after_n_successes(default_value=False, n=args.max)
branches = [b for b in branches if run_n_times(has_no_status, b)]

for branch in branches:
print(template_str.format(
branch=branch['name'], commit=branch['commit']['id']))
print(template_str.format(branch=branch["name"], commit=branch["commit"]["id"]))
52 changes: 34 additions & 18 deletions .gitlab/gitlab-ci-frontier.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ad-hoc build that runs in the ECP Hardware, concretely in OLCF Crusher.
# Ad-hoc build that runs in the ECP Hardware, concretely in OLCF Frontier.

stages:
- pre
Expand All @@ -23,13 +23,17 @@ stages:
ccache -s

.frontier-common:
variables:
CUSTOM_CI_BUILDS_DIR: "/lustre/orion/ums029/scratch/ums029_auser/ci/adios2/runtime"
OLCF_SERVICE_ACCOUNT: "ums029_auser"

.frontier-cmake-common:
rules:
- if: $CI_PIPELINE_SOURCE =~ /parent_pipeline|web/
interruptible: true
variables:
CCACHE_BASEDIR: "/lustre/orion/ums029/scratch/"
CCACHE_DIR: "/lustre/orion/ums029/scratch/ums029_auser/ci/adios2/ccache"
CUSTOM_CI_BUILDS_DIR: "/lustre/orion/ums029/scratch/ums029_auser/ci/adios2/runtime"

# -isystem= is not affected by CCACHE_BASEDIR, thus we must ignore it
CCACHE_IGNOREOPTIONS: "-isystem=*"
Expand All @@ -42,9 +46,11 @@ stages:

# We do not want to use the user's ~/.gitconfig
GIT_CONFIG_GLOBAL: "true"
GITLAB_SITE: "OLCF Crusher"
GITLAB_SITE: "OLCF Frontier"
CI_BIN_DIR: "$CI_PROJECT_DIR/build"
OLCF_SERVICE_ACCOUNT: "ums029_auser"

extends:
.frontier-common

.setup-common:
stage: setup
Expand Down Expand Up @@ -105,7 +111,7 @@ setup:frontier-kokkos-hip:
-DKokkos_ENABLE_HIP_RELOCATABLE_DEVICE_CODE:BOOL=OFF
-DKokkos_ENABLE_SERIAL:BOOL=ON
extends:
- .frontier-common
- .frontier-cmake-common
- .setup-common
- .kokkos-hip-common
before_script:
Expand All @@ -115,7 +121,7 @@ setup:frontier-kokkos-hip:

build:frontier-kokkos-hip:
extends:
- .frontier-common
- .frontier-cmake-common
- .build-common
- .kokkos-hip-common
before_script:
Expand All @@ -137,7 +143,7 @@ build:frontier-kokkos-hip:
zstd
DefApps
extends:
- .frontier-common
- .frontier-cmake-common

setup:frontier-cray:
extends:
Expand All @@ -157,10 +163,11 @@ build:frontier-cray:
rules:
- if: $CI_PIPELINE_SOURCE =~ /parent_pipeline|web/
tags: [ shell ]
extends:
.frontier-common
variables:
STATUS_PROJECT: ornladios/ADIOS2
STATUS_NAME: OLCF Crusher (Frontier)
OLCF_SERVICE_ACCOUNT: "ums029_auser"
STATUS_NAME: OLCF Frontier
before_script: |
git fetch
source scripts/ci/gitlab-ci/setup-vars.sh
Expand All @@ -176,14 +183,12 @@ pending:
stage: pre
variables:
STATUS_DESC: Pipeline is running
OLCF_SERVICE_ACCOUNT: "ums029_auser"
extends:
- .report-status
success:
stage: post
variables:
STATUS_DESC: Pipeline succeeded
OLCF_SERVICE_ACCOUNT: "ums029_auser"
extends:
- .report-status
dependencies:
Expand All @@ -196,7 +201,6 @@ failure:
when: on_failure
variables:
STATUS_DESC: Pipeline failed
OLCF_SERVICE_ACCOUNT: "ums029_auser"
extends:
- .report-status
dependencies:
Expand All @@ -205,25 +209,37 @@ failure:

generate_pipelines:
stage: setup
extends:
.frontier-common
tags: [frontier, shell]
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
variables:
CUSTOM_CI_BUILDS_DIR: "/lustre/orion/ums029/scratch/ums029_auser/ci/adios2/runtime"
OLCF_SERVICE_ACCOUNT: "ums029_auser"
GL_PROJECT_ID: 105
# This the commit where the frontier CI was added, we want to avoid testing
# commits before this.
ROOT_COMMIT_SHA: 30368427fc41d57e428cdd15e7629dded2f71728
script:
- .gitlab/config/generate_pipelines.py -u "https://code.olcf.ornl.gov/" -p 105 -n ornladios/ADIOS2 -f .gitlab/config/dynamic_pipeline.yml.in > generated_pipelines.yml
- pip install --user urllib3 requests GitPython
- >
.gitlab/config/generate_pipelines.py
-u "https://code.olcf.ornl.gov/"
-r "${ROOT_COMMIT_SHA}"
-p "${GL_PROJECT_ID}"
-n ornladios/ADIOS2
-f .gitlab/config/dynamic_pipeline.yml.in
> generated_pipelines.yml

artifacts:
paths:
- generated_pipelines.yml

launch_pipelines:
stage: build
extends:
.frontier-common
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
variables:
CUSTOM_CI_BUILDS_DIR: "/lustre/orion/ums029/scratch/ums029_auser/ci/adios2/runtime"
OLCF_SERVICE_ACCOUNT: "ums029_auser"
trigger:
include:
- artifact: generated_pipelines.yml
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci/gitlab-ci/setup-vars.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ else
export CI_BRANCH_REF="${DOWNSTREAM_BRANCH_REF}"
fi

# In OLCF Crusher we must fix the build directory in the yml.
# In OLCF Frontier we must fix the build directory in the yml.
if [ -z "$CI_BIN_DIR" ]
then
export CI_BIN_DIR="${CI_ROOT_DIR}/${CI_BUILD_NAME}"
Expand Down