Skip to content

Commit

Permalink
Refactor Copr support into modules
Browse files Browse the repository at this point in the history
  • Loading branch information
ehelms committed Apr 20, 2023
1 parent 9f70280 commit 8b9bf8d
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 87 deletions.
26 changes: 26 additions & 0 deletions obal/data/module_utils/copr_wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
A copr-cli wrapper
"""
from subprocess import check_output, CalledProcessError

class CoprCliCommandError(Exception):
"""Raised when copr-cli command fails"""
def __init__(self, message, command):
self.message = message
self.command = command
super(CoprCliCommandError, self).__init__(message) #pylint: disable-all

def copr_cli(command, executable='copr-cli'):
"""
Run a copr-cli command
"""
try:
return check_output([executable] + command, universal_newlines=True)
except CalledProcessError as error:
raise CoprCliCommandError(error.output, error.cmd)

def full_name(user, project):
"""
Returns a full Copr name: user/project
"""
return "{}/{}".format(user, project)
50 changes: 50 additions & 0 deletions obal/data/modules/copr_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Release a package to Copr
"""

import re

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.copr_wrapper 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=True)
)
)

user = module.params['user']
project = module.params['project']
srpm = module.params['srpm']
wait = module.params['wait']

command = [
'build',
full_name(user, project),
srpm
]

if not wait:
command.append('--nowait')

try:
output = copr_cli(command)
except CoprCliCommandError as error:
module.fail_json(msg='Copr build failed', command=error.command, output=error.message,
repo_name=repo_name, srpm=srpm)

builds = re.findall(r'^Build was added to.+:\n^\s(.+)', output, re.MULTILINE)

module.exit_json(changed=True, output=output, builds=builds)


if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion obal/data/modules/copr_chroot.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def main():

command = [
'edit-chroot',
"%s/%s" % (full_name(user, project), chroot)
"{}/{}".format(full_name(user, project), chroot)
]

if external_repos:
Expand Down
57 changes: 57 additions & 0 deletions obal/data/modules/copr_fork.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
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),
)
)

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']

command = [
'fork',
full_name(src_user, src_project),
full_name(dest_user, dest_project)
]

try:
fork_output = copr_cli(command)
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:
output = copr_cli(modify_command)
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()
2 changes: 1 addition & 1 deletion obal/data/modules/copr_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def main():
'create',
full_name(user, project),
'--description',
"%s" % description
description
]

for chroot in chroots:
Expand Down
85 changes: 44 additions & 41 deletions obal/data/roles/build_package/tasks/copr.yml
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
---
- name: Create temporary build directory
tempfile:
state: directory
suffix: srpms
register: srpm_directory
when: srpm_directory is not defined

- 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: 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
- name: 'Run build'
copr_build:
user: "{{ copr_project_user }}"
project: "{{ copr_project_name }}"
srpm: "{{ srpm_build.path }}"
wait: "{{ build_package_wait }}"
register: copr_builds

- when: build_package_scratch
block:
- name: Define copr repo name
- name: Define Copr scratch project 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
copr_scratch_project: "{{ copr_project_name }}-scratch-{{ 999999999 | random | to_uuid }}"
when: copr_scratch_project is not defined

- include_role:
name: copr_repo
run_once: true
- name: Define Copr scatch user name
set_fact:
copr_scratch_user: "{{ copr_project_user }}"
when: copr_scratch_user is not defined

- name: 'Build SRPM'
tito_build:
directory: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}"
srpm: true
scl: "{{ scl }}"
register: srpm_build
- name: Create a Copr fork for scratch builds
copr_fork:
src_user: "{{ copr_project_user }}"
src_project: "{{ copr_project_name }}"
dest_user: "{{ copr_scratch_user }}"
dest_project: "{{ copr_scratch_project }}"
delete_after_days: 4

- name: 'Run build'
command: >-
copr-cli build
{% if not build_package_wait | bool %}--nowait{% endif %}
{{ copr_repo_name }}
{{ srpm_build.path }}
register: build_status
copr_build:
user: "{{ copr_scratch_user }}"
project: "{{ copr_scratch_project }}"
srpm: "{{ srpm_build.path }}"
wait: "{{ build_package_wait }}"
register: copr_builds

- debug:
msg: "{{ build_status.stdout_lines | join('\n') }}"
- debug:
msg: "{{ copr_builds }}"
1 change: 1 addition & 0 deletions obal/data/roles/copr_project/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
---
copr_project_chroots: []
35 changes: 18 additions & 17 deletions obal/data/roles/copr_repo/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -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
17 changes: 3 additions & 14 deletions tests/fixtures/testrepo/copr/package_manifest.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
---
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
hosts:
hello: {}

Expand Down
21 changes: 8 additions & 13 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,10 +662,9 @@ 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 fork example/foreman example/foreman-1234", # noqa: E501
"copr-cli modify example/foreman-1234 --delete-after-days 4", # noqa: E501
"copr-cli build example/foreman-1234 /tmp/SRPMs/hello-2.10-1.src.rpm --nowait"
]
assert_mockbin_log(expected_log)

Expand All @@ -677,10 +676,9 @@ 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 fork example/foreman example/foreman-1234", # noqa: E501
"copr-cli modify example/foreman-1234 --delete-after-days 4", # noqa: E501
"copr-cli build example/foreman-1234 /tmp/SRPMs/hello-2.10-1.src.rpm",
# copr-cli build waits by default, so there is no "watch-build" step here
]
assert_mockbin_log(expected_log)
Expand All @@ -693,8 +691,7 @@ 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 build example/foreman /tmp/SRPMs/hello-2.10-1.src.rpm --nowait"
]
assert_mockbin_log(expected_log)

Expand All @@ -706,9 +703,7 @@ 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 build example/foreman /tmp/SRPMs/hello-2.10-1.src.rpm"
]
assert_mockbin_log(expected_log)

Expand Down

0 comments on commit 8b9bf8d

Please sign in to comment.