From 7c5247a2575471a813ef758291d782903d041004 Mon Sep 17 00:00:00 2001 From: "Eric D. Helms" Date: Fri, 7 Apr 2023 16:36:31 -0400 Subject: [PATCH] Refactor Copr support into modules --- obal/data/module_utils/copr.py | 5 +- obal/data/modules/copr_build.py | 59 ++++++++ obal/data/modules/copr_build_info.py | 55 ++++++++ obal/data/modules/copr_chroot.py | 4 +- obal/data/modules/copr_fork.py | 59 ++++++++ obal/data/modules/copr_project.py | 14 +- .../data/playbooks/release/metadata.obal.yaml | 19 +++ .../data/playbooks/scratch/metadata.obal.yaml | 3 + .../roles/build_package/defaults/main.yaml | 3 + .../tasks/_copr_build_for_chroot.yaml | 0 obal/data/roles/build_package/tasks/copr.yml | 56 +------- .../roles/build_package/tasks/copr_build.yml | 127 ++++++++++++++++++ .../build_package/tasks/download_rpms.yml | 4 + .../tasks/download_rpms_copr.yml | 20 +++ obal/data/roles/build_package/tasks/wait.yml | 7 +- .../roles/copr_project/defaults/main.yaml | 1 + obal/data/roles/copr_project/tasks/main.yaml | 4 +- obal/data/roles/copr_repo/tasks/main.yml | 35 ++--- tests/fixtures/help/release.txt | 14 +- tests/fixtures/help/scratch.txt | 6 +- tests/fixtures/mockbin/mockbin | 56 +++++++- .../testrepo/copr/package_manifest.yaml | 19 +-- tests/test_functional.py | 32 ++--- 23 files changed, 490 insertions(+), 112 deletions(-) create mode 100644 obal/data/modules/copr_build.py create mode 100644 obal/data/modules/copr_build_info.py create mode 100644 obal/data/modules/copr_fork.py create mode 100644 obal/data/roles/build_package/tasks/_copr_build_for_chroot.yaml create mode 100644 obal/data/roles/build_package/tasks/copr_build.yml create mode 100644 obal/data/roles/build_package/tasks/download_rpms_copr.yml diff --git a/obal/data/module_utils/copr.py b/obal/data/module_utils/copr.py index 65ac77f9..deac0a50 100644 --- a/obal/data/module_utils/copr.py +++ b/obal/data/module_utils/copr.py @@ -10,13 +10,16 @@ def __init__(self, message, command): self.command = command super(CoprCliCommandError, self).__init__(message) #pylint: disable-all -def copr_cli(command, executable=None): +def copr_cli(command, executable=None, config_file=None): """ Run a copr-cli command """ if executable is None: executable = 'copr-cli' + if config_file: + command = ['--config', config_file] + command + try: return check_output([executable] + command, universal_newlines=True, stderr=STDOUT) except CalledProcessError as error: diff --git a/obal/data/modules/copr_build.py b/obal/data/modules/copr_build.py new file mode 100644 index 00000000..6b583c7c --- /dev/null +++ b/obal/data/modules/copr_build.py @@ -0,0 +1,59 @@ +""" +Release a package to Copr +""" + +import re + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.copr import copr_cli, CoprCliCommandError, full_name # pylint:disable=import-error,no-name-in-module + + +def main(): + """ + Release a package to Copr + """ + module = AnsibleModule( + argument_spec=dict( + user=dict(type='str', required=True), + project=dict(type='str', required=True), + srpm=dict(type='path', required=True), + wait=dict(type='bool', required=False, default=False), + chroots=dict(type='list', required=False), + config_file=dict(type='str', required=False), + ) + ) + + user = module.params['user'] + project = module.params['project'] + srpm = module.params['srpm'] + wait = module.params['wait'] + chroots = module.params['chroots'] + config_file = module.params['config_file'] + + command = [ + 'build', + full_name(user, project), + srpm + ] + + if not wait: + command.append('--nowait') + + if chroots: + for chroot in chroots: + command.extend(['--chroot', chroot]) + + try: + output = copr_cli(command, config_file=config_file) + except CoprCliCommandError as error: + module.fail_json(msg='Copr build failed', command=error.command, output=error.message, + repo_name=full_name(user, project), srpm=srpm) + + build_urls = re.findall(r'^Build was added to.+:\n^\s+(.+)\s*', output, re.MULTILINE) + builds = re.findall(r'^Created builds:\s(\d+)', output, re.MULTILINE) + + module.exit_json(changed=True, output=output, builds=builds, build_urls=build_urls) + + +if __name__ == '__main__': + main() diff --git a/obal/data/modules/copr_build_info.py b/obal/data/modules/copr_build_info.py new file mode 100644 index 00000000..8f9ec235 --- /dev/null +++ b/obal/data/modules/copr_build_info.py @@ -0,0 +1,55 @@ +""" +Retrieve a particular build for a package in Copr +""" + +import json +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.copr import copr_cli, CoprCliCommandError, full_name # pylint:disable=import-error,no-name-in-module + + +def main(): + """ + Retrieve a particular build for a package in Copr + """ + module = AnsibleModule( + argument_spec=dict( + user=dict(type='str', required=True), + project=dict(type='str', required=True), + nevr=dict(type='str', required=True), + package=dict(type='str', required=True), + config_file=dict(type='str', required=False), + ) + ) + + user = module.params['user'] + project = module.params['project'] + nevr = module.params['nevr'] + package = module.params['package'] + config_file = module.params['config_file'] + + command = [ + 'get-package', + full_name(user, project), + '--name', + package, + '--with-all-builds' + ] + + try: + package_info = json.loads(copr_cli(command, config_file=config_file)) + except CoprCliCommandError as error: + if "Error: No package with name {} in copr {}".format(package, project) in error.message: + module.exit_json(exists=False) + else: + module.fail_json(msg='Retrieval of package from Copr failed', command=command, output=error.message, + repo_name=full_name(user, project), package=package) + + successful_builds = (build for build in package_info['builds'] if build['state'] == 'succeeded') + successful_nevrs = ("{}-{}".format(package, build['source_package']['version']) for build in successful_builds) + exists = nevr in successful_nevrs + + module.exit_json(exists=exists) + + +if __name__ == '__main__': + main() diff --git a/obal/data/modules/copr_chroot.py b/obal/data/modules/copr_chroot.py index 1e0f2ba1..75ba4845 100644 --- a/obal/data/modules/copr_chroot.py +++ b/obal/data/modules/copr_chroot.py @@ -18,6 +18,7 @@ def main(): external_repos=dict(type='list', required=False), buildroot_packages=dict(type='list', required=False), modules=dict(type='list', required=False), + config_file=dict(type='str', required=False), ) ) @@ -27,6 +28,7 @@ def main(): external_repos = module.params['external_repos'] buildroot_packages = module.params['buildroot_packages'] modules = module.params['modules'] + config_file = module.params['config_file'] command = [ 'edit-chroot', @@ -43,7 +45,7 @@ def main(): command.extend(['--modules', ','.join(modules)]) try: - output = copr_cli(command) + output = copr_cli(command, config_file=config_file) except CoprCliCommandError as error: module.fail_json(msg='Copr chroot edit failed', command=' '.join(error.command), output=error.message) diff --git a/obal/data/modules/copr_fork.py b/obal/data/modules/copr_fork.py new file mode 100644 index 00000000..d13a0782 --- /dev/null +++ b/obal/data/modules/copr_fork.py @@ -0,0 +1,59 @@ +""" +Fork a Copr project +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.copr import copr_cli, CoprCliCommandError, full_name # pylint:disable=import-error,no-name-in-module + + +def main(): + """ + Fork a Copr project + """ + module = AnsibleModule( + argument_spec=dict( + src_user=dict(type='str', required=True), + src_project=dict(type='str', required=True), + dest_user=dict(type='str', required=True), + dest_project=dict(type='str', required=True), + delete_after_days=dict(type='str', required=False, default=None), + config_file=dict(type='str', required=False), + ) + ) + + src_user = module.params['src_user'] + src_project = module.params['src_project'] + dest_user = module.params['dest_user'] + dest_project = module.params['dest_project'] + delete_after_days = module.params['delete_after_days'] + config_file = module.params['config_file'] + + command = [ + 'fork', + full_name(src_user, src_project), + full_name(dest_user, dest_project) + ] + + try: + fork_output = copr_cli(command, config_file=config_file) + except CoprCliCommandError as error: + module.fail_json(msg='Copr project forking failed', command=' '.join(error.command), output=error.message) + + if delete_after_days: + modify_command = [ + 'modify', + full_name(dest_user, dest_project), + '--delete-after-days', + delete_after_days + ] + + try: + copr_cli(modify_command, config_file=config_file) + except CoprCliCommandError as error: + module.fail_json(msg='Copr project forking failed', command=' '.join(error.command), output=error.message) + + module.exit_json(changed=True, output=fork_output) + + +if __name__ == '__main__': + main() diff --git a/obal/data/modules/copr_project.py b/obal/data/modules/copr_project.py index 65d54626..0d97b6fc 100644 --- a/obal/data/modules/copr_project.py +++ b/obal/data/modules/copr_project.py @@ -7,7 +7,7 @@ from ansible.module_utils.copr import copr_cli, CoprCliCommandError, full_name # pylint:disable=import-error,no-name-in-module -def project_exists(user, project, module): +def project_exists(user, project, module, config_file=None): """ Return true if a project already exists for a user """ @@ -17,7 +17,7 @@ def project_exists(user, project, module): ] try: - project_list = copr_cli(command) + project_list = copr_cli(command, config_file=config_file) except CoprCliCommandError as error: module.fail_json(msg='Copr project listing failed', command=' '.join(error.command), output=error.message) @@ -35,6 +35,8 @@ def main(): description=dict(type='str', required=False), unlisted_on_homepage=dict(type='bool', required=False, default=False), delete_after_days=dict(type='str', required=False), + appstream=dict(type='str', required=False, default='off'), + config_file=dict(type='str', required=False), ) ) @@ -44,11 +46,13 @@ def main(): description = module.params['description'] unlisted_on_homepage = module.params['unlisted_on_homepage'] delete_after_days = module.params['delete_after_days'] + appstream = module.params['appstream'] + config_file = module.params['config_file'] if not description: description = project - if project_exists(user, project, module): + if project_exists(user, project, module, config_file=config_file): command = ['modify'] else: command = ['create'] @@ -59,6 +63,8 @@ def main(): description ]) + command.extend(['--appstream', appstream]) + for chroot in chroots: command.extend(['--chroot', chroot]) @@ -69,7 +75,7 @@ def main(): command.extend(['--delete-after-days', delete_after_days]) try: - output = copr_cli(command) + output = copr_cli(command, config_file=config_file) except CoprCliCommandError as error: module.fail_json(msg='Copr project creation failed', command=' '.join(error.command), output=error.message) diff --git a/obal/data/playbooks/release/metadata.obal.yaml b/obal/data/playbooks/release/metadata.obal.yaml index 43ba70e5..a782f67d 100644 --- a/obal/data/playbooks/release/metadata.obal.yaml +++ b/obal/data/playbooks/release/metadata.obal.yaml @@ -8,3 +8,22 @@ variables: action: store_false parameter: --skip-koji-whitelist-check help: ignore koji whitelist check and release the package anyway + build_package_copr_chroots: + action: append + parameter: --copr-chroot + help: Specify a Copr chroot to release for, can be specified multiple times + build_package_copr_rebuild: + action: store_true + parameter: --copr-rebuild + help: Forces a rebuild of a package in Copr + build_package_skip_failed_build: + action: store_true + parameter: --skip-failed-build + help: Skips failing builds and continues execution + build_package_wait: + action: store_false + parameter: --nowait + help: Do not wait on builds to complete + build_package_copr_config: + parameter: --copr-config + help: Path to a Copr config file diff --git a/obal/data/playbooks/scratch/metadata.obal.yaml b/obal/data/playbooks/scratch/metadata.obal.yaml index 9e00308f..651aeb7b 100644 --- a/obal/data/playbooks/scratch/metadata.obal.yaml +++ b/obal/data/playbooks/scratch/metadata.obal.yaml @@ -8,3 +8,6 @@ variables: action: store_false parameter: --skip-koji-whitelist-check help: ignore koji whitelist check and scratch build the package anyway + build_package_copr_config: + parameter: --copr-config + help: Path to a Copr config file diff --git a/obal/data/roles/build_package/defaults/main.yaml b/obal/data/roles/build_package/defaults/main.yaml index 9750aed4..9f811261 100644 --- a/obal/data/roles/build_package/defaults/main.yaml +++ b/obal/data/roles/build_package/defaults/main.yaml @@ -12,3 +12,6 @@ build_package_waitrepo: false build_package_koji_whitelist_check: false build_package_tito_builder: build_package_use_koji_build: false +build_package_copr_rebuild: false +build_package_skip_failed_build: false +build_package_archive_build_info: false diff --git a/obal/data/roles/build_package/tasks/_copr_build_for_chroot.yaml b/obal/data/roles/build_package/tasks/_copr_build_for_chroot.yaml new file mode 100644 index 00000000..e69de29b diff --git a/obal/data/roles/build_package/tasks/copr.yml b/obal/data/roles/build_package/tasks/copr.yml index 41487cc1..289fed74 100644 --- a/obal/data/roles/build_package/tasks/copr.yml +++ b/obal/data/roles/build_package/tasks/copr.yml @@ -1,53 +1,5 @@ --- -- when: not build_package_scratch - block: - - name: 'Release to copr' - tito_release: - directory: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}" - arguments: "{{ build_package_tito_args }}" - test: "{{ build_package_test }}" - scratch: "{{ build_package_scratch }}" - releasers: "{{ releasers }}" - releaser_arguments: "{{ build_package_tito_releaser_args }}" - register: build_package_tito_release - - - name: 'Wait for tasks to finish' - include_tasks: wait.yml - when: build_package_wait|bool - -- when: build_package_scratch - block: - - name: Define copr repo name - set_fact: - copr_repo_name: "{{ copr_user }}/{{ build_package_scratch_repo }}-{{ 999999999 | random | to_uuid }}" - run_once: true - when: copr_repo_name is not defined - - - name: 'Write copr repo name to vars file' - copy: - content: "{{ 'copr_repo: ' + copr_repo_name | to_yaml }}" - dest: "{{ obal_tmp_dir }}/copr_repo" - mode: '0640' - run_once: true - - - include_role: - name: copr_repo - run_once: true - - - name: 'Build SRPM' - tito_build: - directory: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}" - srpm: true - scl: "{{ scl }}" - register: srpm_build - - - name: 'Run build' - command: >- - copr-cli build - {% if not build_package_wait | bool %}--nowait{% endif %} - {{ copr_repo_name }} - {{ srpm_build.path }} - register: build_status - - - debug: - msg: "{{ build_status.stdout_lines | join('\n') }}" +- include_tasks: copr_build.yml + loop: "{{ copr_projects }}" + loop_control: + loop_var: copr_project diff --git a/obal/data/roles/build_package/tasks/copr_build.yml b/obal/data/roles/build_package/tasks/copr_build.yml new file mode 100644 index 00000000..5799c5bf --- /dev/null +++ b/obal/data/roles/build_package/tasks/copr_build.yml @@ -0,0 +1,127 @@ +--- +- when: + - not build_package_scratch + - not build_package_copr_rebuild + block: + - name: "Package name" + rpm_nevr: + spec_file: "{{ spec_file_path }}" + scl: "{{ tag.scl | default(omit) }}" + dist: "{{ tag.dist | default(omit) }}" + macros: "{{ tag.macros | default(omit) }}" + register: package_nevr + + - name: Get information about Copr build + copr_build_info: + user: "{{ copr_project_user }}" + project: "{{ copr_project['copr_project_name'] }}" + nevr: "{{ package_nevr.nevr }}" + package: "{{ package_nevr.name }}" + config_file: "{{ build_package_copr_config | default(omit) }}" + register: build_info + +- name: Create temporary build directory + tempfile: + state: directory + suffix: srpms + register: srpm_directory + when: srpm_directory is not defined or ('exists' in build_info and not build_info.exists) or build_package_copr_rebuild + +- name: 'Build SRPM' + srpm: + package: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}" + output: "{{ srpm_directory.path if 'path' in srpm_directory else srpm_directory }}" + source_location: "{{ source_location | default(omit) }}" + source_system: "{{ source_system | default(omit) }}" + register: srpm_build + when: (srpm_directory is defined and (build_info.exists is defined and not build_info.exists)) or build_package_copr_rebuild or build_package_scratch + +- when: (not build_package_scratch and (build_info.exists is defined and not build_info.exists)) or build_package_copr_rebuild + block: + - name: 'Run build' + copr_build: + user: "{{ copr_project_user }}" + project: "{{ copr_project['copr_project_name'] }}" + srpm: "{{ srpm_build.path }}" + chroots: "{{ chroot }}" + config_file: "{{ build_package_copr_config | default(omit) }}" + register: copr_builds + ignore_errors: "{{ build_package_skip_failed_build | default(false) }}" + loop: "{{ copr_project['copr_project_chroots'] | map(attribute='name') | list }}" + loop_control: + loop_var: chroot + + - name: 'Created tasks' + debug: + msg: "{{ copr_builds['results'] | map(attribute='build_urls') | list | flatten }}" + + - name: 'Wait for tasks to finish' + include_tasks: wait.yml + when: build_package_wait|bool + vars: + copr_build_ids: "{{ copr_builds['results'] | map(attribute='builds') | list | flatten }}" + +- when: build_package_scratch + block: + - name: Define Copr scratch project name + set_fact: + copr_scratch_project: "{{ copr_project['copr_project_name'] }}-scratch-{{ 999999999 | random | to_uuid }}" + when: copr_scratch_project is not defined + + - name: Define Copr scatch user name + set_fact: + copr_scratch_user: "{{ copr_project_user }}" + when: copr_scratch_user is not defined + + - include_role: + name: copr_project + vars: + copr_project_user: "{{ copr_scratch_user }}" + copr_project_name: "{{ copr_scratch_project }}" + copr_project_chroots: "{{ copr_project['copr_project_chroots'] }}" + copr_project_description: "{{ copr_project['copr_project_description'] | default('') }}" + copr_project_delete_after_days: "4" + copr_project_unlisted_on_homepage: "{{ copr_project['copr_project_unlisted_on_homepage'] | default(true) }}" + copr_project_copr_config: "{{ build_package_copr_config | default('') }}" + + - name: 'Run build' + copr_build: + user: "{{ copr_scratch_user }}" + project: "{{ copr_scratch_project }}" + srpm: "{{ srpm_build.path }}" + chroots: "{{ chroot }}" + config_file: "{{ build_package_copr_config | default(omit) }}" + register: copr_builds + loop: "{{ copr_project['copr_project_chroots'] | map(attribute='name') | list }}" + loop_control: + loop_var: chroot + + - name: 'Created tasks' + debug: + msg: "{{ copr_builds['results'] | map(attribute='build_urls') | list | flatten }}" + + - name: 'Wait for tasks to finish' + include_tasks: wait.yml + when: build_package_wait|bool + vars: + copr_build_ids: "{{ copr_builds['results'] | map(attribute='builds') | list | flatten }}" + + - name: Create build info directory + file: + path: "{{ inventory_dir }}/copr_build_info" + state: directory + mode: '0755' + + - name: 'Write out build info' + when: + - build_package_archive_build_info + copy: + dest: "{{ inventory_dir }}/copr_build_info/{{ inventory_hostname }}" + content: "{{ copr_builds | to_yaml }}" + mode: '0644' + + - name: 'Download builds' + include_tasks: download_rpms.yml + when: build_package_download_rpms|bool + vars: + chroots: "{{ copr_project['copr_project_chroots'] | map(attribute='name') | list }}" diff --git a/obal/data/roles/build_package/tasks/download_rpms.yml b/obal/data/roles/build_package/tasks/download_rpms.yml index 38f29231..d119ea82 100644 --- a/obal/data/roles/build_package/tasks/download_rpms.yml +++ b/obal/data/roles/build_package/tasks/download_rpms.yml @@ -1,3 +1,7 @@ - include_tasks: download_rpms_from_task.yml with_items: "{{ build_package_koji_task_data }}" when: build_package_build_system == 'koji' and build_package_download_rpms + +- include_tasks: download_rpms_copr.yml + with_items: "{{ copr_builds['results'] | map(attribute='builds') | list | flatten }}" + when: build_package_build_system == 'copr' and build_package_download_rpms diff --git a/obal/data/roles/build_package/tasks/download_rpms_copr.yml b/obal/data/roles/build_package/tasks/download_rpms_copr.yml new file mode 100644 index 00000000..39251240 --- /dev/null +++ b/obal/data/roles/build_package/tasks/download_rpms_copr.yml @@ -0,0 +1,20 @@ +- when: build_package_build_system == 'copr' and build_package_download_rpms + block: + - name: Define download directory + set_fact: + download_dir: "{{ inventory_dir }}/downloaded_rpms" + + - name: 'Create RPM downloads directory' + file: + state: directory + path: "{{ download_dir }}" + mode: '0775' + + - name: "Download Copr RPM(s)" + command: "copr-cli {{ ' --config ' + build_package_copr_config if build_package_copr_config is defined else '' }} download-build {{ item }}" + args: + chdir: "{{ download_dir }}" + + - name: 'Create repo from downloaded RPMs' + command: "createrepo {{ download_dir }}/{{ item }}" + loop: "{{ chroots }}" diff --git a/obal/data/roles/build_package/tasks/wait.yml b/obal/data/roles/build_package/tasks/wait.yml index a0dad277..f0a98827 100644 --- a/obal/data/roles/build_package/tasks/wait.yml +++ b/obal/data/roles/build_package/tasks/wait.yml @@ -36,13 +36,14 @@ - when: build_package_build_system == 'copr' block: - - name: "Watch copr task(s)" - command: "copr-cli watch-build {{ build_package_tito_release.builds | join(' ') }}" + - name: "Watch copr build(s)" + command: + "copr-cli {{ '--config ' + build_package_copr_config if build_package_copr_config is defined else '' }} watch-build {{ copr_build_ids | join(' ') }}" ignore_errors: true register: build_package_copr_status changed_when: false - name: 'Failed build' fail: - msg: "The build in Copr has failed" + msg: "The build in Copr has failed" when: (build_package_copr_status is failed) diff --git a/obal/data/roles/copr_project/defaults/main.yaml b/obal/data/roles/copr_project/defaults/main.yaml index ed97d539..0184c98b 100644 --- a/obal/data/roles/copr_project/defaults/main.yaml +++ b/obal/data/roles/copr_project/defaults/main.yaml @@ -1 +1,2 @@ --- +copr_project_chroots: [] diff --git a/obal/data/roles/copr_project/tasks/main.yaml b/obal/data/roles/copr_project/tasks/main.yaml index 39c9a13c..f8e01d66 100644 --- a/obal/data/roles/copr_project/tasks/main.yaml +++ b/obal/data/roles/copr_project/tasks/main.yaml @@ -3,10 +3,11 @@ copr_project: user: "{{ copr_project_user }}" project: "{{ copr_project_name }}" - chroots: "{{ copr_project_chroots | map(attribute='name') }}" + chroots: "{{ copr_project_chroots | map(attribute='name') | list }}" description: "{{ copr_project_description | default(omit) }}" delete_after_days: "{{ copr_project_delete_after_days | default(omit) }}" unlisted_on_homepage: "{{ copr_project_unlisted_on_homepage | default(omit) }}" + config_file: "{{ copr_project_copr_config | default(omit) }}" register: create_output - name: Configure chroots @@ -17,6 +18,7 @@ external_repos: "{{ chroot.external_repos | default(omit) }}" buildroot_packages: "{{ chroot.buildroot_packages | default(omit) }}" modules: "{{ chroot.modules | default(omit) }}" + config_file: "{{ copr_project_copr_config | default(omit) }}" loop: "{{ copr_project_chroots }}" loop_control: loop_var: chroot diff --git a/obal/data/roles/copr_repo/tasks/main.yml b/obal/data/roles/copr_repo/tasks/main.yml index d52bab75..8b129f55 100644 --- a/obal/data/roles/copr_repo/tasks/main.yml +++ b/obal/data/roles/copr_repo/tasks/main.yml @@ -1,19 +1,20 @@ --- -- name: 'Create copr scratch build repo' - command: > - copr-cli - create - {{ copr_repo_name }} - --chroot {{ copr_repo_chroot }} - --description '{{ copr_repo_description }}' - --unlisted-on-hp on - --repo '{{ copr_repo_external_repos | join(' ') }}' - changed_when: false +- name: 'Create Copr repo' + copr_repo: + repo_name: "{{ copr_repo_name }}" + chroots: "{{ copr_repo_chroots | map(attribute='name') }}" + description: "{{ copr_repo_description | default(omit) }}" + delete_after_days: "{{ copr_repo_delete_after_days | default(omit) }}" + unlisted_on_homepage: "{{ copr_repo_unlisted_on_homepage | default(omit) }}" + register: create_output -- name: 'Add build packages to chroot' - command: > - copr-cli - edit-chroot - {{ copr_repo_name }}/{{ copr_repo_chroot }} - --packages '{{ copr_repo_packages | join(' ') }}' - changed_when: false +- name: Configure chroots + copr_chroot: + repo_name: "{{ copr_repo_name }}" + chroot: "{{ chroot.name }}" + external_repos: "{{ chroot.external_repos | default(omit) }}" + buildroot_packages: "{{ chroot.buildroot_packages | default(omit) }}" + modules: "{{ chroot.modules | default(omit) }}" + loop: "{{ copr_repo_chroots }}" + loop_control: + loop_var: chroot diff --git a/tests/fixtures/help/release.txt b/tests/fixtures/help/release.txt index 138cce6a..ca787c61 100644 --- a/tests/fixtures/help/release.txt +++ b/tests/fixtures/help/release.txt @@ -1,4 +1,8 @@ -usage: obal release [-h] [-v] [-e EXTRA_VARS] [--skip-koji-whitelist-check] +usage: obal release [-h] [-v] [-e EXTRA_VARS] + [--copr-chroot BUILD_PACKAGE_COPR_CHROOTS] + [--copr-config BUILD_PACKAGE_COPR_CONFIG] [--copr-rebuild] + [--skip-koji-whitelist-check] [--skip-failed-build] + [--nowait] target [target ...] This action releases a package to Koji/Brew/Copr @@ -11,9 +15,17 @@ positional arguments: optional arguments: -h, --help show this help message and exit -v, --verbose verbose output + --copr-chroot BUILD_PACKAGE_COPR_CHROOTS + Specify a Copr chroot to release for, can be specified + multiple times + --copr-config BUILD_PACKAGE_COPR_CONFIG + Path to a Copr config file + --copr-rebuild Forces a rebuild of a package in Copr --skip-koji-whitelist-check ignore koji whitelist check and release the package anyway + --skip-failed-build Skips failing builds and continues execution + --nowait Do not wait on builds to complete advanced arguments: -e EXTRA_VARS, --extra-vars EXTRA_VARS diff --git a/tests/fixtures/help/scratch.txt b/tests/fixtures/help/scratch.txt index 0288597c..093441d6 100644 --- a/tests/fixtures/help/scratch.txt +++ b/tests/fixtures/help/scratch.txt @@ -1,4 +1,6 @@ -usage: obal scratch [-h] [-v] [-e EXTRA_VARS] [--skip-koji-whitelist-check] +usage: obal scratch [-h] [-v] [-e EXTRA_VARS] + [--copr-config BUILD_PACKAGE_COPR_CONFIG] + [--skip-koji-whitelist-check] target [target ...] Create a scratch build of a package @@ -11,6 +13,8 @@ positional arguments: optional arguments: -h, --help show this help message and exit -v, --verbose verbose output + --copr-config BUILD_PACKAGE_COPR_CONFIG + Path to a Copr config file --skip-koji-whitelist-check ignore koji whitelist check and scratch build the package anyway diff --git a/tests/fixtures/mockbin/mockbin b/tests/fixtures/mockbin/mockbin index 95407c9e..56a86c30 100755 --- a/tests/fixtures/mockbin/mockbin +++ b/tests/fixtures/mockbin/mockbin @@ -5,6 +5,7 @@ from __future__ import print_function import os import sys import argparse +import json try: from shlex import quote except ImportError: @@ -152,4 +153,57 @@ elif prog in ['koji', 'brew']: print('BUILD: {}\nState: COMPLETE'.format(args.pkg)) elif prog in ['copr-cli']: - print({}) + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers(dest='subcommand') + + parser_build = subparsers.add_parser('get-package') + parser_build.add_argument('project') + parser_build.add_argument('--name') + parser_build.add_argument('--with-all-builds', action='store_true') + + parser_build = subparsers.add_parser('build') + parser_build.add_argument('project') + parser_build.add_argument('pkg') + parser_build.add_argument('--nowait', action='store_true') + parser_build.add_argument('--chroot') + + parser_build = subparsers.add_parser('list') + parser_build.add_argument('project') + + parser_build = subparsers.add_parser('fork') + parser_build.add_argument('src') + parser_build.add_argument('dest') + + parser_build = subparsers.add_parser('create') + parser_build.add_argument('project') + parser_build.add_argument('--description') + parser_build.add_argument('--chroot') + parser_build.add_argument('--appstream') + parser_build.add_argument('--delete-after-days') + parser_build.add_argument('--unlisted-on-hp') + + parser_build = subparsers.add_parser('modify') + parser_build.add_argument('project') + parser_build.add_argument('--delete-after-days') + + parser_build = subparsers.add_parser('edit-chroot') + parser_build.add_argument('project-chroot') + parser_build.add_argument('--repos') + parser_build.add_argument('--packages') + parser_build.add_argument('--modules') + + parser_build = subparsers.add_parser('watch-build') + parser_build.add_argument('build') + + args = parser.parse_args() + + if args.subcommand == 'get-package': + #json_data = json.loads('{"builds": [{"state": "succeeded", "source_package": {"version": "0.0.1"}}]}') + json_data = {"builds": [{"state": "succeeded", "source_package": {"version": "0.0.1"}}]} + print(json.dumps(json_data, indent=2)) + elif args.subcommand == 'build': + print("Build was added to foreman-1234:") + print("https://copr.fedorainfracloud.org/coprs/build/5678") + print("Created builds: 5678") + else: + print({}) diff --git a/tests/fixtures/testrepo/copr/package_manifest.yaml b/tests/fixtures/testrepo/copr/package_manifest.yaml index 6773ae5f..4a59db04 100644 --- a/tests/fixtures/testrepo/copr/package_manifest.yaml +++ b/tests/fixtures/testrepo/copr/package_manifest.yaml @@ -1,21 +1,12 @@ --- packages: vars: - releasers: - - copr - scl: copr-scl - copr_user: "@fake-user" - copr_repo_name: copr-repo-scratch - diff_package_copr_repo: copr-repo-staging - diff_package_type: copr + copr_project_user: example + copr_project_name: foreman + copr_scratch_project: foreman-1234 build_package_build_system: copr - build_package_scratch_repo: copr-repo-scratch - copr_repo_chroot: epel-7-x86_64 - copr_repo_external_repos: - - http://mirror.centos.org/centos/7/sclo/x86_64/rh/ - copr_repo_packages: - - scl-utils-build - - rh-ruby24-build + copr_projects: + - "{{ hostvars['foreman'] }}" hosts: hello: {} diff --git a/tests/test_functional.py b/tests/test_functional.py index a339cad4..e29d33c6 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -662,10 +662,10 @@ def test_obal_scratch_copr_hello_nowait(): assert os.path.exists('packages/hello/hello-2.10.tar.gz') expected_log = [ - "copr-cli create copr-repo-scratch --chroot epel-7-x86_64 --description 'Scratch Builds' --unlisted-on-hp on --repo http://mirror.centos.org/centos/7/sclo/x86_64/rh/", # noqa: E501 - "copr-cli edit-chroot copr-repo-scratch/epel-7-x86_64 --packages 'scl-utils-build rh-ruby24-build'", # noqa: E501 - "tito build --srpm --scl copr-scl", - "copr-cli build --nowait copr-repo-scratch hello-2.10-1.src.rpm" + "copr-cli list example", + "copr-cli create example/foreman-1234 --description foreman-1234 --appstream off --chroot epel-7-x86_64 --unlisted-on-hp on --delete-after-days 4", # noqa: E501 + "copr-cli edit-chroot example/foreman-1234/epel-7-x86_64 --repos http://mirror.centos.org/centos/7/sclo/x86_64/rh/ --packages 'rh-ruby24-build scl-utils-build'", # noqa: E501 + "copr-cli build example/foreman-1234 /tmp/SRPMs/hello-2.10-1.src.rpm --nowait --chroot epel-7-x86_64" ] assert_mockbin_log(expected_log) @@ -677,11 +677,11 @@ def test_obal_scratch_copr_hello(): assert os.path.exists('packages/hello/hello-2.10.tar.gz') expected_log = [ - "copr-cli create copr-repo-scratch --chroot epel-7-x86_64 --description 'Scratch Builds' --unlisted-on-hp on --repo http://mirror.centos.org/centos/7/sclo/x86_64/rh/", # noqa: E501 - "copr-cli edit-chroot copr-repo-scratch/epel-7-x86_64 --packages 'scl-utils-build rh-ruby24-build'", # noqa: E501 - "tito build --srpm --scl copr-scl", - "copr-cli build copr-repo-scratch hello-2.10-1.src.rpm", - # copr-cli build waits by default, so there is no "watch-build" step here + "copr-cli list example", + "copr-cli create example/foreman-1234 --description foreman-1234 --appstream off --chroot epel-7-x86_64 --unlisted-on-hp on --delete-after-days 4", # noqa: E501 + "copr-cli edit-chroot example/foreman-1234/epel-7-x86_64 --repos http://mirror.centos.org/centos/7/sclo/x86_64/rh/ --packages 'rh-ruby24-build scl-utils-build'", # noqa: E501 + "copr-cli build example/foreman-1234 /tmp/SRPMs/hello-2.10-1.src.rpm --nowait --chroot epel-7-x86_64", + "copr-cli watch-build 5678" ] assert_mockbin_log(expected_log) @@ -693,8 +693,8 @@ def test_obal_release_copr_hello_nowait(): assert os.path.exists('packages/hello/hello-2.10.tar.gz') expected_log = [ - "copr-cli get-package @fake-user/copr-repo-staging --name hello --with-latest-build", - "tito release --yes copr", + "copr-cli get-package example/foreman --name hello --with-all-builds", + "copr-cli build example/foreman /tmp/SRPMs/hello-2.10-1.src.rpm --nowait --chroot epel-7-x86_64" ] assert_mockbin_log(expected_log) @@ -706,9 +706,9 @@ def test_obal_release_copr_hello(): assert os.path.exists('packages/hello/hello-2.10.tar.gz') expected_log = [ - "copr-cli get-package @fake-user/copr-repo-staging --name hello --with-latest-build", - "tito release --yes copr", - "copr-cli watch-build" + "copr-cli get-package example/foreman --name hello --with-all-builds", + "copr-cli build example/foreman /tmp/SRPMs/hello-2.10-1.src.rpm --nowait --chroot epel-7-x86_64", + "copr-cli watch-build 5678" ] assert_mockbin_log(expected_log) @@ -808,7 +808,7 @@ def test_copr_project_one_chroot(): expected_log = [ "copr-cli list example", - "copr-cli create example/foreman --description foreman --chroot epel-7-x86_64", # noqa: E501 + "copr-cli create example/foreman --description foreman --appstream off --chroot epel-7-x86_64", # noqa: E501 "copr-cli edit-chroot example/foreman/epel-7-x86_64 --repos http://mirror.centos.org/centos/7/sclo/x86_64/rh/ --packages 'rh-ruby24-build scl-utils-build'", # noqa: E501 ] @@ -821,7 +821,7 @@ def test_copr_project_many_chroots(): expected_log = [ "copr-cli list example", - "copr-cli create example/foreman-client --description foreman-client --chroot rhel-9-x86_64 --chroot rhel-8-x86_64 --chroot rhel-7-x86_64", # noqa: E501 + "copr-cli create example/foreman-client --description foreman-client --appstream off --chroot rhel-9-x86_64 --chroot rhel-8-x86_64 --chroot rhel-7-x86_64", # noqa: E501 "copr-cli edit-chroot example/foreman-client/rhel-9-x86_64", "copr-cli edit-chroot example/foreman-client/rhel-8-x86_64", "copr-cli edit-chroot example/foreman-client/rhel-7-x86_64"