Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 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
20 changes: 18 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,21 @@ inputs:
required: false
default: ''
unittest_dependencies:
description: 'List of bundle items to use as unittest dependencies.'
description: '(Deprecated) use test_dependencies+test_strategy instead. This option forces test strategy to be ALL.'
required: false
default: ''
test_dependencies:
description: 'Build bundle dependencies used for tests.'
required: false
default: ''
test_strategy:
description: |
The strategy used for building and running tests. May be ALL, INTEGRATION, or UNIT.
- INTEGRATION: The bundle is trimmed to only include the test_dependencies all tests are run.
- UNIT: The bundle is trimmed to only include the test_dependencies and unit tests are run.
- ALL: A 2-stage build is performed with the first step using the
test_dependencies to build the unit tests and the second step
building the full bundle for integration tests.
required: false
default: ''
self_test:
Expand All @@ -57,8 +71,10 @@ runs:
TARGET_REPO_DIR: ${{ inputs.target_repo_dir }}
BUNDLE_REPOSITORY: ${{ inputs.bundle_repository }}
CI_SELF_TEST: ${{ inputs.self_test }}
UNITTEST_BUNDLE_DEPENDENCIES: ${{ inputs.unittest_dependencies }}
JEDI_CI_TOKEN: ${{ inputs.jedi_ci_token }}
UNITTEST_DEPENDENCIES: ${{ inputs.unittest_dependencies }}
TEST_DEPENDENCIES: ${{ inputs.test_dependencies }}
TEST_STRATEGY: ${{ inputs.test_strategy }}

branding:
icon: 'play'
Expand Down
60 changes: 38 additions & 22 deletions ci_action/implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,24 +148,28 @@ def prepare_and_launch_ci_test(
# Move the original bundle file to the original file.
shutil.move(bundle_file, bundle_original)

# Rewrite the bundle cmake file twice
# First, rewrite the unit test bundle file with the build group commit hashes
test_dependencies = config['test_dependencies']
test_strategy = config['test_strategy']

# Rewrite the bundle cmake file with the selected projects for the first build stage.
with open(bundle_file_unittest, 'w') as f:
enabled_bundles = set(config['unittest_dependencies'] + [config['target_project_name']])
bundle.rewrite_build_group_whitelist(
file_object=f,
enabled_bundles=enabled_bundles,
build_group_commit_map=repo_to_commit_hash,
)

# Create an integration test file.
with open(bundle_integration, 'w') as f:
bundle.rewrite_build_group_blacklist(
file_object=f,
disabled_bundles=set(),
enabled_bundles=test_dependencies,
build_group_commit_map=repo_to_commit_hash,
)
LOG.info(f'{timer.checkpoint()}\n Rewrote bundle for build groups.')
LOG.info(f'{timer.checkpoint()}\n Wrote CMakeLists file with '
f'bundles: {test_dependencies}.')

# Create an integration test bundle definition if necessary.
if test_strategy == 'all':
with open(bundle_integration, 'w') as f:
bundle.rewrite_build_group_blacklist(
file_object=f,
disabled_bundles=set(),
build_group_commit_map=repo_to_commit_hash,
)
LOG.info(f'{timer.checkpoint()}\n Wrote second CMakeLists file with bundles.')

# Add resources to the bundle by copying all files in /app/shell to jedi_ci_resources
shutil.copytree(
Expand Down Expand Up @@ -244,12 +248,24 @@ def prepare_and_launch_ci_test(

# write the test github check runs to the PR.
for build_environment in chosen_build_environments:
checkrun_id_map = github_client.create_check_runs(
build_environment,
config['repo_name'],
config['owner'],
config['trigger_commit'],
test_annotations.next_ci_suffix)
integration_run_id = 0
unit_run_id = 0
if test_strategy in ('all', 'unit'):
unit_run_id = github_client.create_check_run(
github_client.UNIT_TEST_PREFIX,
build_environment,
config['repo_name'],
config['owner'],
config['trigger_commit'],
test_annotations.next_ci_suffix)
if test_strategy in ('all', 'integration'):
integration_run_id = github_client.create_check_run(
github_client.INTEGRATION_TEST_PREFIX,
build_environment,
config['repo_name'],
config['owner'],
config['trigger_commit'],
test_annotations.next_ci_suffix)
LOG.info(f'{timer.checkpoint()}\nCreated check runs for {build_environment}.')

# Note checkrun_id_map is dict {'unit': unit_run.id, 'integration': integration_run.id}
Expand Down Expand Up @@ -277,9 +293,9 @@ def prepare_and_launch_ci_test(
unittest_tag=config['unittest_tag'],
trigger_sha=config['trigger_commit'],
trigger_pr=str(config['pull_request_number']),
integration_run_id=checkrun_id_map['integration'],
unit_run_id=checkrun_id_map['unit'],
unittest_dependencies=' '.join(config['unittest_dependencies']),
integration_run_id=integration_run_id,
unit_run_id=unit_run_id,
unittest_dependencies=' '.join(test_dependencies),
test_script=config['test_script'],
)
job_arn = job['jobArn']
Expand Down
22 changes: 8 additions & 14 deletions ci_action/library/github_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,11 @@ def cancel_prior_unfinished_check_runs(repo, owner, pr_number, history_limit=20)
return github_app.cancel_prior_unfinished_check_runs(repo, owner, pr_number, history_limit)


def create_check_runs(build_environment, repo, owner, trigger_commit, next_suffix):
"""Create check runs (unit and integration) for a given build environment.
def create_check_run(prefix, build_environment, repo, owner, trigger_commit, next_suffix):
"""Create check run for a given build environment.

Args:
prefix: the prefix of the check run name.
build_environment: intel, gcc, or gcc11 (or any other supported build
environment).
repo: The name of the repository.
Expand All @@ -185,21 +186,14 @@ def create_check_runs(build_environment, repo, owner, trigger_commit, next_suffi
pre-release test images in the job name.

Returns:
Struct of check run ID's.
{
"integration": 14645415163,
"unit": 14645415264,
}
The run ID of the new check run.
"""
build_environment_name = build_environment + next_suffix
github_app = GitHubAppClientManager.init_from_environment()
unit_run_name = f'{UNIT_TEST_PREFIX}: {build_environment_name}'
integration_run_name = f'{INTEGRATION_TEST_PREFIX}: {build_environment_name}'
unit_run = github_app.create_check_run(
repo, owner, trigger_commit, unit_run_name)
integration_run = github_app.create_check_run(
repo, owner, trigger_commit, integration_run_name)
return {'unit': unit_run.id, 'integration': integration_run.id}
run_name = f'{prefix}: {build_environment_name}'
run = github_app.create_check_run(
repo, owner, trigger_commit, run_name)
return run.id


@lru_cache(maxsize=1)
Expand Down
39 changes: 31 additions & 8 deletions ci_action/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,18 +103,32 @@ def get_environment_config():
self_test = os.environ.get('CI_SELF_TEST', 'false').lower() == 'true'
test_script = os.environ.get('TEST_SCRIPT', 'run_tests.sh')

# Test dependencies as bundle items
test_deps = [d.strip() for d in os.environ.get('UNITTEST_BUNDLE_DEPENDENCIES', '').split(' ')]
filtered_test_deps = []
for td in test_deps:
if td:
filtered_test_deps.append(td)

# Get the target project name. If not passed explicitly, use the repo name.
target_project_name = os.environ.get('TARGET_PROJECT_NAME', '')
if not target_project_name.strip():
target_project_name = repo_name

# Collect the test dependencies from the environment variables.
unittest_deps_env = os.environ.get('UNITTEST_DEPENDENCIES', '').strip()
unittest_deps = [d.strip() for d in unittest_deps_env.split(' ') if d.strip()]
test_deps_env = os.environ.get('TEST_DEPENDENCIES', '').strip()
test_deps = [d.strip() for d in test_deps_env.split(' ') if d.strip()]

test_strategy = os.environ.get('TEST_STRATEGY', 'all').lower()
if test_strategy not in ['all', 'integration', 'unit']:
raise ValueError('Option "test_strategy" must be one of "ALL", "INTEGRATION", or "UNIT".')

# Handle deprecated config option 'unittest_dependencies'.
if test_deps and unittest_deps:
raise ValueError('Config option "unittest_dependencies" and '
'"test_dependencies" cannot be set simultaneously.')
elif unittest_deps:
test_deps = unittest_deps
test_strategy = 'all'

# Ensure that the test dependencies include the target project.
test_deps = [d for d in set(test_deps + [target_project_name])]

config = {
'repository': repository,
'owner': owner,
Expand All @@ -129,7 +143,8 @@ def get_environment_config():
'bundle_branch': default_bundle_branch,
'bundle_repository': bundle_repository,
'self_test': self_test,
'unittest_dependencies': filtered_test_deps,
'test_dependencies': test_deps,
'test_strategy': test_strategy,
'unittest_tag': test_tag,
'test_script': test_script,
'target_project_name': target_project_name,
Expand Down Expand Up @@ -189,6 +204,14 @@ def main():
# Enumerate and indent each error message.
enumerated_errors = [f' {i+1}. ' + str(e) for i, e in enumerate(non_blocking_errors)]
error_list = '\n'.join(enumerated_errors)
LOG.error(f"Tests could not launch due to these errors:\n{error_list}")
return 1

if non_blocking_errors:
# Enumerate and indent each error message.
indented_errors = [textwrap.indent(e, ' ') for e in non_blocking_errors]
enumerated_errors = [f' {i+1}. ' + e[4:] for i, e in enumerate(indented_errors)]
error_list = '\n'.join(enumerated_errors)
LOG.error(f"Tests launched successfully but experienced errors:\n{error_list}")
return 1

Expand Down
Loading
Loading