diff --git a/obal/data/module_utils/chdir.py b/obal/data/module_utils/chdir.py new file mode 100644 index 00000000..3393333d --- /dev/null +++ b/obal/data/module_utils/chdir.py @@ -0,0 +1,19 @@ +""" +A chdir context manager +""" +import os +from contextlib import contextmanager + + +@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..9dbd3613 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 def tito(command, directory): diff --git a/obal/data/modules/srpm.py b/obal/data/modules/srpm.py new file mode 100644 index 00000000..b6e01e3e --- /dev/null +++ b/obal/data/modules/srpm.py @@ -0,0 +1,113 @@ +""" +Build SRPM +""" + +import shutil +import os +import subprocess +from tempfile import mkdtemp + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.chdir import chdir + +def run_command(command): + return subprocess.check_output( + ' '.join(command), + universal_newlines=True, + shell=True, + stderr=subprocess.STDOUT + ) + + +def copy_sources(spec_file, package_dir, sources_dir, module): + 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() + run_command(["git-annex", "get"]) + + try: + run_command(["git-annex", "unlock"]) + + for annex in annexed_files: + shutil.copy(annex, sources_dir) + finally: + 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, module) + 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] + + 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) + + try: + shutil.copy(result, output) + except Exception as error: + module.fail_json(msg='Failed to srpm build', command=' '.join(command), output=error) + + path = "%s/%s" % (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) + 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..efc6fa43 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('') }}" 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 93b59862..3dd39964 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -655,10 +655,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-1.src.rpm') @obal_cli_test(repotype='upstream') @@ -666,8 +665,8 @@ 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", + "rpmbuild -bs {pwd}/SRPMs/packages/hello/hello.spec", + "rpmbuild -bs {pwd}/SRPMs/packages/foo/foo.spec", "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" ] assert_mockbin_log(expected_log)