From f50b6a1dcbe46a48d07d42ec603a58e18227b15f Mon Sep 17 00:00:00 2001 From: "Eric D. Helms" Date: Wed, 18 Mar 2020 15:29:11 -0400 Subject: [PATCH] Add srpm-build to replace tito build --- .github/workflows/main.yml | 2 +- obal/data/module_utils/obal.py | 16 +++ obal/data/module_utils/tito_wrapper.py | 16 +-- obal/data/modules/srpm.py | 121 ++++++++++++++++++ obal/data/roles/build_srpm/tasks/main.yaml | 14 +- .../testrepo/upstream/packages/foo/foo-source | 2 + .../testrepo/upstream/packages/foo/foo.spec | 2 +- tests/test_functional.py | 11 +- 8 files changed, 150 insertions(+), 34 deletions(-) create mode 100644 obal/data/modules/srpm.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64bbe778..bafcd3e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,7 +9,7 @@ env: jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: diff --git a/obal/data/module_utils/obal.py b/obal/data/module_utils/obal.py index 6d73d73b..0a56cae7 100644 --- a/obal/data/module_utils/obal.py +++ b/obal/data/module_utils/obal.py @@ -2,6 +2,8 @@ Ansible module helper functions for obal modules """ import subprocess +import os +from contextlib import contextmanager def specfile_macro_lookup(specfile, macro_str, scl=None, dist=None, macros=None): @@ -75,3 +77,17 @@ def get_whitelist_status(build_command, tag, package): ] retcode = subprocess.call(cmd) return retcode == 0 + + +@contextmanager +def chdir(directory): + """ + Change the directory in a context manager. Automatically switches back even if an exception + occurs. + """ + old = os.getcwd() + os.chdir(directory) + try: + yield + finally: + os.chdir(old) diff --git a/obal/data/module_utils/tito_wrapper.py b/obal/data/module_utils/tito_wrapper.py index 945f4efb..d77c9379 100644 --- a/obal/data/module_utils/tito_wrapper.py +++ b/obal/data/module_utils/tito_wrapper.py @@ -1,23 +1,9 @@ """ A tito wrapper """ -import os -from contextlib import contextmanager from subprocess import STDOUT, check_output - -@contextmanager -def chdir(directory): - """ - Change the directory in a context manager. Automatically switches back even if an exception - occurs. - """ - old = os.getcwd() - os.chdir(directory) - try: - yield - finally: - os.chdir(old) +from ansible.module_utils.chdir import chdir # pylint:disable=import-error,no-name-in-module def tito(command, directory): diff --git a/obal/data/modules/srpm.py b/obal/data/modules/srpm.py new file mode 100644 index 00000000..e7d8fbfb --- /dev/null +++ b/obal/data/modules/srpm.py @@ -0,0 +1,121 @@ +""" +Build SRPM +""" + +import shutil +import os +import subprocess +from tempfile import mkdtemp + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.obal import chdir # pylint:disable=import-error,no-name-in-module + +def run_command(command): + """ + Run a system command + """ + return subprocess.check_output( + command, + universal_newlines=True, + stderr=subprocess.STDOUT + ) + + +def copy_sources(spec_file, package_dir, sources_dir): + """ + Copy RPM sources to rpmbuild environment + """ + command = ["spectool", "--list-files", spec_file] + sources = run_command(command) + + for source in sources.split("\n"): + if not source: + continue + + source_link = source.split(' ')[1] + + if not source_link.startswith('http'): + shutil.copy(os.path.join(package_dir, source_link), sources_dir) + + with chdir(package_dir): + run_command(["git-annex", "lock"]) + annexed_files = run_command(["git-annex", "find", "--include", "*"]) + annexed_files = annexed_files.splitlines() + + if not annexed_files: + return + + run_command(["git-annex", "get"]) + + try: + run_command(["git-annex", "unlock"]) + finally: + for annex in annexed_files: + shutil.copy(annex, sources_dir) + + run_command(["git-annex", "lock", "--force"]) + + +def main(): + """ + Build a package using tito + """ + module = AnsibleModule( + argument_spec=dict( + package=dict(type='str', required=False), + scl=dict(type='str', required=False), + output=dict(type='path', required=False), + ) + ) + + package = module.params['package'] + output = module.params['output'] + scl = module.params['scl'] + + spec_file = os.path.join(package, '%s.spec' % os.path.basename(package)) + + try: + base_dir = mkdtemp() + sources_dir = os.path.join(base_dir, 'SOURCES') + build_dir = os.path.join(base_dir, 'BUILD') + + os.mkdir(sources_dir) + os.mkdir(build_dir) + + copy_sources(spec_file, package, sources_dir) + shutil.copy(spec_file, base_dir) + + command = ['rpmbuild', '-bs'] + command += ['--define', '_topdir %s' % base_dir] + command += ['--define', '_sourcedir %s' % sources_dir] + command += ['--define', '_builddir %s' % build_dir] + command += ['--define', '_srcrpmdir %s' % base_dir] + command += ['--define', '_rpmdir %s' % base_dir] + command += ['--undefine', 'dist'] + + if scl: + command += ['--define', 'scl %s' % scl] + + command += [os.path.join(base_dir, '%s.spec' % os.path.basename(package))] + + try: + result = run_command(command) + result = result.split("Wrote: ")[-1].rstrip() + + if not os.path.exists(output): + os.mkdir(output) + + shutil.copy(result, output) + path = os.path.join(output, os.path.basename(result)) + + module.exit_json(changed=True, path=path) + except subprocess.CalledProcessError as error: + module.fail_json(msg='Failed to srpm build', command=' '.join(command), output=error.output) + except subprocess.CalledProcessError as error: + module.fail_json(msg='Failed to build srpm', output=error.output) + finally: + shutil.rmtree(base_dir) + + +if __name__ == '__main__': + main() diff --git a/obal/data/roles/build_srpm/tasks/main.yaml b/obal/data/roles/build_srpm/tasks/main.yaml index 7b3ee6a6..3953c965 100644 --- a/obal/data/roles/build_srpm/tasks/main.yaml +++ b/obal/data/roles/build_srpm/tasks/main.yaml @@ -1,18 +1,12 @@ --- - name: 'Build SRPM' - tito_build: - directory: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}" - build_arguments: "{{ build_srpm_tito_build_args }}" - srpm: true - offline: true - dist: "{{ build_srpm_dist }}" - scl: "{{ build_srpm_scl }}" + srpm: + package: "{{ inventory_dir }}/{{ package_base_dir }}/{{ inventory_hostname }}" output: "{{ build_srpm_output_dir }}" - arguments: "{{ build_srpm_tito_args }}" - builder: "{{ build_srpm_tito_builder }}" + scl: "{{ scl | default(omit) }}" register: srpm_build -- name: 'Built SRPM' +- name: 'Built srpm path' debug: msg: "Built {{ srpm_build.path }}" when: srpm_build is successful diff --git a/tests/fixtures/testrepo/upstream/packages/foo/foo-source b/tests/fixtures/testrepo/upstream/packages/foo/foo-source index 522d3b5b..1e019d74 100644 --- a/tests/fixtures/testrepo/upstream/packages/foo/foo-source +++ b/tests/fixtures/testrepo/upstream/packages/foo/foo-source @@ -1 +1,3 @@ Bar! +Baz! +No Foo! diff --git a/tests/fixtures/testrepo/upstream/packages/foo/foo.spec b/tests/fixtures/testrepo/upstream/packages/foo/foo.spec index d2971741..0135eaad 100644 --- a/tests/fixtures/testrepo/upstream/packages/foo/foo.spec +++ b/tests/fixtures/testrepo/upstream/packages/foo/foo.spec @@ -19,7 +19,7 @@ A fake RPM for foos and bars. %install cp . %{buildroot}/ -%files foo +%files foo-source %changelog diff --git a/tests/test_functional.py b/tests/test_functional.py index c37862bf..42535503 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -657,10 +657,9 @@ def test_obal_changelog_custom(): @obal_cli_test(repotype='upstream') def test_obal_srpm(): assert_obal_success(['srpm', 'hello', 'foo']) - assert_mockbin_log([ - 'tito build --srpm --offline --output {pwd}/SRPMs', - 'tito build --srpm --offline --output {pwd}/SRPMs' - ]) + + assert os.path.exists('SRPMs/foo-1.0-1.src.rpm') + assert os.path.exists('SRPMs/hello-2.10-2.src.rpm') @obal_cli_test(repotype='upstream') @@ -668,8 +667,6 @@ def test_obal_mock(): assert_obal_success(['mock', 'hello', 'foo', '--config', 'mock/el7.cfg']) expected_log = [ - "tito build --srpm --offline --output {pwd}/SRPMs", - "tito build --srpm --offline --output {pwd}/SRPMs", - "mock --recurse --chain -r mock/el7.cfg --localrepo {pwd}/mock_builds SRPMs/foo-1.0-1.src.rpm SRPMs/hello-2.10-1.src.rpm" + "mock --recurse --chain -r mock/el7.cfg --localrepo {pwd}/mock_builds SRPMs/foo-1.0-1.src.rpm SRPMs/hello-2.10-2.src.rpm" ] assert_mockbin_log(expected_log)