summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2025-03-29 06:59:40 +0000
committerCoprDistGit <infra@openeuler.org>2025-03-29 06:59:40 +0000
commitde4e8c7fc5220c8eea5a7b2110a10ad0673205a5 (patch)
tree1ccab56fc7ab390613b7bef51c1d75cbcd01972a
parent0a886502463cf9904e7903d2ea2a1ac8792cafe8 (diff)
automatic import of copr-backendopeneuler24.03_LTS_SP1
-rw-r--r--copr-backend.spec1440
-rw-r--r--euler_msgbus.patch83
-rw-r--r--fail_to_build_in_oe2403.patch14
-rw-r--r--signatrust_bin.patch105
-rw-r--r--sources4
-rw-r--r--support_signatrust_backend.patch953
6 files changed, 1417 insertions, 1182 deletions
diff --git a/copr-backend.spec b/copr-backend.spec
index c70cb5a..2bf37e4 100644
--- a/copr-backend.spec
+++ b/copr-backend.spec
@@ -1,12 +1,16 @@
+%if 0%{?rhel} <= 7 && 0%{?rhel} > 0
+%global _pkgdocdir %{_docdir}/%{name}-%{version}
+%endif
+
%global prunerepo_version 1.20
-%global tests_version 5
+%global tests_version 2
%global tests_tar test-data-copr-backend
-%global copr_common_version 0.21.1.dev1
+%global copr_common_version 0.16.4.dev
Name: copr-backend
-Version: 1.177
-Release: 1
+Version: 1.168
+Release: 1%{?dist}
Summary: Backend for Copr
License: GPL-2.0-or-later
@@ -16,13 +20,7 @@ URL: https://github.com/fedora-copr/copr
# git clone %%url && cd copr
# tito build --tgz --tag %%name-%%version-%%release
Source0: %{name}-%{version}.tar.gz
-Source1: %{tests_tar}-%{tests_version}.tar.gz
-Patch1: fail_to_build_in_oe2403.patch
-Patch2: euler_msgbus.patch
-#Patch3: print_queues.patch
-#Patch4: redis_helpers.patch # should patch to copr common
-Patch5: support_signatrust_backend.patch
-Patch6: signatrust_bin.patch
+Source1: https://github.com/fedora-copr/%{tests_tar}/archive/v%{tests_version}/%{tests_tar}-%{tests_version}.tar.gz
BuildArch: noarch
BuildRequires: asciidoc
@@ -39,7 +37,6 @@ BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-copr
-BuildRequires: python3-kafka-python
BuildRequires: python3-copr-common >= %copr_common_version
BuildRequires: python3-daemon
BuildRequires: python3-dateutil
@@ -59,12 +56,9 @@ BuildRequires: python3-retask
BuildRequires: python3-setproctitle
BuildRequires: python3-sphinx
BuildRequires: python3-tabulate
-BuildRequires: python3-zstandard
-BuildRequires: python3-cachetools
BuildRequires: modulemd-tools >= 0.6
BuildRequires: prunerepo >= %prunerepo_version
BuildRequires: dnf
-BuildRequires: rpmdevtools
Requires: (copr-selinux if selinux-policy-targeted)
Requires: ansible
@@ -100,14 +94,12 @@ Requires: python3-retask
Requires: python3-setproctitle
Requires: python3-tabulate
Requires: python3-boto3
-Requires: python3-cachetools
Requires: redis
Requires: rpm-sign
Requires: rsync
Requires: modulemd-tools >= 0.6
Recommends: util-linux-core
Requires: zstd
-Requires: python3-kafka-python
Requires(post): systemd
Requires(preun): systemd
@@ -131,8 +123,7 @@ only.
%prep
-%autosetup -a1 -p1
-
+%setup -q -a 1
%build
@@ -182,6 +173,7 @@ install -d %{buildroot}%{_sysconfdir}/logstash.d
install -d %{buildroot}%{_datadir}/logstash/patterns/
cp -a conf/logstash/lighttpd.pattern %{buildroot}%{_datadir}/logstash/patterns/lighttpd.pattern
+cp -a conf/playbooks %{buildroot}%{_pkgdocdir}/
install -d %{buildroot}%{_pkgdocdir}/examples/%{_sysconfdir}/logstash.d
cp -a conf/logstash/copr_backend.conf %{buildroot}%{_pkgdocdir}/examples/%{_sysconfdir}/logstash.d/copr_backend.conf
@@ -225,6 +217,7 @@ useradd -r -g copr -G lighttpd -s /bin/bash -c "COPR user" copr
%config(noreplace) %{_sysconfdir}/logrotate.d/copr-backend
%dir %{_pkgdocdir}
%doc %{_pkgdocdir}/lighttpd
+%doc %{_pkgdocdir}/playbooks
%dir %{_sysconfdir}/copr
%config(noreplace) %attr(0640, root, copr) %{_sysconfdir}/copr/copr-be.conf
%{_unitdir}/*.service
@@ -245,11 +238,1408 @@ useradd -r -g copr -G lighttpd -s /bin/bash -c "COPR user" copr
%doc
%{_pkgdocdir}/
%exclude %{_pkgdocdir}/lighttpd
+%exclude %{_pkgdocdir}/playbooks
%changelog
-* Tue Mar 25 2025 lichaoran <pkwarcraft@hotmail.com> 1.177-1
-- Upgrade to 1.177
-* Sun Mar 23 2025 lichaoran <pkwarcraft@hotmail.com> 1.173-1
-- Upgrade to 1.173
-* Wed Mar 12 2025 lichaoran <pkwarcraft@hotmail.com> 1.168-1
-- Init package
+* Wed Apr 05 2023 Jiri Kyjovsky <j1.kyjovsky@gmail.com> 1.168-1
+- Bump version for release mess
+
+* Tue Apr 04 2023 Jiri Kyjovsky <j1.kyjovsky@gmail.com> 1.167-1
+- Run createrepo without --database
+- Make copr_messaging optional
+
+* Wed Mar 22 2023 Jiri Kyjovsky <j1.kyjovsky@gmail.com> 1.166-1
+- Don't include package name into srpm result dir name
+- Remove libmodulemd1 dependency
+- Hardlink RPMs while doing rawhide_to_release
+- Make sign key domain name configurable
+* Wed Jan 25 2023 Jakub Kadlcik <frostyx@email.cz> 1.165-1
+- Skip the test_run_prunerepo test because of Koji
+
+* Tue Jan 24 2023 Jakub Kadlcik <frostyx@email.cz> 1.164-1
+- Fix chroot version parsing with new python-packaging
+- Fix traceback for non-existing tasks
+- Python: drop the unneeded marshmallow dep
+- Log general exceptions to find issues more easily
+- Proper log argument formatting instead of .format
+- Use spdx license
+
+* Wed Nov 30 2022 Pavel Raiskup <praiskup@redhat.com> 1.163-1
+- start systemd services after the redis.service
+- build worker - list the built RPMs with rpm --nosignature
+
+* Sat Nov 26 2022 Jakub Kadlcik <frostyx@email.cz> 1.162-1
+- use OpenPGP v4 signatures
+- migrate from pipes to shlex
+- require redis.service to be started
+- move to GitHub home page
+- add resultdir cleaner
+- move dispatcher and background workers to copr-common
+- de-prio IO for the analyze-results script
+- don't traceback when there are no files in the S3 storage
+- allow devel instance to remove access files
+- send non-CDN hitcounter hits in chunks
+- copr-backend-unknown-resalloc-tickets script
+- work with multiple CDN hostnames per instance
+- move setup_script_logger to copr-common
+
+* Mon Sep 26 2022 Pavel Raiskup <praiskup@redhat.com> 1.161-1
+- sign everything EPEL-5+ with sha256 hashalgo
+
+* Tue Sep 20 2022 Jakub Kadlcik <frostyx@email.cz> 1.160-1
+- aws-hitcounter: remove temporary files as soon as possible
+- aws-hitcounter: ignore downloaded SRPM files
+- aws-hitcounter: decode special characters from URLs
+
+* Tue Aug 16 2022 Pavel Raiskup <praiskup@redhat.com> 1.159-1
+- count only hits from an appropriate CDN hostname
+- add option for infinite number of attempts to the hitcounter script
+- print more reasonable output from AWS hitcounter script
+
+* Tue Aug 16 2022 Jiri Kyjovsky <j1.kyjovsky@gmail.com> 1.158-1
+- log every request that is sent to frontend
+
+* Tue Jul 26 2022 Jakub Kadlcik <frostyx@email.cz> 1.157-1
+- Don't use --keep-all-metadata
+- Search for comps.xml in chroot dir
+
+* Tue Jun 21 2022 Jakub Kadlcik <frostyx@email.cz> 1.156-1
+- Consolidate the two hitcounter scripts
+- Dump Resalloc ticket ID and hostname to backend.log
+- Automatically restart services in %%post
+- Don't count RPMs downloaded from Mock
+- Attempt to sign multiple times
+- Try multiple attempts of creating GPG keys
+
+* Mon Apr 04 2022 Pavel Raiskup <praiskup@redhat.com> 1.155-1
+- fix slow priority queue filling
+- speedup the background-process spawner
+
+* Fri Mar 18 2022 Pavel Raiskup <praiskup@redhat.com> 1.154-1
+- copr_fix_gpg: automatically refresh CDN cache
+- copr_fix_gpg: don't use --skip-stat for copr-repo when RPMs are re-signed
+- action processor: properly return failures of the fork action
+- sign EL8+ with sha256 hash algorithm
+- copr_fix_gpg: add a new --chroot option
+- copr_fix_gpg: skip non-chroot directories
+- add hitcounter script for AWS CDN
+- backend: tasks in concurrent sandboxes reprioritized to be more fair
+
+* Wed Feb 02 2022 Silvie Chlupova <schlupov@redhat.com> 1.153-1
+- less aggressive final_prunerepo setting
+- analyze-results: dump data for projects' chroots
+- basic build tagging
+- better "regenerate repo" instructions
+- limit RubyGems and PyPI package names length
+- Disable coverage analysis during RPM build
+- python code for removing unused tarballs on dist-git server
+
+* Wed Nov 10 2021 Silvie Chlupova <schlupov@redhat.com> 1.152-1
+- Fixup ACR handling
+- Drop the unused pid file from the specfile
+* Thu Sep 30 2021 Silvie Chlupova 1.151-1
+- backend: use lock(timeout=5) to work-around fair-locks
+
+* Wed Aug 25 2021 Pavel Raiskup <praiskup@redhat.com> 1.150-1
+- request arch_noarch resalloc tag for source RPM builds
+- re-try /bin/sign call upon connection timeout
+- drop 'check_consecutive_build_fails' script
+
+* Tue Jun 15 2021 Pavel Raiskup <praiskup@redhat.com> 1.149-1
+- new weekly cron-job for analyzing storage use (graphs, statistics)
+- added some convenience globals into copr_backend.setup module
+- keep the max batch size really on the MAX_IN_BATCH limit
+- require up2date rpmbuild version
+- new action for removing CoprDirs (triggered by cron on frontend)
+- fix the CompsUpdate action
+- users now can disable appstream metadata generation themselves (without admins asistance)
+- handle results.json given by builder, and provide it to frontend (served as APIv3 later)
+- pruner: allow pruning also the finalized chroots on demand
+- invent FE-BE API version, so backend politely waits for an updated copr-frontend version
+
+* Thu May 13 2021 Pavel Raiskup <praiskup@redhat.com> 1.148-1
+- work with builders also over ipv6
+
+* Sun May 02 2021 Pavel Raiskup <praiskup@redhat.com> 1.147-1
+- fix logging traceback for module builds
+- call creatrepo_c with --update if possible
+- don't do full createrpeo with --rpms-to-remove
+
+* Fri Apr 30 2021 Pavel Raiskup <praiskup@redhat.com> 1.146-1
+- better fixes for the appstream-builder generated files
+- new helper script named /bin/copr-assure-permissions
+- do not rsync-copy permissions from the builder
+- log the partial "prunerepo" effects into resultdir
+- better, more verbose call_copr_repo logging
+
+* Tue Apr 27 2021 Jakub Kadlcik <frostyx@email.cz> 1.145-1
+- backend: make the walk_limited test not dependend on its output order, pt2
+
+* Tue Apr 27 2021 Jakub Kadlcik <frostyx@email.cz> 1.144-1
+- backend: make the walk_limited test not dependend on its output order
+
+* Tue Apr 27 2021 Jakub Kadlcik <frostyx@email.cz> 1.143-1
+- backend: fix copr_prune_results logging once more
+- backend: better logging in prunerepo
+- backend: prunerepo: don't re-createrepo when no rpm is removed
+- backend: catch correct client exceptions in copr_prune_results
+- test: backend: change prunerepo logic, use get_rpms_to_remove from prunerepo
+- backend: new fixture for testing prunerepo
+- backend: use safe defaults if APIv3 result doesn't contain what it should
+- backend: migrate to APIv3
+- backend: better how-to-redirect logs comment
+- backend, frontend, keygen, distgit: keep cca 3 months of logs
+- backend: don't createrepo in srpm-builds on delete
+- backend: test walk_limited function from helpers
+
+* Tue Mar 16 2021 Pavel Raiskup <praiskup@redhat.com> 1.142-1
+- prepare for the centos-stream-8 rename
+- add script to prune srpm-build directories
+- pruner: correctly deliver the final prunerepo stamp to frontend
+- pruner: logging through RedisLogHandler
+- pruner: better parallelization
+- pruner: re-try be-fe communication upon failures
+- require up2date modulemd-tools
+
+* Wed Jan 20 2021 Pavel Raiskup <praiskup@redhat.com> 1.141-1
+- run prunerepo in parallel
+- add one-shot copr_find_wrong_chroot_artifacts.py script
+- support modulemd v2
+
+* Tue Dec 01 2020 Pavel Raiskup <praiskup@redhat.com> 1.140-1
+- fix frontend-client post arguments
+
+* Mon Nov 30 2020 Pavel Raiskup <praiskup@redhat.com> 1.139-1
+- require appropriate common version
+- use common for repeatedly sends requests to frontend
+
+* Mon Nov 30 2020 Pavel Raiskup <praiskup@redhat.com> 1.138-1
+- get back to using standard createrepo_c command from createrepo_mod
+- drop call to stomp's conn.start() (it was dropped)
+
+* Mon Nov 09 2020 Jakub Kadlcik <frostyx@email.cz> 1.137-1
+- backend: test action for deleting chroot
+- backend: fix testsuite for the new createrepo_c
+- frontend: don't set ended_on for canceled builds
+- all: run pytest with -vv in package build
+- common, cli, python, rpmbuild, frontend, backend: DistGit source method
+- backend: use createrepo_mod tool for generating module repodata
+
+* Wed Aug 12 2020 Pavel Raiskup <praiskup@redhat.com> 1.136-1
+- testsuite: give more time to the slow Koji builders
+
+* Mon Aug 10 2020 Pavel Raiskup <praiskup@redhat.com> 1.135-1
+- prioritize all non-background jobs
+- fix up libmodulemd dependency
+
+* Fri Jun 19 2020 Pavel Raiskup <praiskup@redhat.com> 1.134-1
+- fix copr-repo to work with absolute paths
+- automatically batch the createrepo requests
+- scheduler is now fair, and ordered
+- indefinitely retry workers' talk to frontend
+- allow canceling also "starting" builds
+- more verbose delete action in logs
+- cleanup the example configuration
+- use FileHandler for backend.log, fixes traceback
+
+* Tue Jun 09 2020 Pavel Raiskup <praiskup@redhat.com> 1.133-1
+- better build task priority processing
+- dump attempt to send message to backend.log
+- drop the VMM concept, replaced with resalloc
+- delegate more work to the builder code
+- external blob tarball for unittests
+- buggy error handler in pkg_name_evr()
+- basic build task priority
+- the reschedule-all builds idiom removed
+- fix the build cancelation
+- drop duplicate BuildRequire on python-requests
+- require the newest version of copr-common
+- minimalize the transfered amount of information about actions from FE
+- process actions in regard to their priority
+- move backend's code to standard PYTHONPATH
+- move ActionResult to copr_common.enums
+- actions/builds use the same WorkerManager logic
+- more verbose rawhide to release action processing
+
+* Wed Feb 05 2020 Pavel Raiskup <praiskup@redhat.com> 1.132-1
+- better handle invalid options in copr-repo --add/--delete
+- copr-repo: optimize-out useless createrepo_c runs
+- move initial createrepo check from dispatcher to worker
+- don't send messages on bus N-times
+- /bin/copr-repo now respects .disable-appstream files
+- drop unused build_deleting_without_createrepo option
+
+* Wed Jan 15 2020 Tomas Hrnciar <thrnciar@redhat.com> 1.131-1
+- put build-ID.log file to resultdir
+- call call_copr_repo if initial createrepo failed
+- Build Dispatcher does not wait forever till repo is created,
+ it creates it manually
+- properly delete logs for old builds
+- delete build-ID.log files again
+- edit repositories only by new 'copr-repo' tool
+- fix multi-build delete
+- fix for not saving end time of actions
+- lower traffic in build_dispatcher log
+- more resilient redis logging
+- attempt to publish on msgbus N-times
+- log service: move RequiredBy to [Install]
+- keep worker ID in proc title
+
+* Fri Dec 06 2019 Pavel Raiskup <praiskup@redhat.com> 1.130-1
+- backend: execute actions with sane umask=0022
+
+* Wed Dec 04 2019 Pavel Raiskup <praiskup@redhat.com> 1.129-1
+- do not start a build if copr_base is not available yet
+- systemd services' restart re-ordering
+- de-duplicate frontend_.update() call when reattaching to existing build
+- allow specifying timeout for spawn/terminate playbooks
+- removing dependecy on euca2ools in spec
+- send `uses_devel_repo' as a part of task info
+- correctly configure logrotate
+- get_redis_logger: skip log entries bellow log_level
+- delete leftover action workers from redis
+
+* Fri Oct 11 2019 Pavel Raiskup <praiskup@redhat.com> 1.128-1
+- restart copr-backend sub-services on failure
+- don't kill action processors by 'systemctl restart'
+- lower the log traffic in build_dispatcher.log
+
+* Thu Oct 03 2019 Pavel Raiskup <praiskup@redhat.com> 1.127-1
+- fix testsuite for slow Koji builders
+
+* Thu Oct 03 2019 Pavel Raiskup <praiskup@redhat.com> 1.126-1
+- more reliable communication with frontend (#1021)
+- only ask for auto_createrepo once per project
+- parallel handling of actions (#1007)
+- don't provide builder-live.log once the build ended, and
+ add 'copr-compress-live-logs' helper (#985)
+- less exceptions in logs
+- project forking fixes
+- depend on copr-messaging, not fedora-messaging
+- fixes for copr_print_results_to_delete.py script
+
+* Wed Aug 28 2019 Dominik Turecek <dturecek@redhat.com> 1.125-1
+- minimize redis traffic for looping over pending-jobs (issue#902)
+- batch delete builds into a single action (issue#688)
+- admin opt-out createrepo after build-deleting
+- fix wrong message validation class
+- refine cleanup_vm_nova.py
+- depend on copr-messaging
+
+* Mon Jul 29 2019 Pavel Raiskup <praiskup@redhat.com> 1.124-1
+- run createrepo immediately, don't wait for build (issue#833)
+- compress backend-live.log by calling gzip (issue#86)
+- use copr-messaging module for validating outgoing messages
+- don't run appstream-builder for PR dirs
+- don't run createrepo for srpm directories
+- skip VMs with failing live-check in scheduler
+- sandbox builds per user/submitter/project
+- drop unused compat code for droped /bin/copr-builder
+- do not call appstream builder with --max-threads (issue#717)
+- added copr_print_results_to_delete.py script, should help
+ us with removal of orphaned resources on backend storage (issue#712)
+- allow disabling appstream builder per project (issue#738)
+- tabular output from copr_get_vm_info.py
+
+* Wed Apr 24 2019 Jakub Kadlčík <frostyx@email.cz> 1.123-1
+- clean data for failed builds; fix #619
+- replace runnecessary regex with str.endswith
+- move clean_copr from prunerepo to our codebase
+- cleanup_vm_nova.py: use yaml.safe_load
+- don't rely on createrepo from prunerepo
+- simplify logging through redis
+- run sign command without sudo to fix #636
+- encode 'msg' in LogRecord sooner
+- fix charset warnings on redis-py v3
+- fix default arguments in redis scripts
+- don't prunerepo too old directories
+- LogHandler: don't drop exc_info from LogRecord
+- use the correct data for rawhide_to_release createrepo
+- make copr_prune_results skip already pruned outdated chroots
+- require libmodulemd in at least 1.7.0
+- remove dependency on python3-configparser
+
+* Mon Feb 11 2019 Jakub Kadlčík <frostyx@email.cz> 1.122-1
+- Add requires python3-novaclient
+- Set the architecture for which the module has been built
+- Generate module artifacts in the correct format
+- Compress the modules.yaml file
+
+* Fri Jan 11 2019 Miroslav Suchý <msuchy@redhat.com> 1.121-1
+- remove data from outdated chroots
+
+* Thu Jan 10 2019 Miroslav Suchý <msuchy@redhat.com> 1.120-1
+- update list of copr services
+- Use oslo_concurrency for craeterepo locking
+- use run_cmd() in pkg_name_evr()
+- drop "downloading" state
+- allow blacklisting packages from chroots
+
+* Fri Oct 19 2018 Miroslav Suchý <msuchy@redhat.com> 1.119-1
+- optimize copr_log_hitcounter.py for speed a bit
+- move selinux rules to copr-selinux
+- fix traceback for non-serializable log message
+- fix tracebacks in copr-backend-log
+- more robust run_tests.sh
+- remove unused imports
+- py3 compat for msgbus support
+- use git_dir_archive instead of git_dir_pack
+- migrate from deprecated python3-modulemd to libmodulemd
+- doc: remove warning that _static directory does not exists
+- doc: the undeline need to be at least as long as the title
+
+* Thu Aug 23 2018 clime <clime@redhat.com> 1.118-1
+- fix logging exception
+- send proper arguments for rawhide_to_release
+- packaging: Python 2/3, RHEL/Fedora fixes
+
+* Mon Aug 06 2018 clime <clime@redhat.com> 1.117-1
+- None task protection
+- pagure integration
+- use manual .pyc file generation
+- remove unused imports, ad. pr#327
+- resolving pylint warnings
+- for py3 use unittest.mock
+- fix msgbus ContentType to application/json
+
+* Fri May 18 2018 clime <clime@redhat.com> 1.116-1
+- fix #291 forks are incomplete
+- log more information about incoming actions
+- preparation for opensuse-leap-15.0-x86_64
+
+* Thu Apr 26 2018 Dominik Turecek <dturecek@redhat.com> 1.115-1
+- rpkg deployment into COPR - containers + releng continuation
+- fix pagure bugs #269, #273, #221 and #268
+- cleanup in test_helpers, one test added
+- change order of args in StrictRedis call
+- add comment about expected usage of the copr_log_hitcounter script
+- try to send hit data to frontend several times from
+copr_log_hitcounter
+
+* Mon Feb 26 2018 clime <clime@redhat.com> 1.114-1
+- add possibility for copr_log_hitcounter to ignore multiple subnets
+
+* Fri Feb 23 2018 clime <clime@redhat.com> 1.113-1
+- original builder deprecation
+- remove Group tag
+
+* Mon Feb 19 2018 clime <clime@redhat.com> 1.112-1
+- Shebangs cleanup
+- escapes in changelogs
+
+* Sun Feb 18 2018 clime <clime@redhat.com> 1.111-1
+- use netaddr instead of IPy module
+- sleep after each load_jobs iteration
+- python3 conversion
+- UMB: adding content type
+- add source_status field for Builds
+- generate module artifacts rpms
+- the rsync log is actually renderred directly into result dir now
+- mockchain.log renamed to backend.log
+- pg#192 missing records in mockchain.log
+- enable running tests in spec file
+- enable and update vmmamanger tests, fix three minor bugs in the
+ manager
+- frontend now presents the whole job queue state to
+ backend
+- copy only module builds into the repo directory
+
+* Wed Dec 20 2017 clime <clime@redhat.com> 1.110-1
+- exception handling for hit counting when IP address cannot be parsed
+
+* Mon Dec 18 2017 Dominik Turecek <dturecek@redhat.com> 1.109-1
+- terminate also 'in_use' builders if health checks have failed
+- make --detached the last arg for copr-rpmbuild
+- update copr_log_hitcounter to check ip against ignored pattern
+- new msg bus options
+- disable DNF makecache timer/service
+- fix message duplication for multi-bus scenario
+
+* Thu Nov 16 2017 Miroslav Suchý <msuchy@redhat.com> 1.108-1
+- optimize createrepo_c
+- Revert "[backend] remove --ignore-lock from createrepo_c"
+
+* Thu Nov 09 2017 clime <clime@redhat.com> 1.107-1
+- kill all processes in copr-rpmbuild's process group
+- add --drop-resultdir switch to copr-rpmbuild call
+- release_vm immediately after VM is no longer needed
+- remove --ignore-lock from createrepo_c
+
+* Wed Oct 18 2017 clime <clime@redhat.com> 1.106-1
+- run copr-rpmbuild with --verbose option
+
+* Wed Sep 27 2017 clime <clime@redhat.com> 1.105-1
+- remove uneeded yum dep
+
+* Tue Sep 26 2017 clime <clime@redhat.com> 1.104-1
+- update copr-rpmbuild command for the new options
+- change arguments to build_id and chroot
+- #128 AppStream data collection vetoes addons
+- fix rpm download stats collection
+- module-stuff update
+
+* Fri Sep 15 2017 clime <clime@redhat.com> 1.103-1
+- update fedora image version to 26
+- fixes for recent code
+
+* Thu Sep 07 2017 clime <clime@redhat.com> 1.102-1
+- srpms are now being built from upstream on builders
+
+* Wed Jun 14 2017 clime <clime@redhat.com> 1.101-1
+- remove unused helpers.run_ssh + function spacing fixup
+- cancel-build action fix
+
+* Fri Jun 09 2017 clime <clime@redhat.com> 1.100-1
+- extend check for a builder package present on a builder machine
+- arbitrary dist-git branching
+- remove --add-cache-id from appstream-builder call, see Bug 1426166
+- change to using a standalone builder package
+
+* Wed May 03 2017 clime <clime@redhat.com> 1.99-1
+- missing on_success_build call added back to sign packages and recreate repo after each build
+
+* Mon Apr 24 2017 clime <clime@redhat.com> 1.98-1
+- Bug 1444804 - Logs are not present for failed builds
+
+* Wed Apr 19 2017 clime <clime@redhat.com> 1.97-1
+- do not condrestart optional logstash service
+- standalone builder option
+- build reattaching after copr-backend(-build) service restart
+- live mockchain log
+- use openssh instead of paramiko
+- update cleanup_vm_nova script
+- remove buggy logging
+- removed Sphinx as a dependency...
+- verbose log everything we have about failed playbook
+- replace fedorahosted links
+- make systemd services out of ActionDispatcher and BuildDispatcher
+
+* Thu Jan 26 2017 clime <clime@redhat.com> 1.96-1
+- Fixes for building COPR Backend and Dist-git on EL7
+- simplified/improved logging of exceptions mainly
+- don't use sha256 checksum for rhel-5* repos, too
+- drop mentions of the max_builds_per_vm optoin
+- switched usage of deprecated ansible Runner for python-paramiko module
+- os_nova filter plugin fixed for python-novaclient 3
+- support for STOMP msg buses
+- fix Bug 1402689 regarding job cancellation
+- jobgrab service is no more
+- respect 'do_sign' option when forking
+- fix buildroot_cmd for rhel mock profiles
+
+* Thu Dec 01 2016 clime <clime@redhat.com> 1.95-1
+- use buildroot_pkgs substitution type according to job.chroot
+- use timeout command to respect timeout param coming from frontend
+- don't ship unitfiles in %%bindir
+- move createrepo to the end of the rawhide_to_release handler
+- modulemd 1.0.2 compatibility
+- Bug 1397119 - Error reading SSH protocol banner
+- added auto-prune project's option
+- Bug 1086139 - [RFE] provide UI to cancel a build
+- Fix misleading debug statement
+- fix exception logging in ensure_dir_exists helper
+- Fix chroot_setup_cmd regex for custom chroot
+
+* Mon Sep 19 2016 clime <clime@redhat.com> 1.94-1
+- also provide default version and release for generated modules.json
+
+* Mon Sep 19 2016 clime <clime@redhat.com> 1.93-1
+- fix NameError: global name 'result' is not defined
+- fix exception logging
+- Modularity support
+- Bug 1357564 - RFE: allow downloading of mock profiles (reproducible builds)
+- "safer" exception handling for actions
+
+* Mon Aug 15 2016 clime <clime@redhat.com> 1.92-1
+- wrap feedback about actions to frontend into try-except
+- log even the traceback from forking
+- use makedirs instead of mkpath in fork action
+- if anything bad happens, log exception in generate_gpg_key action
+- also restart copr-backend-vmm and copr-backend-log when (re)installing
+- Bug 1361344 - RFE: Allow denial of build deletion and resubmitting at project or group level
+- catch errors in fork action
+- set action result for comps.xml and module_md.yaml file deletion
+- backend fork action now takes care of new gpg-key generation instead of frontend
+- removed no longer supported --api-version=0.8 arg from appstream-builder command line
+- specify module_md as module type
+- fix saving comps.xml and module_md.yaml into empty copr (with no build)
+- module_md.yaml is added to repodata now similarly to appstream.xml
+- support for generation of module dist tags
+- module_md.yaml uploading for a chroot
+- simplified build and action task workflow
+- use copy of the mock (chroot) config, not the original in /etc/mock/
+
+* Wed Jun 22 2016 Miroslav Suchý <msuchy@redhat.com> 1.91-1
+- configure more packages to run pylint
+- terminate machine which was only partially spawned
+- [copr-prune-results] do not sys.exit if prunerepo returns non-zero status,
+ just raise an exception
+- more of log file migration
+- claim /var/log/copr-backend in %%files
+- adjust log path in runtime files
+- update conf file log path directives
+- change logdir to /var/log/copr-backend/
+
+* Fri May 27 2016 Miroslav Suchý <msuchy@redhat.com> 1.90-1
+- do not use --log-dir in appstream-builder
+
+* Tue May 24 2016 Miroslav Suchý <miroslav@suchy.cz> 1.89-1
+- use correct conditional in requires
+
+* Mon May 23 2016 Miroslav Suchý <msuchy@redhat.com> 1.88-1
+- backend: change logstash requires to soft requires
+- 1336360 - allow custom chroots
+
+* Fri May 13 2016 Miroslav Suchý <msuchy@redhat.com> 1.87-1
+- workaround for BZ 1334200
+- more info in logs by default
+- print seconds just as int
+- unsign gpg from forked packages before signing them with new key
+- sign forked packages @TODO We need to delsign them first
+
+* Fri May 06 2016 Miroslav Suchý <msuchy@redhat.com> 1.86-1
+- more info in logs by default
+- unsign gpg from forked packages before signing them with new key
+
+* Thu May 05 2016 Miroslav Suchý <msuchy@redhat.com> 1.85-1
+- also be tolerant about sign/unsign failures on particular rpm
+- just log errors (exception) during particular copr fixing, do not
+ interrupt the whole process
+- added additional check on copr path existence into copr_fix_gpg.py
+- allow sudo /usr/bin/rpm for `copr` user
+- look into build dirs (subdirs of a chroot) for rpms to be re-signed
+- on F24+ use just ansible
+- Run rpm-sign with sudo when unsigning
+- script to fix gpg keys & rpm signatures
+- define functions for deleting gpg signatures from packages
+- removed temporary mock workaround from Dockerfile (no
+ longer needed)
+
+* Thu Apr 28 2016 Miroslav Suchý <msuchy@redhat.com> 1.84-1
+- Bug 1327996 - config_opts['use_host_resolv'] is not set back to
+ True if it was False before
+
+* Fri Apr 22 2016 Miroslav Suchý <msuchy@redhat.com> 1.83-1
+- run createrepo on forked project (RhBug: 1329076)
+- Bug 1327852 - /usr/bin/check_consecutive_build_fails.py errors
+- we need to stick to ansible1.9
+- more escaping
+- prunning down testresults :)
+- a few unittests for copr_prune_results.py script
+- unit test "fixes"
+- fix error when forking into existing project
+- (mockremote): improve chroot_setup_cmd replacement for EL-5
+- copr_prune_results.py - python path fix
+- Bug 1324514 - copr createrepo error messages - fix for errors of
+ type one
+- Bug 1324514 - copr createrepo error messages - fix for errors of
+ type 2
+
+* Thu Mar 24 2016 Jakub Kadlčík <jkadlcik@redhat.com> 1.82-1
+- use timeout variable from config
+
+* Mon Mar 14 2016 Jakub Kadlčík <jkadlcik@redhat.com> 1.81-1
+- support project forking
+- support building from PyPI
+- support for redis_host, redis_port, redis_db config options
+- dockerized-backend project moved under backend/docker
+- run createrepo in rawhide_to_release
+- specify rawhide name when calling rawhide_to_release
+
+* Fri Jan 29 2016 Miroslav Suchý <msuchy@redhat.com> 1.80-1
+- do not fail when when you receive job with architecture which does not have
+ queue
+- fix 1260780 - Build fails after successful package generation -
+ just add a log error message pointing to an rsync log
+- jobgrabcontrol.py/retask misuse fix
+- "localhost-targeted" spawn and terminate playbooks added for testing
+- [frontend]implement rawhide to release feature First create new
+ chroots: python manage.py create_chroot fedora-24-i386 fedora-24-x86_64
+- abstraction above [BE <-> JG <-> Builders] channels
+- don't traceback backend if frontend is not yet up&running
+- do not preserve user and group when rsyncing
+
+* Wed Dec 23 2015 Miroslav Suchý <msuchy@redhat.com> 1.79-1
+- fix packaging issues in epel-7+
+
+* Mon Nov 16 2015 Miroslav Suchý <miroslav@suchy.cz> 1.78-1
+- handle_generate_gpg_key skips key creation when signing is disabled
+- Added test_handle_generate_gpg_key
+- fixed failing tests
+- show when createrepo is waiting for lock
+- do not block builds when processing too much actions
+
+* Fri Nov 06 2015 Miroslav Suchý <msuchy@redhat.com> 1.77-1
+- we need to have recent python-copr
+- create copr-backend-service script to handle all copr services
+- [backend] fix not starting job_grab
+
+* Tue Oct 13 2015 Miroslav Suchý <msuchy@redhat.com> 1.76-1
+- createrepo action run infinitely when applied to
+ deleted project
+
+* Mon Sep 21 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.75-1
+- [backend] run copr-backend-log service before other components
+
+* Mon Sep 21 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.74-1
+- [backend] add executable bit to run/copr_run_job_grab.py
+
+* Mon Sep 21 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.73-1
+- added context manager `local_file_logger`
+- eliminated global multiprocessing.Lock
+- split backend daemon: extracted RedisLogHandler, JobGrab, VMM
+- replace python-bunch with python-munch
+- added comps.xml support
+
+* Tue Aug 04 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.72-1
+- support new results naming in the build deletion action
+- fix BuildJob.results_dir; eliminated MockRemote.pkg_dest_path
+- using package name and versiong given in the build task; cleanup;
+- handle error's caused by failure to obtain srpm from dist-git
+- repairing test for newest changes
+- rsync update + several fixes
+- building from dist git
+- fix vm spawn check: spawner count child processes per build group;
+
+* Wed Jul 01 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.71-1
+- add small script to print queues
+- AppData supproted
+- copy mockchain and rsync logs to resdir (RhBug:1221519)
+- note which modules still stops us from migrating to python3
+
+* Mon Jun 15 2015 Miroslav Suchý <msuchy@redhat.com> 1.70-1
+- alter vm_name= regexp
+- polishing Bug 1195867 - Move or delete logs when rebuilding failed
+ build.
+- backup only info and log files
+- have just one backup directory per results directory
+- clean results from previous build
+- alter IP= regexp
+- disabled appdata until fixed
+- unable appdata in createrepo
+- more safe VmMaster.check_one_vm_for_dead_builder function
+- adding support for AppData
+- new requirement form AppData support
+- createrepo_unsafe now returns only STDOUT and raise exception on
+ errors
+
+* Mon Jun 01 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.69-1
+- removed creation of symlinks for log.gz
+- catch exception during Worker.can_start_job
+- config cleanup
+
+* Thu May 28 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.68-1
+- [backend] add config option for VM health check timeout
+- [backend] moved config parameters from Threshold class into the backend
+ config file
+
+* Thu May 21 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.67-1
+- [backend] Handle unexpected exception VmMaster::check_one_vm_for_dead_builder
+
+* Thu May 21 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.66-1
+- [backend] fix race condition in check for dead worker
+
+* Wed May 20 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.65-1
+- [backend] Rescheduling unfinished builds before stop
+- fix indentation
+- [backend] request frontend to reschedule old unfinished builds at startup
+- [backend] update sytemd unit: removed obsolete
+ EnviromentFile=/home/copr/cloud/ec2rc.variable directive
+
+* Tue May 19 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.64-1
+- [backend] check for aux process state and restart if needed
+
+* Fri May 15 2015 Miroslav Suchý <msuchy@redhat.com> 1.63-1
+- BR python-sphinx
+
+* Fri May 15 2015 Miroslav Suchý <msuchy@redhat.com> 1.62-1
+- [backend] small cleanup, need more tests
+
+* Fri May 15 2015 Miroslav Suchý <msuchy@redhat.com> 1.61-1
+- [backend] notify job_grab to remove job from added when start_job failed
+- [backend] [vmm] terminate VM with state IN_USE only when builder process is
+ missed
+- [backend] bugfix VMM.get_all_vm_in_group : VM could be removed before load
+ occures
+- [backend] job_grab: postpone build is we already serving more builds
+ than`max_vm_per_user` option
+- [backend] fix build logging
+- [backend] defer sending job to worker if job owner acquired too much VMs
+- [backend] replaced Thresholds.dirty_vm_terminating_timeout with config option
+ vm_dirty_terminating_timeout
+- [backend] Thread's doesn't have a pid
+- [backend] vm manage: user threading instead of multiprocessing
+- [backend] VMM aware cleunup_vm_nova
+- [backend] moving to nginx to serve results. lighttpd couldnt server pre-
+ compressed properly
+- [backend] script to clean up erred and forgotten VM's using python-novaclient
+- [backend] new documentation
+- [backend] repaired unittests
+- [backend] updated builder playbooks
+- [backend] updated example spawn playbook
+- [backend] don't provide logstash config directly, add only example to
+ documentation
+- [backend] do logging from multiply processes through redis pubsub; some fixes
+ to VM-management
+- [image_builder] initial release, due to OS bug, we cannot create snapshot
+ after provision through API, need to do it manually in the WebUI.
+- [backend] tests cleanup
+- [backend] ensure that prune script running under the copr user; simpler
+ `copr_find_obsolete_builds`
+- [backend] safer copr_prune_results script, unittests
+- [backend][frontend] Send for delete action only `src_pkg_name` instead of
+ original URL.
+- [backend] returned script to call createrepo from cli
+- [copr] don't allow acquire VMs that was last checked before server restart.
+- [backend] Added limit to acquire_vm based on VMs used by the same username at
+ the current moment.
+- New python dependencies
+- [backend] run tmp redis-server for tests
+- [backend] Dedicated and more complex management for builder machines.
+ [frontend] Now builds failed due to VM errors reschedulted faster.
+
+* Fri Mar 20 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.60-1
+- [backend][spec] start/stop redis server during package build tests
+
+* Fri Mar 20 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.59-1
+- [backend][hotfix] 1203753 : don't process delete action if src_pkg is
+ mallformed
+
+* Mon Mar 02 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.58-1
+- [rhbz:#1185959] - RFE: Present statistics about project
+ popularity. A few more counters for downloads from backend's result
+ directory.
+- [backend] [rhbz:#1191037] RFE: Include package name and version in fedmsg
+ notification
+- [rhbz:#1091640] RFE: Release specific additional repos
+- [rhbz:#1119300] [RFE] allow easy add copr repos in using
+ repository lis
+- [backend][frontend] removing code related to multiply source rpms in build.
+ Build.pkgs now expected to have exactly one src.rpm.
+- [copr] backend: script fixes, dropped create_repo cli script
+- more file descriptors on builder
+- [rhbz:#1171796] copr sometimes doesn't delete build from repository
+- [rhbz:#1073333] Record consecutive builds fails to redis. Added
+ script to produce warnings for nagios check from failures recorded to redis.
+- correctly print job representation
+
+* Fri Jan 23 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.57-1
+- call correct Worker method on backend termination
+- put gpg pubkey to the project results root dir (one level up from
+ the chroot dir)
+- don't kill Worker from errors during job build
+- [rhbz:#1169782] RFE - Show package "version-release" instead of
+ just "version"
+- [rhbz:#1117446] add a build id tagfile into the package directory
+- Updated unittests to reflect latest changes.
+- builder: use only one log file for rsync per build
+- dispatcher: run terminate_instance safely
+- cleanup example config
+- cleanup mockremote.builder
+- Builder.download don't use Popen+PIPE.communicate with rsync,
+ output redirected to the files.
+- disable networking only when required; python style exception
+ handling in mockremote*; removed run/copr_mockremote
+- test build with disabled networking
+- simplified mockremote.builder.Builder.check_for_ans_error; new
+ method mockremote.builder.Builder.run_ansible_with_check
+- daemons.dispatched.Worker: don't fail when wrong group_id was
+ provided
+- add vm_ip to worker process title (rhbz: 1182637)
+
+* Wed Jan 14 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.56-1
+- [backend] [.spec] fix %%files section
+
+* Wed Jan 14 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.55-1
+- [backend] [bugfix] set pythonpath in systemd unit to run /usr/bin/copr_be.py
+- [backend] [RHBZ:#1182106] JobGrabber dies when action raises an exception.
+- [backend] Moved scripts into /usr/bin/ Renamed copr{-,_}be.py.
+
+* Wed Jan 07 2015 Miroslav Suchý <msuchy@redhat.com> 1.54-1
+- 1179713 - workaround for 1179806
+- run script unbufferred otherwise log is written after full block
+- express that it is n-th projects
+- fix permissions on prune script
+
+* Mon Jan 05 2015 Valentin Gologuzov <vgologuz@redhat.com> 1.53-1
+- [backend, frontend] [RHBZ:#1176364] Wrong value for the build timeout.
+
+* Mon Dec 15 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.52-1
+- fixed config option `results_baseurl` usage, in mockremote
+
+* Fri Dec 12 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.51-1
+- updated BuildRequires; cleanup imports
+- package sign: generate gpg usermail with special symbol
+- bugfix: when dispatcher has vm_ip it shouldn't start new VM;
+- run tests during rpm build
+- minor docstring fix
+
+* Wed Dec 10 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.50-1
+- [backend] added option to control ansible ssh transport, changed by default
+ to `paramiko` [frontend] bugfix api create new
+- [backend] removed spawn_vars options, to be able to spawn VMs in advance
+- [backend] unittest for backend.daemons.log
+- [backend] massive refactoring and unittest coverage
+- [backend] backend.sign: discover `keygen_host` from backend config file
+
+* Tue Nov 25 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.49-1
+- [backend] small bug in dispatcher
+
+* Tue Nov 25 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.48-1
+- bugfixes, disabled debug prints, fixed PEP8 violations
+
+* Thu Nov 20 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.47-1
+- refactored mockremote, added explicit BuildJob class
+- allow to spawn builder in advance
+- copr-prune-repo respects auto_createrepo option
+- bugfix: repeated config reads produced constantly growing lists
+
+* Fri Oct 24 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.46-1
+- [backend] added handling of new action type: "createrepo"
+- [backend] added dependency on `python-copr`
+- [backend] added to mockchroot -a /devel/repodata subfolder
+- [backend] new config option to define the public frontend api endpoint
+- [backend] conditional execution of createrepo_c
+- [backend] unittest for Action and minor refactoring
+- [backend] rotate backend.log as well
+
+* Thu Sep 18 2014 Miroslav Suchý <msuchy@redhat.com> 1.45-1
+- [backend][keygen] minor fixes/typos
+
+* Thu Sep 18 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.44-1
+- [backend] type fix
+
+* Thu Sep 18 2014 Valentin Gologuzov <vgologuz@redhat.com> 1.43-1
+- [backend] config parsing: convert fields to proper data type.
+- [backend] added option to disable package signing.
+- [keygen] new component for copr: gpg key generation for package sign
+- [backend] broadcast both submitter and owner to fedmsg
+- [backend] example backend config: changes url protocol to HTTPS.
+
+* Mon Aug 25 2014 Adam Samalik <asamalik@redhat.com> 1.42-1
+- [backend] [RHBZ:1128606 ] For rhel-5 builds pass "--checksum md5" to
+ `createrepo_c` command.
+- [backend] fix of builder test
+- [backend] test builder instance after spawning
+- [backend] never give up while spawning an OpenStack VM
+- [backend] worker's log filename correction
+- [backend] task id in worker process' name
+- [backend] async build playbooks
+
+* Thu Aug 14 2014 Miroslav Suchý <miroslav@suchy.cz> 1.41-1
+- [backend] fix of fix
+- [backend] couple of fixes
+
+* Wed Aug 13 2014 Miroslav Suchý <msuchy@redhat.com> 1.40-1
+- [backend] queue cleaning
+- [backend] experimental build groups for more architectures
+- [backend] fix of a strange beaviour of retask
+- [backend] fedmsg shows submitter instead of project owner
+- [backend] new task queue for workers using retask
+- epel-7 comps workaround is need no more, since CENTOS7 have been released
+
+* Tue Jul 22 2014 Miroslav Suchý <msuchy@redhat.com> 1.39-1
+- FrontendCallback prettified
+- Starting state implemented, cancelling fixed
+- [backend] faster skipping
+
+* Tue Jul 15 2014 Miroslav Suchý <msuchy@redhat.com> 1.38-1
+- [backend] built pkgs fix
+
+* Tue Jul 15 2014 Miroslav Suchý <msuchy@redhat.com> 1.37-1
+- [backend] shell command uses pipes.quote
+- Return the chroot that finished when sending build.end
+- better and safer deleting of builds
+- [backend] separate playbooks for each architecture
+- [backend] built pkgs - include subpackages
+- [backend] skipped status and package details implemented
+- document vm_name option
+
+* Thu Jun 19 2014 Miroslav Suchý <msuchy@redhat.com> 1.36-1
+- backend: migrate to nova ansible module
+- backend: make sure that exit() exit whole script not just sub-shell
+- backend: allow passing additional info to playbooks
+- handle {spawn,terminate}_instance equally
+- backend: stop if you could not change to directory
+- W:310, 8: Attribute 'abort' defined outside __init__ (attribute-defined-
+ outside-init)
+- W:139, 0: Dangerous default value [] as argument (dangerous-default-value)
+ W:139, 0: Dangerous default value [0] as argument (dangerous-default-value)
+ W:139, 0: Dangerous default value ['stdout', 'stderr'] as argument
+ (dangerous-default-value)
+- W:543, 4: Dangerous default value DEF_MACROS ({}) as argument (dangerous-
+ default-value)
+- W:543, 4: Dangerous default value DEF_REPOS ([]) as argument (dangerous-
+ default-value)
+- W:677,24: Unused variable 'out' (unused-variable) W:677,20: Unused variable
+ 'rc' (unused-variable)
+- W:297,12: Unused variable 'hn' (unused-variable)
+- C:116, 0: Unnecessary parens after 'print' keyword (superfluous-parens)
+- W: 72,28: Unused variable 'out' (unused-variable) W: 72,24: Unused variable
+ 'rc' (unused-variable)
+- fix typo in exception message printing
+- 1102788 - Increase number of file descriptors on the build machine
+
+* Fri May 30 2014 Miroslav Suchý <msuchy@redhat.com> 1.35-1
+- follow selinux packaging draft
+- [backend] epel 5 repo fix (sha256 -> sha)
+
+* Thu Apr 24 2014 Miroslav Suchý <msuchy@redhat.com> 1.34-1
+- if directory does not exist, do not try to delete it
+
+* Tue Apr 15 2014 Miroslav Suchý <miroslav@suchy.cz> 1.33-1
+- do not publish copr.worker messages
+- better count workers
+
+* Thu Apr 10 2014 Miroslav Suchý <msuchy@redhat.com> 1.32-1
+- include ec2rc in service unit file
+
+* Wed Apr 09 2014 Miroslav Suchý <msuchy@redhat.com> 1.31-1
+- 1077791 - set perm of cronfile to 755
+- 1077791 - add LICENSE to -doc subpackage
+- 1077791 - remove make as BR
+
+* Tue Mar 18 2014 Miroslav Suchý <msuchy@redhat.com> 1.30-1
+- [backend] exclude files which are part of main package
+- copr-backend.src:113: W: mixed-use-of-spaces-and-tabs (spaces: line 5, tab:
+ line 113)
+
+* Tue Mar 18 2014 Miroslav Suchý <msuchy@redhat.com> 1.29-1
+- move backend into separate package
+
+* Thu Feb 27 2014 Miroslav Suchý <msuchy@redhat.com> 1.28-1
+- [backend] - pass lock to Actions
+
+* Wed Feb 26 2014 Miroslav Suchý <msuchy@redhat.com> 1.27-1
+- [frontend] update to jquery 1.11.0
+- [fronted] link username to fas
+- [cli] allow to build into projects of other users
+- [backend] do not create repo in destdir
+- [backend] ensure that only one createrepo is running at the same time
+- [cli] allow to get data from sent build
+- temporary workaround for BZ 1065251
+- Chroot details API now uses GET instead of POST
+- when deleting/canceling task, go to same page
+- add copr modification to web api
+- 1063311 - admin should be able to delete task
+- [frontend] Stray end tag h4.
+- [frontend] another s/coprs/projects/ rename
+- [frontend] provide info about last successful build
+- [spec] rhel5 needs group definition even in subpackage
+- [frontend] move 'you agree' text to dd
+- [frontend] add margin to chroots-set
+- [frontend] add margin to field label
+- [frontend] put disclaimer to paragraph tags
+- [frontend] use black font color
+- [frontend] use default filter instead of *_not_filled
+- [frontend] use markdown template filter
+- [frontend] use isdigit instead of is_int
+- [frontend] move Serializer to helpers
+- [frontend] fix coding style and py3 compatibility
+- [cli] fix coding style and py3 compatibility
+- [backend] fix coding style and py3 compatibility
+
+* Tue Jan 28 2014 Miroslav Suchý <miroslav@suchy.cz> 1.26-1
+- lower testing date
+- move localized_time into filters
+- [frontend] update user data after login
+- [frontend] use iso-8601 date
+
+* Mon Jan 27 2014 Miroslav Suchý <msuchy@redhat.com> 1.25-1
+- 1044085 - move timezone modification out of template and make it actually
+ work
+- clean up temp data if any
+- [db] timezone can be nullable
+- [frontend] actually save the timezone to model
+- fix colision of revision id
+- 1044085 - frontend: display time in user timezone
+- [frontend] rebuild stuck task
+- disable test on i386
+- use experimental createrepo_c to get rid of lock on temp files
+- [frontend] - do not throw ISE when build_id is malformed
+- [tests] add test for BuildLogic.add
+- [tests] add test for build resubmission
+- [frontend] permission checking is done in BuildLogic.add
+- [frontend] remove BuildLogic.new, use BL.add only
+- [api] fix validation error handling
+- [cli] fix initial_pkgs and repos not sent to backend
+- [frontend] fix BuildsLogic.new not assigning copr to build
+- [frontend] allow resubmitting builds from monitor
+- [frontend] allow GET on repeat_build
+- [frontend] 1050904 - monitor shows not submitted chroots
+- [frontend] rename active_mock_chroots to active_chroots
+- [frontend] rename MockChroot.chroot_name to .name
+- [frontend] 1054474 - drop Copr.build_count nonsense
+- [tests] fix https and repo generation
+- [tests] return exit code from manage.py test
+- 1054472 - Fix deleting multiple SRPMs
+- [spec] tighten acl on copr-be.conf
+- [backend] - add missing import
+- 1054082 - general: encode to utf8 if err in mimetext
+- [backend] lock log file before writing
+- 1055594 - mockremote: always unquote pkg url
+- 1054086 - change vendor tag
+- mockremote: rawhide instead of $releasever in repos when in rawhide chroot
+- 1055499 - do not replace version with $releasever on rawhide
+- 1055119 - do not propagate https until it is properly signed
+- fix spellings on chroot edit page
+- 1054341 - be more verbose about allowed licenses
+- 1054594 - temporary disable https in repo file
+
+* Thu Jan 16 2014 Miroslav Suchý <msuchy@redhat.com> 1.24-1
+- add BR python-markdown
+- [fronted] don't add description to .repo files
+- [spec] fix with_tests conditional
+- add build deletion
+- 1044158 - do not require fas username prior to login
+- replace http with https in copr-cli and in generated repo file
+- [cli] UX changes - explicitly state that pkgs is URL
+- 1053142 - only build copr-cli on el6
+- [frontend] correctly handle mangled chroot
+- [frontend] do not traceback when user malform url
+- [frontend] change default description and instructions to sound more
+ dangerously
+- 1052075 - do not set chroots on repeated build
+- 1052071 - do not throw ISE when copr does not exist
+
+* Mon Jan 13 2014 Miroslav Suchý <msuchy@redhat.com> 1.23-1
+- [backend] rhel7-beta do not have comps
+- 1052073 - correctly parse malformed chroot
+
+* Fri Jan 10 2014 Miroslav Suchý <msuchy@redhat.com> 1.22-1
+- [backend] if we could not spawn VM, wait a moment and try again
+- [backend] use createrepo_c instead of createrepo
+- 1050952 - check if copr_url exist in config
+- [frontend] replace newlines in description by space in repo file
+
+* Wed Jan 08 2014 Miroslav Suchý <msuchy@redhat.com> 1.21-1
+- 1049460 - correct error message
+- [cron] manually clean /var/tmp after createrepo
+
+* Wed Jan 08 2014 Miroslav Suchý <msuchy@redhat.com> 1.20-1
+- [cli] no need to set const with action=store_true
+- [cli] code cleanup
+- 1049460 - print nice error when projects does not exist
+- 1049392 - require python-setuptools
+- [backend] add --verbose to log to stderr
+- [backend] handle KeyboardInterrupt without tons of tracebacks
+- 1048508 - fix links at projects lists
+- [backend] in case of error the output is in e.output
+- [selinux] allow httpd to search
+- [backend] set number of worker in name of process
+- [logrotate] rotate every week unconditionally
+- [backend] do not traceback if jobfile is mangled
+- [backend] print error messages to stderr
+- [cli] do not require additional arguments for --nowait
+- [backend] replace procname with setproctitle
+- [cli] use copr.fedoraproject.org as default url
+- [frontend] show monitor even if last build have been canceled
+- [backend] call correct function
+- [cli] print errors to stderr
+- 1044136 - do not print TB if config in mangled
+- 1044165 - Provide login and token information in the same form as entered to
+ ~/.config-copr
+- [frontend] code cleanup
+- [frontend] move rendering of .repo file to helpers
+- 1043649 - in case of Fedora use $releasever in repo file
+- [frontend] condition should be in reverse
+
+* Mon Dec 16 2013 Miroslav Suchý <msuchy@redhat.com> 1.19-1
+- [backend] log real cause if ansible crash
+- [frontend] try again if whoosh does not get lock
+- [backend] if frontend does not respond, repeat
+- print yum repos nicely
+- Bump the copr-cli release to 0.2.0 with all the changes made
+- Refer to the man page for more information about the configuration file for
+ copr-cli
+- Rework the layout of the list command
+- Fix parsing the copr_url from the configuration file
+- [backend] run createrepo as copr user
+- 1040615 - wrap lines with long URL
+
+* Wed Dec 11 2013 Miroslav Suchý <msuchy@redhat.com> 1.18-1
+- [frontend] inicialize variable
+
+* Wed Dec 11 2013 Miroslav Suchý <msuchy@redhat.com> 1.17-1
+- [frontend] fix latest build variable overwrite
+
+* Wed Dec 11 2013 Miroslav Suchý <msuchy@redhat.com> 1.16-1
+- [backend] store jobs in id-chroot.json file
+- [frontend] handle unknown build/chroot status
+- use newstyle ansible variables
+
+* Tue Dec 10 2013 Miroslav Suchý <msuchy@redhat.com> 1.15-1
+- [frontend] smarter package name parsing
+- [frontend] extend range to allow 0
+- handle default timeout on backend
+- initial support for SCL
+- [backend] create word readable files in result directory
+- [backend] print tracebacks
+- [frontend] monitor: display only pkg name w/o version
+- [doc] update api docs
+- [doc] update copr-cli manpage
+- [cli] list only name, description and instructions
+- [cli] add support for build status & build monitor
+- [frontend] add build status to API
+- [playbook] do not overwrite mockchain
+- [backend] add spece between options
+- [backend] pass mock options correctly
+- [frontend] support markdown in description and instructions
+- [backend] Add macros to mockchain define arguments
+- [backend] Pass copr username and project name to MockRemote
+- [backend] Handle additional macro specification in MockRemote
+- [frontend] monitor: show results per package
+- [frontend] add favicon
+- [backend] quote strings before passing to mockchain
+- send chroots with via callback to frontend
+- [cli] change cli to new api call
+- enhance API documentation
+- add yum_repos to coprs/user API call
+- [frontend] provide link to description of allowed content
+- [backend] we pass just one chroot
+- [backend] - variable play is not defined
+- if createrepo fail, run it again
+- [cron] fix syntax error
+- [man] state that --chroot for create command is required
+- [spec] enable tests
+- [howto] add note about upgrading db schema
+- [frontend]: add copr monitor
+- [tests]: replace test_allowed_one
+- [tests]: fix for BuildChroots & new backend view
+- [frontend] rewrite backend view to use Build <-> Chroot relation
+- [frontend] add Build <-> Chroot relation
+- 1030493 - [cli] check that at least one chroot is entered
+- [frontend] typo
+- fixup! [tests]: fix test_build_logic to handle BuildChroot
+- fixup! [frontend] add ActionsLogic
+- [tests]: fix test_build_logic to handle BuildChroot
+- [spec] enable/disable test using variable
+- add migration script - add table build_chroot
+- [frontend] skip legal-flag actions when dumping waiting actions
+- [frontend] rewrite backend view to use Build <-> Chroot relation
+- [frontend] add ActionsLogic
+- [frontend] create BuildChroot objects on new build
+- [frontend] add Build <-> Chroot relation
+- [frontend] add StatusEnum
+- [frontend] fix name -> coprname typo
+- [frontend] remove unused imports
+- [frontend] add missing json import
+- [backend] rework ip address extraction
+- ownership of /etc/copr should be just normal
+- [backend] - wrap up returning action in "action" blok
+- [backend] rename backend api url
+- [backend] handle "rename" action
+- [backend] handle "delete" action
+- base handling of actions
+- move callback to frontend to separate object
+- secure waiting_actions with password
+- pick only individual builds
+- make address, where we send legal flags, configurable
+- send email to root after legal flag have been raised
+
+* Fri Nov 08 2013 Miroslav Suchý <msuchy@redhat.com> 1.14-1
+- 1028235 - add disclaimer about repos
+- fix pagination
+- fix one failing test
+
+* Wed Nov 06 2013 Miroslav Suchý <msuchy@redhat.com> 1.13-1
+- suggest correct name of repo file
+- we could not use releasever macro
+- no need to capitalize Projects
+- another s/copr/project
+- add link to header for sign-in
+- fix failing tests
+- UX - let textarea will full widht of box
+- UX - make background of hovered builds darker
+- generate yum repo for each chroot of copr
+- align table header same way as ordinary rows
+- enable resulting repo and disable gpgchecks
+
+* Mon Nov 04 2013 Miroslav Suchý <msuchy@redhat.com> 1.12-1
+- do not send parameters when we neither need them nor use them
+- authenticate using api login, not using username
+- disable editing name of project
+- Add commented out WTF_CSRF_ENABLED = True to configs
+- Use new session for each test
+- fix test_coprs_general failures
+- fix test_coprs_builds failures
+- Add WTF_CSRF_ENABLED = False to unit test config
+- PEP8 fixes
+- Fix compatibility with wtforms 0.9
+- typo s/submited/submitted/
+- UX - show details of build only after click
+- add link to FAQ to footer
+- UX - add placeholders
+- UX - add asterisk to required fields
+- dynamicly generate url for home
+- add footer
+
+* Sat Oct 26 2013 Miroslav Suchý <msuchy@redhat.com> 1.11-1
+- catch IOError from libravatar if there is no network
+
+* Fri Oct 25 2013 Miroslav Suchý <msuchy@redhat.com> 1.10-1
+- do not normalize url
+- specify full prefix of http
+- execute playbook using /usr/bin/ansible-playbook
+- use ssh transport
+- check after connection is made
+- add notes about debuging mockremote
+- clean up instance even when worker fails
+- normalize paths before using
+- do not use exception variable
+- operator should be preceded and followed by space
+- remove trailing whitespace
+- convert comment to docstring
+- use ssh transport
+- do not create new ansible connection, reuse self.conn
+- run copr-be.py as copr
+- s/Copr/Project/ where we use copr in meaning of projects
+- number will link to those coprs, to which it refers
+- run log and jobgrab as copr user
+- log event to log file
+- convert comment into docstring
+- use unbufferred output for copr-be.py
+- hint how to set ec2 variables
+- document sleeptime
+- document copr_url for copr-cli
+- document how to set api key for copr-cli
+- do not create list of list
+- document SECRET_KEY variable
+- make note how to become admin
+- instruct people to install selinux with frontend
+
+* Thu Oct 03 2013 Miroslav Suchý <msuchy@redhat.com> 1.9-1
+- prune old builds
+- require python-decorator
+- remove requirements.txt
+- move TODO-backend to our wiki
+- create pid file in /var/run/copr-backend
+- add backend service file for systemd
+- remove daemonize option in config
+- use python logging
+- create pid file in /var/run by default
+- do not create destdir
+- use daemon module instead of home brew function
+- fix default location of copr-be.conf
+- 2 tests fixed, one still failing
+- fix failing test test_fail_on_missing_dash
+- fixing test_fail_on_nonexistent_copr test
+- run frontend unit tests when building package
+- Adjust URLs in the unit-tests to their new structure
+- Adjust the CLI to call the adjuste endpoint of the API
+- Adjust API endpoint to reflects the UI endpoints in their url structure
+- First pass at adding fedmsg hooks.
+
+* Tue Sep 24 2013 Miroslav Suchý <msuchy@redhat.com> 1.8-1
+- 1008532 - require python2-devel
+- add note about ssh keys to copr-setup.txt
+- set home of copr user to system default
+
+* Mon Sep 23 2013 Miroslav Suchý <msuchy@redhat.com> 1.7-1
+- 1008532 - backend should own _pkgdocdir
+- 1008532 - backend should owns /etc/copr as well
+- 1008532 - require logrotate
+- 1008532 - do not distribute empty copr.if
+- 1008532 - use %%{?_smp_mflags} macro with make
+- move jobsdir to /var/lib/copr/jobs
+- correct playbooks path
+- selinux with enforce can be used for frontend
+
+* Wed Sep 18 2013 Miroslav Suchý <msuchy@redhat.com> 1.6-1
+- add BR python-devel
+- generate selinux type for /var/lib/copr and /var/log/copr
+- clean up backend setup instructions
+- initial selinux subpackage
+
+* Mon Sep 16 2013 Miroslav Suchý <msuchy@redhat.com> 1.5-1
+- 1008532 - use __python2 instead of __python
+- 1008532 - do not mark man page as doc
+- 1008532 - preserve timestamp
+
+* Mon Sep 16 2013 Miroslav Suchý <msuchy@redhat.com> 1.4-1
+- add logrotate file
+
+* Mon Sep 16 2013 Miroslav Suchý <msuchy@redhat.com> 1.3-1
+- be clear how we create tgz
+
+* Mon Sep 16 2013 Miroslav Suchý <msuchy@redhat.com> 1.2-1
+- fix typo
+- move frontend data into /var/lib/copr
+- no need to own /usr/share/copr by copr-fe
+- mark application as executable
+- coprs_frontend does not need to be owned by copr-fe
+- add executable attribute to copr-be.py
+- remove shebang from dispatcher.py
+- squeeze description into 80 chars
+- fix typo
+- frontend need argparse too
+- move results into /var/lib/copr/public_html
+- name of dir is just copr-%%version
+- Remove un-necessary quote that breaks the tests
+- Adjust unit-tests to the new urls
+- Update the URL to be based upon a /user/copr/<action> structure
+- comment config copr-be.conf and add defaults
+- put examples of builderpb.yml and terminatepb.yml into doc dir
+- more detailed description of copr-be.conf
+- move files in config directory not directory itself
+- include copr-be.conf
+- include copr-be.py
+- create copr with lighttpd group
+- edit backend part of copr-setup.txt
+- remove fedora16 and add 19 and 20
+- create -doc subpackage with python documentation
+- add generated documentation on gitignore list
+- add script to generate python documentation
+- copr-setup.txt change to for mock
+- rhel6 do not know _pkgdocdir macro
+- make instruction clear
+- require recent whoosh
+- add support for libravatar
+- include backend in rpm
+- add notes about lighttpd config files and how to deploy them
+- do not list file twice
+- move log file to /var/log
+- change destdir in copr-be.conf.example
+- lightweight is the word and buildsystem has more meaning than 'koji'.
+- restart apache after upgrade of frontend
+- own directory where backend put results
+- removal of hidden-file-or-dir
+ /usr/share/copr/coprs_frontend/coprs/logic/.coprs_logic.py.swo
+- copr-backend.noarch: W: spelling-error %%description -l en_US latests ->
+ latest, latest's, la tests
+- simplify configuration - introduce /etc/copr/copr*.conf
+- Replace "with" statements with @TransactionDecorator decorator
+- add python-flexmock to deps of frontend
+- remove sentence which does not have meaning
+- change api token expiration to 120 days and make it configurable
+- create_chroot must be run as copr-fe user
+- add note that you have to add chroots to db
+- mark config.py as config so it is not overwritten during upgrade
+- own directory data/whooshee/copr_user_whoosheer
+- gcc is not needed
+- sqlite db must be owned by copr-fe user
+- copr does not work with selinux
+- create subdirs under data/openid_store
+- suggest to install frontend as package from copr repository
+- on el6 add python-argparse to BR
+- add python-requests to BR
+- add python-setuptools to BR
+- maintain apache configuration on one place only
+- apache 2.4 changed access control
+- require python-psycopg2
+- postgresql server is not needed
+- document how to create db
+- add to HOWTO how to create db
+- require python-alembic
+- add python-flask-script and python-flask-whooshee to requirements
+- change user in coprs.conf.example to copr-fe
+- fix paths in coprs.conf.example
+- copr is noarch package
+- add note where to configure frontend
+- move frontend to /usr/share/copr/coprs_frontend
+- put production placeholders in coprs_frontend/coprs/config.py
+- put frontend into copr.spec
+- web application should be put in /usr/share/%%{name}
+
+* Mon Jun 17 2013 Miroslav Suchý <msuchy@redhat.com> 1.1-1
+- new package built with tito
diff --git a/euler_msgbus.patch b/euler_msgbus.patch
deleted file mode 100644
index 5eca90a..0000000
--- a/euler_msgbus.patch
+++ /dev/null
@@ -1,83 +0,0 @@
-diff --git a/copr_backend/euler_msgbus.py b/copr_backend/euler_msgbus.py
-new file mode 100644
-index 000000000..1395249be
---- /dev/null
-+++ b/copr_backend/euler_msgbus.py
-@@ -0,0 +1,77 @@
-+import socket
-+
-+from kafka import KafkaProducer
-+import os
-+import datetime
-+import uuid
-+import json
-+import ssl
-+
-+
-+def message_from_worker_job(topic, job, who, ip, pid):
-+ message = {}
-+ content = {
-+ 'user': job.submitter,
-+ 'copr': job.project_name,
-+ 'owner': job.project_owner,
-+ 'pkg': job.package_name,
-+ 'build': job.build_id,
-+ 'chroot': job.chroot,
-+ 'version': job.package_version,
-+ 'status': job.status,
-+ }
-+ content.update({'ip': ip, 'who': who, 'pid': pid})
-+ message_types = {
-+ 'build.start': {
-+ 'what': "build start: user:{user} copr:{copr}" \
-+ " pkg:{pkg} build:{build} ip:{ip} pid:{pid}",
-+ },
-+ 'chroot.start': {
-+ 'what': "chroot start: chroot:{chroot} user:{user}" \
-+ " copr:{copr} pkg:{pkg} build:{build} ip:{ip} pid:{pid}",
-+ },
-+ 'build.end': {
-+ 'what': "build end: user:{user} copr:{copr} build:{build}" \
-+ " pkg:{pkg} version:{version} ip:{ip} pid:{pid} status:{status}",
-+ },
-+ }
-+ content['what'] = message_types[topic]['what'].format(**content)
-+ message['body'] = content
-+ now = datetime.datetime.now().isoformat()
-+ headers = {
-+ "openEuler_messaging_schema": "eur." + topic,
-+ "sent-at": now,
-+ }
-+ message['headers'] = headers
-+ message['id'] = str(uuid.uuid4())
-+ message['topic'] = "org.openEuler.prod.eur." + topic
-+ return message
-+
-+
-+class MessageSender:
-+ def __init__(self, backend_opts, name, log):
-+ self.log = log
-+ self.name = name
-+ self.pid = os.getpid()
-+ self.opts = backend_opts
-+
-+ def announce(self, topic, job, host):
-+ msg = message_from_worker_job(topic, job, self.name, host, self.pid)
-+ self.send_message(msg)
-+
-+ def send_message(self, msg):
-+ """ Send message to kafka """
-+
-+ context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
-+ context.verify_mode = ssl.CERT_REQUIRED
-+ context.load_verify_locations("etc/copr/kafka.crt")
-+ producer = KafkaProducer(bootstrap_servers=self.opts.message.bootstrap_servers,
-+ api_version=(3, 5, 0),
-+ sasl_mechanism="PLAIN",
-+ ssl_context=context,
-+ security_protocol='SASL_SSL',
-+ sasl_plain_username=self.opts.message.user_name,
-+ sasl_plain_password=self.opts.message.password,
-+ value_serializer=lambda v: json.dumps(v).encode('utf-8'))
-+ producer.send(str(self.opts.message.topic), msg)
-+ producer.flush()
diff --git a/fail_to_build_in_oe2403.patch b/fail_to_build_in_oe2403.patch
deleted file mode 100644
index be32aee..0000000
--- a/fail_to_build_in_oe2403.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/tests/test_modifyrepo.py b/backend/tests/test_modifyrepo.py
-index 330ff68f7..2c1bd0a66 100644
---- a/tests/test_modifyrepo.py
-+++ b/tests/test_modifyrepo.py
-@@ -431,7 +431,8 @@ def test_copr_repo_run_createrepo(self, popen, do_stat, chroot, database_option)
- "--workers", "8", "--general-compress-type=gz", "--update"] + additional_args
-
- @pytest.mark.skipif(
-- distro.id() == 'fedora' and int(distro.version()) >= 36,
-+ (distro.id() == 'fedora' and int(distro.version()) >= 36) or
-+ (distro.id() == 'openeuler' and float(distro.version()) >= 24.03),
- reason="createrepo_c dropped md5 checksum support"
- )
- def test_copr_repo_el5(self, f_third_build):
diff --git a/signatrust_bin.patch b/signatrust_bin.patch
deleted file mode 100644
index fcba220..0000000
--- a/signatrust_bin.patch
+++ /dev/null
@@ -1,105 +0,0 @@
-diff --git a/run/copr_fix_gpg.py b/run/copr_fix_gpg.py
-index 24edf74e..bfa70c05 100755
---- a/run/copr_fix_gpg.py
-+++ b/run/copr_fix_gpg.py
-@@ -9,7 +9,7 @@ from urllib.parse import urlparse
- import pwd
-
- from copr_backend.helpers import BackendConfigReader, call_copr_repo, run_cmd
--from copr_backend.sign import get_pubkey, unsign_rpms_in_dir, sign_rpms_in_dir, create_user_keys, create_gpg_email
-+from copr_backend.sign import new_signer, create_gpg_email
-
- logging.basicConfig(
- filename="/var/log/copr-backend/fix_gpg.log",
-@@ -69,12 +69,14 @@ def fix_copr(args, opts, copr_full_name):
- log.info('Ignoring %s. Directory does not exist.', copr_path)
- return
-
-+ signer = new_signer(opts)
-+
- log.info("Generate key-pair on copr-keygen (if not generated) for email %s",
- create_gpg_email(owner, coprname, opts.sign_domain))
-- create_user_keys(owner, coprname, opts)
-+ signer.create_user_keys(owner, coprname, opts)
-
- log.info("Regenerate pubkey.gpg in copr %s", copr_path)
-- get_pubkey(owner, coprname, log, opts.sign_domain, os.path.join(copr_path, 'pubkey.gpg'))
-+ signer.get_pubkey(owner, coprname, log, opts.sign_domain, os.path.join(copr_path, 'pubkey.gpg'))
-
- # Match the "00001231-anycharacer" directory names. Compile once, use many.
- builddir_matcher = re.compile(r"\d{8,}-")
-@@ -111,8 +113,8 @@ def fix_copr(args, opts, copr_full_name):
-
- log.info("Processing rpms in builddir %s", builddir_path)
- try:
-- unsign_rpms_in_dir(builddir_path, opts, log) # first we need to unsign by using rpm-sign before we sign with obs-sign
-- sign_rpms_in_dir(owner, coprname, builddir_path, chroot, opts, log)
-+ signer.unsign_rpms_in_dir(builddir_path, opts, log) # first we need to unsign by using rpm-sign before we sign with obs-sign
-+ signer.sign_rpms_in_dir(owner, coprname, builddir_path, chroot, opts, log)
- except Exception as e:
- log.exception(str(e))
- continue
-diff --git a/run/copr_sign_unsigned.py b/run/copr_sign_unsigned.py
-index 33eaeae3..e17e65bb 100755
---- a/run/copr_sign_unsigned.py
-+++ b/run/copr_sign_unsigned.py
-@@ -12,7 +12,7 @@ import pwd
-
- from copr_backend.helpers import (BackendConfigReader, create_file_logger,
- uses_devel_repo, call_copr_repo)
--from copr_backend.sign import get_pubkey, sign_rpms_in_dir, create_user_keys
-+from copr_backend.sign import new_signer
- from copr_backend.exceptions import CoprSignNoKeyError
-
-
-@@ -26,10 +26,11 @@ log = logging.getLogger(__name__)
- def check_signed_rpms_in_pkg_dir(pkg_dir, user, project, opts, chroot_dir, devel):
- success = True
-
-+ signer = new_signer(opts)
- logger = create_file_logger("run.check_signed_rpms_in_pkg_dir",
- "/tmp/copr_check_signed_rpms.log")
- try:
-- sign_rpms_in_dir(user, project, pkg_dir, chroot_dir, opts, log=logger)
-+ signer.sign_rpms_in_dir(user, project, pkg_dir, chroot_dir, opts, log=logger)
- log.info("running createrepo for %s", pkg_dir)
- call_copr_repo(directory=chroot_dir, devel=devel, logger=log)
- except Exception as err:
-@@ -80,9 +81,10 @@ def check_pubkey(pubkey_path, user, project, opts):
- log.info("Pubkey for %s/%s exists: %s", user, project, pubkey_path)
- return True
- else:
-+ signer = new_signer(opts)
- log.info("Missing pubkey for %s/%s", user, project)
- try:
-- get_pubkey(user, project, log, opts.sign_domain, pubkey_path)
-+ signer.get_pubkey(user, project, log, opts.sign_domain, pubkey_path)
- return True
- except Exception as err:
- log.exception(err)
-@@ -102,6 +104,8 @@ def main():
- opts = BackendConfigReader().read()
- log.info("Starting pubkey fill, destdir: %s", opts.destdir)
-
-+ signer = new_signer(opts)
-+
- log.debug("list dir: %s", os.listdir(opts.destdir))
- for user_name in os.listdir(opts.destdir):
- if user_name in users_done_old:
-@@ -116,13 +120,13 @@ def main():
- log.info("Checking project dir: %s", project_name)
-
- try:
-- get_pubkey(user_name, project_name, log, opts.sign_domain)
-+ signer.get_pubkey(user_name, project_name, log, opts.sign_domain)
- log.info("Key-pair exists for %s/%s", user_name, project_name)
- except CoprSignNoKeyError:
-- create_user_keys(user_name, project_name, opts)
-+ signer.create_user_keys(user_name, project_name, opts)
- log.info("Created new key-pair for %s/%s", user_name, project_name)
- except Exception as err:
-- log.error("Failed to get pubkey for {}/{}, mark as failed, skipping")
-+ log.error("Failed to get pubkey for {}/{}, mark as failed, skipping".format(user_name, project_name))
- log.exception(err)
- failed = True
- continue
diff --git a/sources b/sources
index efbd8eb..704becb 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-25ff25e926c351d188a38b843a7d898a copr-backend-1.177.tar.gz
-c94d55e21a4935b3e62f673fbae65af2 test-data-copr-backend-5.tar.gz
+8dacd18f46475296d0199365db977649 copr-backend-1.168.tar.gz
+a35697a68640fb4c0bcfef02a93eac63 test-data-copr-backend-2.tar.gz
diff --git a/support_signatrust_backend.patch b/support_signatrust_backend.patch
deleted file mode 100644
index adcbf1e..0000000
--- a/support_signatrust_backend.patch
+++ /dev/null
@@ -1,953 +0,0 @@
-diff --git a/copr_backend/constants.py b/backend/copr_backend/constants.py
-index a529be28a..83bcb8fbe 100644
---- a/copr_backend/constants.py
-+++ b/copr_backend/constants.py
-@@ -13,6 +13,7 @@ DEF_BUILD_USER = "mockbuilder"
- DEF_DESTDIR = os.getcwd()
- DEF_MACROS = {}
- DEF_BUILDROOT_PKGS = ""
-+DEF_SIGN_BACKEND = "obs-signd"
-
-
- DEF_CONSECUTIVE_FAILURE_THRESHOLD = 10
-diff --git a/copr_backend/exceptions.py b/backend/copr_backend/exceptions.py
-index 21afb14c6..0865fcc8c 100644
---- a/copr_backend/exceptions.py
-+++ b/copr_backend/exceptions.py
-@@ -48,8 +48,8 @@ class CoprKeygenRequestError(Exception):
-
- def __str__(self):
- out = super(CoprKeygenRequestError, self).__str__()
-- out += "\nrequest to copr-keygen: {}\n".format(self.request)
-- if self.response:
-+ out += "\nrequest to key_backend: {}\n".format(self.request)
-+ if self.response is not None:
- out += "status code: {}\n" "response content: {}\n" \
- .format(self.response.status_code, self.response.content)
- return out
-diff --git a/copr_backend/helpers.py b/backend/copr_backend/helpers.py
-index 75fa5e62d..291228912 100644
---- a/copr_backend/helpers.py
-+++ b/copr_backend/helpers.py
-@@ -31,7 +31,7 @@ from munch import Munch
- from copr_common.redis_helpers import get_redis_connection
- from copr.v3 import Client
- from copr_backend.constants import DEF_BUILD_USER, DEF_BUILD_TIMEOUT, DEF_CONSECUTIVE_FAILURE_THRESHOLD, \
-- CONSECUTIVE_FAILURE_REDIS_KEY, default_log_format
-+ CONSECUTIVE_FAILURE_REDIS_KEY, default_log_format, DEF_SIGN_BACKEND
- from copr_backend.exceptions import CoprBackendError
-
- from . import constants
-@@ -309,6 +309,18 @@ class BackendConfigReader(object):
- opts.sign_domain = _get_conf(
- cp, "backend", "sign_domain", DOMAIN)
-
-+ opts.sign_backend = _get_conf(
-+ cp, "backend", "sign_backend", DEF_SIGN_BACKEND)
-+
-+ opts.signatrust_host = _get_conf(
-+ cp, "backend", "signatrust_host", "")
-+
-+ opts.signatrust_token = _get_conf(
-+ cp, "backend", "signatrust_token", "")
-+
-+ opts.signatrust_key_expire = _get_conf(
-+ cp, "backend", "signatrust_key_expire", 1825, mode="int")
-+
- opts.build_groups = []
- for group_id in range(opts.build_groups_count):
- archs = _get_conf(cp, "backend",
-diff --git a/copr_backend/sign.py b/backend/copr_backend/sign.py
-index e21653e78..599d209ee 100644
---- a/copr_backend/sign.py
-+++ b/copr_backend/sign.py
-@@ -7,17 +7,16 @@ Wrapper for /bin/sign from obs-sign package
- from subprocess import Popen, PIPE, SubprocessError
- import os
- import time
-+import functools
-
- from packaging import version
-
- from copr_common.request import SafeRequest
--from copr_backend.helpers import get_redis_logger
-+from copr_backend.helpers import get_redis_logger, get_backend_opts
- from .exceptions import CoprSignError, CoprSignNoKeyError, \
- CoprKeygenRequestError
-
-
--SIGN_BINARY = "/bin/sign"
--
- def create_gpg_email(username, projectname, domain):
- """
- Creates canonical name_email to identify gpg key
-@@ -25,77 +24,17 @@ def create_gpg_email(username, projectname, domain):
-
- return "{}#{}@copr.{}".format(username, projectname, domain)
-
--
- def call_sign_bin(cmd, log):
-- """
-- Call /bin/sign and return (rc, stdout, stderr). Re-try the call
-- automatically upon certain failures (if that makes sense).
-- """
-- cmd_pretty = ' '.join(cmd)
-- for attempt in [1, 2, 3]:
-- log.info("Calling '%s' (attempt #%s)", cmd_pretty, attempt)
-- try:
-- handle = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding="utf-8")
-- stdout, stderr = handle.communicate()
-- except (SubprocessError, OSError) as err:
-- new_err = CoprSignError("Failed to invoke '{}'".format(cmd_pretty))
-- raise new_err from err
--
-- if handle.returncode != 0:
-- log.warning("Command '%s' failed with: %s",
-- cmd_pretty, stderr.rstrip())
-- sleeptime = 20
-- log.warning("Going to sleep %ss and re-try.", sleeptime)
-- time.sleep(sleeptime)
-- continue
-- break
-- return handle.returncode, stdout, stderr
--
-+ signer = new_signer()
-+ return signer.call_sign_bin(cmd, log)
-
- def get_pubkey(username, projectname, log, sign_domain, outfile=None):
-- """
-- Retrieves public key for user/project from signer host.
--
-- :param sign_domain: the domain name of the sign key
-- :param outfile: [optional] file to write obtained key
-- :return: public keys
--
-- :raises CoprSignError: failed to retrieve key, see error message
-- :raises CoprSignNoKeyError: if there are no such user in keyring
-- """
-- usermail = create_gpg_email(username, projectname, sign_domain)
-- cmd = [SIGN_BINARY, "-u", usermail, "-p"]
--
-- returncode, stdout, stderr = call_sign_bin(cmd, log)
-- if returncode != 0:
-- if "unknown key:" in stderr:
-- raise CoprSignNoKeyError(
-- "There are no gpg keys for user {} in keyring".format(username),
-- return_code=returncode,
-- cmd=cmd, stdout=stdout, stderr=stderr)
-- raise CoprSignError(
-- msg="Failed to get user pubkey\n"
-- "sign stdout: {}\n sign stderr: {}\n".format(stdout, stderr),
-- return_code=returncode,
-- cmd=cmd, stdout=stdout, stderr=stderr)
--
-- if outfile:
-- with open(outfile, "w") as handle:
-- handle.write(stdout)
--
-- return stdout
--
-+ signer = new_signer()
-+ return signer.get_pubkey(username, projectname, log, sign_domain, outfile)
-
- def _sign_one(path, email, hashtype, log):
-- cmd = [SIGN_BINARY, "-4", "-h", hashtype, "-u", email, "-r", path]
-- returncode, stdout, stderr = call_sign_bin(cmd, log)
-- if returncode != 0:
-- raise CoprSignError(
-- msg="Failed to sign {} by user {}".format(path, email),
-- return_code=returncode,
-- cmd=cmd, stdout=stdout, stderr=stderr)
-- return stdout, stderr
--
-+ signer = new_signer()
-+ return signer._sign_one(path, email, hashtype, log)
-
- def gpg_hashtype_for_chroot(chroot, opts):
- """
-@@ -135,134 +74,455 @@ def gpg_hashtype_for_chroot(chroot, opts):
- # fallback to sha256
- return "sha256"
-
--
- def sign_rpms_in_dir(username, projectname, path, chroot, opts, log):
-- """
-- Signs rpms using obs-signd.
-+ signer = new_signer()
-+ return signer.sign_rpms_in_dir(username, projectname, path, chroot, opts, log)
-
-- If some some pkgs failed to sign, entire build marked as failed,
-- but we continue to try sign other pkgs.
--
-- :param username: copr username
-- :param projectname: copr projectname
-- :param path: directory with rpms to be signed
-- :param chroot: chroot name where we sign packages, affects the hash type
-- :param Munch opts: backend config
-+def create_user_keys(username, projectname, opts, try_indefinitely=False):
-+ signer = new_signer()
-+ return signer.create_user_keys(username, projectname, opts, try_indefinitely)
-
-- :type log: logging.Logger
-+def _unsign_one(path):
-+ signer = new_signer()
-+ return signer._unsign_one(path)
-
-- :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
-- """
-+def unsign_rpms_in_dir(path, opts, log):
-+ signer = new_signer()
-+ return signer.unsign_rpms_in_dir(path, opts, log)
-+
-+
-+# a sign interface
-+class Signer(object):
-+ @classmethod
-+ def get_pubkey(cls, username, projectname, log, sign_domain, outfile=None):
-+ """get public key"""
-+ raise NotImplementedError
-+
-+ @classmethod
-+ def sign_rpms_in_dir(cls, username, projectname, path, chroot, opts, log):
-+ """batch sign rpms"""
-+ raise NotImplementedError
-+
-+ @classmethod
-+ def create_user_keys(username, projectname, opts, try_indefinitely=False):
-+ """create user key pair"""
-+ raise NotImplementedError
-+
-+ @classmethod
-+ def _sign_one(cls, path, email, hashtype, log):
-+ """sign one rpm"""
-+ raise NotImplementedError
-+
-+ @classmethod
-+ def _unsign_one(cls, path):
-+ # Requires rpm-sign package
-+ cmd = ["/usr/bin/rpm", "--delsign", path]
-+ handle = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding="utf-8")
-+ stdout, stderr = handle.communicate()
-
-- rpm_list = [
-- os.path.join(path, filename)
-- for filename in os.listdir(path)
-- if filename.endswith(".rpm")
-- ]
-+ if handle.returncode != 0:
-+ err = CoprSignError(
-+ msg="Failed to unsign {}".format(path),
-+ return_code=handle.returncode,
-+ cmd=cmd, stdout=stdout, stderr=stderr)
-
-- if not rpm_list:
-- return
-+ raise err
-+
-+ return stdout, stderr
-+
-+ @classmethod
-+ def call_sign_bin(cls, cmd, log):
-+ """
-+ Call sign_cmd and return (rc, stdout, stderr). Re-try the call
-+ automatically upon certain failures (if that makes sense).
-+ """
-+ cmd_pretty = ' '.join(cmd)
-+ for attempt in [1, 2, 3]:
-+ log.info("Calling '%s' (attempt #%s)", cmd_pretty, attempt)
-+ try:
-+ handle = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding="utf-8")
-+ stdout, stderr = handle.communicate()
-+ except (SubprocessError, OSError) as err:
-+ new_err = CoprSignError("Failed to invoke '{}'".format(cmd_pretty))
-+ raise new_err from err
-+
-+ if handle.returncode != 0:
-+ log.warning("Command '%s' failed with: %s",
-+ cmd_pretty, stderr.rstrip())
-+ sleeptime = 20
-+ log.warning("Going to sleep %ss and re-try.", sleeptime)
-+ time.sleep(sleeptime)
-+ continue
-+ break
-+ return handle.returncode, stdout, stderr
-+
-+ @classmethod
-+ def sign_rpms_in_dir(cls, username, projectname, path, chroot, opts, log):
-+ """
-+ Signs rpms using obs-signd.
-+
-+ If some some pkgs failed to sign, entire build marked as failed,
-+ but we continue to try sign other pkgs.
-+
-+ :param username: copr username
-+ :param projectname: copr projectname
-+ :param path: directory with rpms to be signed
-+ :param chroot: chroot name where we sign packages, affects the hash type
-+ :param Munch opts: backend config
-+
-+ :type log: logging.Logger
-+
-+ :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
-+ """
-+ rpm_list = [
-+ os.path.join(path, filename)
-+ for filename in os.listdir(path)
-+ if filename.endswith(".rpm")
-+ ]
-
-- hashtype = gpg_hashtype_for_chroot(chroot, opts)
-+ if not rpm_list:
-+ return
-
-- try:
-- get_pubkey(username, projectname, log, opts.sign_domain)
-- except CoprSignNoKeyError:
-- create_user_keys(username, projectname, opts, try_indefinitely=True)
-+ hashtype = gpg_hashtype_for_chroot(chroot, opts)
-
-- errors = [] # tuples (rpm_filepath, exception)
-- for rpm in rpm_list:
- try:
-- _sign_one(rpm, create_gpg_email(username, projectname, opts.sign_domain),
-- hashtype, log)
-- log.info("signed rpm: %s", rpm)
--
-- except CoprSignError as e:
-- log.exception("failed to sign rpm: %s", rpm)
-- errors.append((rpm, e))
--
-- if errors:
-- raise CoprSignError("Rpm sign failed, affected rpms: {}"
-- .format([err[0] for err in errors]))
--
--
--def create_user_keys(username, projectname, opts, try_indefinitely=False):
-- """
-- Generate a new key-pair at sign host
-+ cls.get_pubkey(username, projectname, log, opts.sign_domain)
-+ except CoprSignNoKeyError:
-+ cls.create_user_keys(username, projectname, opts, try_indefinitely=True)
-+
-+ errors = [] # tuples (rpm_filepath, exception)
-+ for rpm in rpm_list:
-+ try:
-+ cls._sign_one(rpm, create_gpg_email(username, projectname, opts.sign_domain),
-+ hashtype, log)
-+ log.info("signed rpm: %s", rpm)
-+
-+ except CoprSignError as e:
-+ log.exception("failed to sign rpm: %s", rpm)
-+ errors.append((rpm, e))
-+
-+ if errors:
-+ raise CoprSignError("Rpm sign failed, affected rpms: {}"
-+ .format([err[0] for err in errors]))
-+
-+ @classmethod
-+ def unsign_rpms_in_dir(cls, path, opts, log):
-+ """
-+ :param path: directory with rpms to be signed
-+ :param Munch opts: backend config
-+ :type log: logging.Logger
-+ :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
-+ """
-+ rpm_list = [
-+ os.path.join(path, filename)
-+ for filename in os.listdir(path)
-+ if filename.endswith(".rpm")
-+ ]
-+
-+ if not rpm_list:
-+ return
-+
-+ errors = [] # tuples (rpm_filepath, exception)
-+ for rpm in rpm_list:
-+ try:
-+ cls._unsign_one(rpm)
-+ log.info("unsigned rpm: %s", rpm)
-+
-+ except CoprSignError as e:
-+ log.exception("failed to unsign rpm: %s", rpm)
-+ errors.append((rpm, e))
-+
-+ if errors:
-+ raise CoprSignError("Rpm unsign failed, affected rpms: {}"
-+ .format([err[0] for err in errors]))
-+
-+@functools.lru_cache(maxsize=1)
-+def new_signer():
-+ opts = get_backend_opts()
-+ if hasattr(opts, "sign_backend") and opts.sign_backend == "signatrust":
-+ Signatrust.signatrust_token = opts.signatrust_token
-+ Signatrust.signatrust_host = opts.signatrust_host
-+ return Signatrust
-+ else: # keep obs-signd as default backend
-+ return ObsSign
-+
-+class ObsSign(Signer):
-+ sign_cmd = "/bin/sign"
-+
-+ @classmethod
-+ def get_pubkey(cls, username, projectname, log, sign_domain, outfile=None):
-+ """
-+ Retrieves public key for user/project from signer host.
-+
-+ :param sign_domain: the domain name of the sign key
-+ :param outfile: [optional] file to write obtained key
-+ :return: public keys
-+
-+ :raises CoprSignError: failed to retrieve key, see error message
-+ :raises CoprSignNoKeyError: if there are no such user in keyring
-+ """
-+ usermail = create_gpg_email(username, projectname, sign_domain)
-+ cmd = [cls.sign_cmd, "-u", usermail, "-p"]
-+
-+ returncode, stdout, stderr = cls.call_sign_bin(cmd, log)
-+ if returncode != 0:
-+ if "unknown key:" in stderr:
-+ raise CoprSignNoKeyError(
-+ "There are no gpg keys for user {} in keyring".format(username),
-+ return_code=returncode,
-+ cmd=cmd, stdout=stdout, stderr=stderr)
-+ raise CoprSignError(
-+ msg="Failed to get user pubkey\n"
-+ "sign stdout: {}\n sign stderr: {}\n".format(stdout, stderr),
-+ return_code=returncode,
-+ cmd=cmd, stdout=stdout, stderr=stderr)
-
-- :param username:
-- :param projectname:
-- :param opts: backend config
-+ if outfile:
-+ with open(outfile, "w") as handle:
-+ handle.write(stdout)
-
-- :return: None
-- """
-- data = {
-- "name_real": "{}_{}".format(username, projectname),
-- "name_email": create_gpg_email(username, projectname, opts.sign_domain)
-- }
--
-- log = get_redis_logger(opts, "sign", "actions")
-- keygen_url = "http://{}/gen_key".format(opts.keygen_host)
-- query = dict(url=keygen_url, data=data, method="post")
-- try:
-- request = SafeRequest(log=log, try_indefinitely=try_indefinitely)
-- response = request.send(**query)
-- except Exception as e:
-- raise CoprKeygenRequestError(
-- msg="Failed to create key-pair for user: {},"
-- " project:{} with error: {}"
-- .format(username, projectname, e), request=query)
--
-- if response.status_code >= 400:
-- raise CoprKeygenRequestError(
-- msg="Failed to create key-pair for user: {}, project:{}, status_code: {}, response: {}"
-- .format(username, projectname, response.status_code, response.text),
-- request=query, response=response)
-+ return stdout
-
-+ @classmethod
-+ def _sign_one(cls, path, email, hashtype, log):
-+ cmd = [cls.sign_cmd, "-4", "-h", hashtype, "-u", email, "-r", path]
-+ returncode, stdout, stderr = cls.call_sign_bin(cmd, log)
-+ if returncode != 0:
-+ raise CoprSignError(
-+ msg="Failed to sign {} by user {}".format(path, email),
-+ return_code=returncode,
-+ cmd=cmd, stdout=stdout, stderr=stderr)
-+ return stdout, stderr
-+
-+ @classmethod
-+ def create_user_keys(cls, username, projectname, opts, try_indefinitely=False):
-+ """
-+ Generate a new key-pair at sign host
-+
-+ :param username:
-+ :param projectname:
-+ :param opts: backend config
-+
-+ :return: None
-+ """
-+ data = {
-+ "name_real": "{}_{}".format(username, projectname),
-+ "name_email": create_gpg_email(username, projectname, opts.sign_domain)
-+ }
-+
-+ log = get_redis_logger(opts, "sign", "actions")
-+ keygen_url = "http://{}/gen_key".format(opts.keygen_host)
-+ query = dict(url=keygen_url, data=data, method="post")
-+ try:
-+ request = SafeRequest(log=log, try_indefinitely=try_indefinitely)
-+ response = request.send(**query)
-+ except Exception as e:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to create key-pair for user: {},"
-+ " project:{} with error: {}"
-+ .format(username, projectname, e), request=query)
-+
-+ if response.status_code >= 400:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to create key-pair for user: {}, project:{}, status_code: {}, response: {}"
-+ .format(username, projectname, response.status_code, response.text),
-+ request=query, response=response)
-+
-+class Signatrust(Signer):
-+ sign_cmd = "/usr/local/bin/client"
-+ prefix = ""
-+ signatrust_host = ""
-+ signatrust_token = ""
-+
-+ @classmethod
-+ def get_prefix(cls):
-+ """
-+ Get prefix of the user
-+
-+ As in copr, we set key attr with visibility=private
-+ These keys' name were prefixed by user's email like:
-+ tommylikehu@gmail.com:mywaaagh_admin_test
-+ """
-+ headers = {
-+ "accept": "application/json",
-+ "Authorization": cls.signatrust_token
-+ }
-+ try:
-+ r = requests.get("{}/api/v1/users/info".format(cls.signatrust_host), headers=headers).json()
-+ cls.prefix = r.get("email")
-+ except Exception as e:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to get userinfo", request="/api/v1/users/info")
-+
-+ @classmethod
-+ def get_key_name(cls, username, projectname, prefix=True):
-+ """
-+ copr key_name rule in signatrust:
-+ <user prefix>:<user_name>_<project_name>
-+ """
-+ if not cls.prefix:
-+ cls.get_prefix()
-+ if prefix:
-+ return "{}:{}_{}".format(cls.prefix, username, projectname)
-+ return "{}_{}".format(username, projectname)
-+
-+ @classmethod
-+ def get_pubkey(cls, username, projectname, log, sign_domain, outfile=None):
-+ """
-+ get public key
-+
-+ https://domain:port/api/v1/keys/<key_name>/public_key
-+ """
-+ if not cls.prefix:
-+ cls.get_prefix()
-+
-+ headers = {
-+ "accept": "application/json",
-+ "Authorization": cls.signatrust_token
-+ }
-+
-+ key_name = cls.get_key_name(username, projectname)
-+ url = "{}/api/v1/keys/{}/public_key".format(cls.signatrust_host, key_name)
-+ try:
-+ r = requests.get(url, headers=headers)
-+ except Exception as e:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to get public_key", request="/api/v1/keys/{}/public_key".format(key_name), response=r)
-
--def _unsign_one(path):
-- # Requires rpm-sign package
-- cmd = ["/usr/bin/rpm", "--delsign", path]
-- handle = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding="utf-8")
-- stdout, stderr = handle.communicate()
-+ if r.status_code == 404:
-+ raise CoprSignNoKeyError(
-+ "There are no gpg keys for user {} in keyring".format(username),
-+ return_code=r.status_code,
-+ cmd="GET {}".format(url), stdout="", stderr="")
-+ elif r.status_code >= 400:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to get user pubkey\n",
-+ request="/api/v1/keys/{}/public_key".format(key_name), response=r)
-+
-+ if outfile:
-+ with open(outfile, "wb") as handle:
-+ handle.write(r.content)
-+
-+ return r.content
-+
-+ @classmethod
-+ def sign_rpms_in_dir(cls, username, projectname, path, chroot, opts, log):
-+ """batch sign rpms"""
-+ if not cls.prefix:
-+ cls.get_prefix()
-+
-+ if not cls._key_existed(username, projectname, opts):
-+ cls.create_user_keys(username, projectname, opts)
-+
-+ # when we migrate copr keys into signatrust
-+ # we fellow the rules:
-+ # key_name = <user_email>:<user_name>_<project_name>
-+ cmd = [cls.sign_cmd, "-c", "/etc/signatrust.toml", "add", "--file-type", "rpm", "--key-type", "pgp", "--key-name", cls.get_key_name(username, projectname), path]
-+
-+ returncode, stdout, stderr = cls.call_sign_bin(cmd, log)
-+ if returncode != 0:
-+ raise CoprSignError(
-+ msg="Failed to sign rpms\n"
-+ "sign stdout: {}\n sign stderr: {}\n".format(stdout, stderr),
-+ return_code=returncode,
-+ cmd=cmd, stdout=stdout, stderr=stderr)
-
-- if handle.returncode != 0:
-- err = CoprSignError(
-- msg="Failed to unsign {}".format(path),
-- return_code=handle.returncode,
-- cmd=cmd, stdout=stdout, stderr=stderr)
-+ if stderr:
-+ # signatrust client will print error message for one rpm per line
-+ failed_list = re.findall(r"failed to sign file (.*.rpm) due to error", stderr)
-+
-+ if failed_list:
-+ failed_rpms = " ".join(map(os.path.basename, failed_list))
-+ log.exception("failed to sign rpm: %s".format(failed_rpms))
-+ raise CoprSignError("Rpm sign failed, affected rpms: {}"
-+ .format(failed_rpms))
-+
-+ @classmethod
-+ def unsign_rpms_in_dir(cls, path, opts, log):
-+ """
-+ signatrust will replace the signature infomation defaultly,
-+ so there is no need to unsign, just return
-+ """
-+ return
-
-- raise err
-+ @classmethod
-+ def _key_existed(cls, username, projectname, opts):
-+ """
-+ check keyname existence
-
-- return stdout, stderr
-+ HEAD /api/v1/keys/
-+ """
-+ if not cls.prefix:
-+ cls.get_prefix()
-
-+ key_name = cls.get_key_name(username, projectname, prefix=False)
-
--def unsign_rpms_in_dir(path, opts, log):
-- """
-- :param path: directory with rpms to be signed
-- :param Munch opts: backend config
-- :type log: logging.Logger
-- :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
-- """
-- rpm_list = [
-- os.path.join(path, filename)
-- for filename in os.listdir(path)
-- if filename.endswith(".rpm")
-- ]
-+ query = {
-+ "name": key_name,
-+ "visibility": "private"
-+ }
-
-- if not rpm_list:
-- return
-+ headers = {
-+ "accept": "application/json",
-+ "Authorization": cls.signatrust_token
-+ }
-
-- errors = [] # tuples (rpm_filepath, exception)
-- for rpm in rpm_list:
- try:
-- _unsign_one(rpm)
-- log.info("unsigned rpm: %s", rpm)
--
-- except CoprSignError as e:
-- log.exception("failed to unsign rpm: %s", rpm)
-- errors.append((rpm, e))
-+ res = requests.head("{}/api/v1/keys/name_identical".format(opts.signatrust_host), headers=headers, params=query)
-+ except Exception as e:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to check key existence", request="/api/v1/keys/name_identical", response=res)
-+
-+ # signatrust return 200 means key name available
-+ if res.status_code == 200:
-+ return False
-+ # signatrust return 409 means key name redundant
-+ elif res.status_code == 409:
-+ return True
-+ else:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to check key existence", request="/api/v1/keys/name_identical", response=res)
-+
-+ @classmethod
-+ def create_user_keys(cls, username, projectname, opts, try_indefinitely=False):
-+ """
-+ create user key pair
-+
-+ POST /api/v1/keys/
-+ """
-+ if not cls.prefix:
-+ cls.get_prefix()
-+
-+ if cls._key_existed(username, projectname, opts):
-+ return
-+ time_format = "%Y-%m-%d %H:%M:%S%z"
-+ expire = datetime.now(datetime.now(timezone.utc).astimezone().tzinfo) + timedelta(days=opts.signatrust_key_expire)
-+ data = {
-+ "name": cls.get_key_name(username, projectname, prefix=False),
-+ "description": "gpg key to sign rpms in {}/{}".format(username, projectname),
-+ "key_type": "pgp",
-+ "visibility": "private", # we use private key type for those key will not be seen by other users
-+ "attributes": {
-+ "digest_algorithm": "sha2_256",
-+ "key_type": "rsa",
-+ "key_length": "2048",
-+ "email": "{}".format(create_gpg_email(username, projectname, opts.sign_domain)),
-+ },
-+ "expire_at": datetime.strftime(expire, time_format)
-+ }
-+
-+ headers = {
-+ "content-type": "application/json",
-+ "accept": "application/json",
-+ "Authorization": opts.signatrust_token
-+ }
-
-- if errors:
-- raise CoprSignError("Rpm unsign failed, affected rpms: {}"
-- .format([err[0] for err in errors]))
-+ try:
-+ res = requests.post("{}/api/v1/keys/".format(opts.signatrust_host), headers=headers, json=data)
-+ except Exception as e:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to get userinfo", request="/api/v1/keys/", response=res)
-+
-+ if res.status_code >= 400:
-+ raise CoprKeygenRequestError(
-+ msg="Failed to create user payload: {}".format(data), request="/api/v1/keys/", response=res)
-diff --git a/tests/test_background_worker_build.py b/backend/tests/test_background_worker_build.py
-index 1dfe19563..ba1e5aeab 100644
---- a/tests/test_background_worker_build.py
-+++ b/tests/test_background_worker_build.py
-@@ -88,6 +88,12 @@ def _fake_host():
- host.release = mock.MagicMock()
- return host
-
-+@pytest.fixture(autouse=True)
-+def get_opts():
-+ with pytest.MonkeyPatch.context() as mp:
-+ mp.setattr("copr_backend.sign.get_backend_opts", lambda: None)
-+ yield mp
-+
- @pytest.fixture
- def f_build_something():
- """
-@@ -324,8 +330,8 @@ def test_full_srpm_build(f_build_srpm):
- "00855954/hello-2.8-1.src.rpm")
-
-
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
--@mock.patch("copr_backend.sign._sign_one")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign._sign_one")
- def test_build_and_sign(mc_sign_one, f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -351,7 +357,7 @@ def test_build_and_sign(mc_sign_one, f_build_rpm_sign_on, caplog):
- _, level, _ = record
- assert level <= logging.INFO
-
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- @mock.patch("copr_backend.sign._sign_one")
- @_patch_bwbuild_object("sign_rpms_in_dir")
- def test_sign_built_packages_exception(mc_sign_rpms, mc_sign_one,
-@@ -452,7 +458,7 @@ def test_invalid_job_info(f_build_rpm_case, caplog):
-
- @mock.patch("copr_backend.vm_alloc.time.sleep", mock.MagicMock())
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_build_on_vm_allocation(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -513,7 +519,7 @@ class _CancelFunction():
- time.sleep(0.25)
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_build_on_tail_log_no_ssh(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -542,7 +548,7 @@ def test_cancel_build_on_tail_log_no_ssh(f_build_rpm_sign_on, caplog):
- assert "canceled stdout" in log
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_before_vm(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -558,7 +564,7 @@ def test_cancel_before_vm(f_build_rpm_sign_on, caplog):
- assert_logs_dont_exist(["Releasing VM back to pool"], caplog)
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_before_start(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -578,7 +584,7 @@ def test_cancel_before_start(f_build_rpm_sign_on, caplog):
- ], caplog)
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_build_retry(f_build_rpm_sign_on):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -650,7 +656,7 @@ def test_fe_failed_start(f_build_rpm_sign_on, caplog):
- assert worker.redis_get_worker_flag("status") == "done"
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_script_failure(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-@@ -672,7 +678,7 @@ def test_cancel_script_failure(f_build_rpm_sign_on, caplog):
- ], caplog)
-
- @_patch_bwbuild_object("CANCEL_CHECK_PERIOD", 0.5)
--@mock.patch("copr_backend.sign.SIGN_BINARY", "tests/fake-bin-sign")
-+@mock.patch("copr_backend.sign.ObsSign.sign_cmd", "tests/fake-bin-sign")
- def test_cancel_build_during_log_download(f_build_rpm_sign_on, caplog):
- config = f_build_rpm_sign_on
- worker = config.bw
-diff --git a/tests/test_sign.py b/backend/tests/test_sign.py
-index bf2dd1b8c..13a7a2ebc 100644
---- a/tests/test_sign.py
-+++ b/tests/test_sign.py
-@@ -12,13 +12,16 @@ from copr_backend.exceptions import CoprSignError, CoprSignNoKeyError, CoprKeyge
- from copr_backend.sign import (
- get_pubkey, _sign_one, sign_rpms_in_dir, create_user_keys,
- gpg_hashtype_for_chroot,
-- call_sign_bin,
-+ call_sign_bin
- )
-+from copr_backend import helpers
-
- STDOUT = "stdout"
- STDERR = "stderr"
-
-
-+
-+
- class TestSign(object):
- # pylint: disable=too-many-public-methods
-
-@@ -38,6 +41,12 @@ class TestSign(object):
- if self.tmp_dir_path:
- shutil.rmtree(self.tmp_dir_path)
-
-+ @pytest.fixture(autouse=True)
-+ def get_opts(self):
-+ with pytest.MonkeyPatch.context() as mp:
-+ mp.setattr("copr_backend.sign.get_backend_opts", lambda: None)
-+ yield mp
-+
- @pytest.fixture
- def tmp_dir(self):
- subdir = "test_createrepo_{}".format(time.time())
-@@ -54,7 +63,7 @@ class TestSign(object):
- handle.write("1")
-
- @mock.patch("copr_backend.sign.Popen")
-- def test_get_pubkey(self, mc_popen):
-+ def test_get_pubkey(self, mc_popen, get_opts):
- mc_handle = MagicMock()
- mc_handle.communicate.return_value = (STDOUT, STDERR)
- mc_handle.returncode = 0
-@@ -198,9 +207,9 @@ class TestSign(object):
- create_user_keys(self.username, self.projectname, self.opts)
- assert "Failed to create key-pair for user: foo, project:bar" in str(err)
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_nothing(self, mc_gp, mc_cuk, mc_so,
- tmp_dir):
- # empty target dir doesn't produce error
-@@ -212,9 +221,9 @@ class TestSign(object):
- assert not mc_cuk.called
- assert not mc_so.called
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_ok(self, mc_gp, mc_cuk, mc_so,
- tmp_dir, tmp_files):
-
-@@ -234,9 +243,9 @@ class TestSign(object):
- assert os.path.join(self.tmp_dir_path, name) in pathes
- assert len(pathes) == count
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_error_on_pubkey(
- self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
-
-@@ -250,9 +259,9 @@ class TestSign(object):
- assert not mc_cuk.called
- assert not mc_so.called
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_no_pub_key(
- self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
-
-@@ -266,9 +275,9 @@ class TestSign(object):
- assert mc_cuk.called
- assert mc_so.called
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_sign_error_one(
- self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
-
-@@ -285,9 +294,9 @@ class TestSign(object):
-
- assert mc_so.called
-
-- @mock.patch("copr_backend.sign._sign_one")
-- @mock.patch("copr_backend.sign.create_user_keys")
-- @mock.patch("copr_backend.sign.get_pubkey")
-+ @mock.patch("copr_backend.sign.ObsSign._sign_one")
-+ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
-+ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
- def test_sign_rpms_id_dir_sign_error_all(
- self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
-