debian-koji/tests/test_hub/test_repo_requests.py
Mike McLean df4a54e204 kojira on demand work
squashed to keep the history more readable

commit b4383d81f48f9c58cb53119cb453034c5676657f
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Jun 21 09:03:07 2024 -0400

    unit tests

commit 151b6ea053fc2e93b104fb3f01749602401fa0ee
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 17:55:35 2024 -0400

    unit tests and fixes

commit 15457499665a0c0e0e45b17d19c6d07b6f681ca8
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 17:14:01 2024 -0400

    use tag name in waitrepo task for readability

commit a20a21d39d2cb96b02046788de77aa33a7cbc906
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 17:00:45 2024 -0400

    cleanup

commit a0058fce436a39de5cde6f11788ca4aaaa3553c0
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 16:44:22 2024 -0400

    better approach to repo lookup from task id

commit 057527d71318d4494d80a2f24510e82ac9bc33f8
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 10:42:08 2024 -0400

    support priority for requests

commit 882eaf2c4349e6f75db055fa36c80d66ab40526f
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 18 10:16:44 2024 -0400

    track user for request

commit 273739e2f43170d80dae9e3796185230fae0607e
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 15:37:16 2024 -0400

    update additional fields in repo_done_hook

commit d0a886eb161468675720549ad8a31921cd5c3647
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 15:14:38 2024 -0400

    simplify updateRepos

commit 2a3ab6839299dd507835804e6326d93f08aa4040
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 15:03:39 2024 -0400

    kojira: adjust cleanup of self.repos

commit dfc5934423b7f8f129ac9c737cc21d1798b33c2d
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 14:03:57 2024 -0400

    docs updates

commit 4c5d4c2b50b11844d5dd6c8295b33bcc4453928b
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 09:18:10 2024 -0400

    Apply repo_lifetime to custom repos even if current

commit 2b2d63a771244358f4a7d77766374448343d2c4c
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Jun 17 09:36:50 2024 -0400

    fix migration script

commit 447a3f47270a324463a335d19b8e2c657a99ee9b
Author: Tomas Kopecek <tkopecek@redhat.com>
Date:   Fri Jun 7 11:32:14 2024 +0200

    migration script

commit f73bbe88eea7caf31c908fdaa5231e39d0f0d0a8
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Jun 14 15:30:24 2024 -0400

    clean up some TODO items

commit 836c89131d2b125c2761cfbd3917473504d459e4
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Jun 14 11:43:13 2024 -0400

    update unit tests

commit 4822ec580b96ae63778b71cee2127364bc31d258
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Jun 14 11:17:24 2024 -0400

    streamline simple case for tag_first/last_change_event

commit 3474384c56a8a2e60288279b459000f3b9c54968
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Jun 11 16:11:55 2024 -0400

    backwards compatible age checks in kojira

commit e796db0bdc6e70b489179bcddaa899855d64b706
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Jun 14 11:49:37 2024 -0400

    repowatch unit test fixes

commit 7f17eb741502ab5417f70413f699c99e140f380d
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Jun 6 21:35:11 2024 -0400

    adjust watch output; die if request fails

commit a0318c44576d6acab459f623c8ff0ab6961bd6b4
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Jun 6 20:45:56 2024 -0400

    handle problem repos

commit d90ca6f9d41a39da86089a0fad7afdb649fd680b
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 30 22:43:56 2024 -0400

    fix typos

commit 29830d1b8125664ddeae5ccb7e6b6e53260cdc47
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 30 16:57:48 2024 -0400

    clarify --wait-repo help text

commit 43db92302643b67e7f6f419424d6813e5dca53f3
Author: Mike McLean <mikem@redhat.com>
Date:   Tue May 21 17:32:44 2024 -0400

    unit tests

commit 27f979fbccc5a286fba9caeec16ca7092fa79813
Author: Mike McLean <mikem@redhat.com>
Date:   Tue May 21 17:23:32 2024 -0400

    wait-repo compat

commit f3a8f76d9340b1bdddb5f7bab154962e848d4d10
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 16 20:14:59 2024 -0400

    fixes

commit 6638b0fd76b31aa49ad0cf79639014ad9ace09f0
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 16 16:41:50 2024 -0400

    use old regen-repo code for older hubs

commit 7f2d8ec49fe1d2d511759221a821a146a4ef6837
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 16 16:18:36 2024 -0400

    fixes

commit 791df709c10d3c10c9b79f59f4fda435ac3bd285
Author: Mike McLean <mikem@redhat.com>
Date:   Thu May 16 12:22:09 2024 -0400

    don't trigger regens from scheduler. kojira is enough

commit 75f5e695287b92d53e4f173f57b12b5a7159adaf
Author: Mike McLean <mikem@redhat.com>
Date:   Wed May 15 22:54:08 2024 -0400

    more docs

commit 0e0f53160bbe09e35409dabce63739eb50813310
Author: Mike McLean <mikem@redhat.com>
Date:   Wed May 15 21:49:27 2024 -0400

    support MaxRepoTasksMaven

commit 88da9639860cb7c0d92f7c3bc881cd480b4e1620
Author: Mike McLean <mikem@redhat.com>
Date:   Wed May 15 16:15:12 2024 -0400

    drop unused method

commit 4cdbe6c4d2ba8735312d0cd0095612c159db9cce
Author: Mike McLean <mikem@redhat.com>
Date:   Wed May 15 15:48:55 2024 -0400

    api for querying repo queue

commit 2367eb21e60865c8e5a2e19f2f840938dbbbc58b
Author: Mike McLean <mikem@redhat.com>
Date:   Wed May 15 15:24:44 2024 -0400

    flake8

commit 811378d703a68b63c577468b85f4a49a9be2c441
Author: Mike McLean <mikem@redhat.com>
Date:   Tue May 14 16:20:59 2024 -0400

    record custom opts in repo.json

commit d448b6b3417e95bff2bae3b5a3790877ac834816
Author: Mike McLean <mikem@redhat.com>
Date:   Mon May 13 15:32:33 2024 -0400

    drop unused RawClauses code

    will revisit in a later PR

commit 0422220e05ee3d43e5431a0d741f3632f42a8434
Author: Mike McLean <mikem@redhat.com>
Date:   Sat May 11 13:34:12 2024 -0400

    clean up BulkUpdateProcessor and add tests

commit 6721f847e655a3794d4f2fce383070cb6ad2d2d1
Author: Mike McLean <mikem@redhat.com>
Date:   Fri May 10 17:43:17 2024 -0400

    fix unit test after rebase

commit 833286eead2b278a99fe9ef80c13df88ca3af48c
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Apr 5 00:23:15 2024 -0400

    adjust valid_repo opts checks

commit 7f418d550d8636072292ee05f6e9748b622c2d89
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Apr 5 00:03:33 2024 -0400

    extend valid_repo unit test and fix a bug

commit eb844ba15894cb7fc2a739908e7d83c80fd82524
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 15:41:08 2024 -0400

    test_request_existing_req_invalid

commit 2e290453abf9ac31f51a1853aa123a2a34ad9605
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 15:22:06 2024 -0400

    test_request_at_event

commit 2c3389c24f5cabfbbaeb70512a4ba917cf5bd09b
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 11:14:37 2024 -0400

    test_request_new_req

commit 2cdeab9b5f5b0bff4c4806ae802e5f5e571bb25e
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 10:56:36 2024 -0400

    test_request_existing_req

commit 63c9ddab5f3e50b3537a82f390e9da5a66275a25
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 10:45:22 2024 -0400

    test_request_existing_repo

commit 03b5ba5c57ce1ade0cf7990d23ec599c8cb19482
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Apr 4 10:04:36 2024 -0400

    more stubs

commit 92d16847f2cc2db0d8ee5afcf2d812b9bb6467ec
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 22:44:00 2024 -0400

    fix import

commit 1f621685532564a1c1ac373e98bec57c59107e6c
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 22:16:25 2024 -0400

    stub test

commit 45eef344e701c910f172d5642676d8f70d44049a
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 22:01:31 2024 -0400

    link repo doc in toc

commit bfffe233051c71785c335a82f64bf2abaae50078
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 21:57:35 2024 -0400

    unused options

commit 19f5a55faecf8229d60d21fd3e334e9a7f813384
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 16:37:50 2024 -0400

    include new setting

commit b7f81bd18016f862d1246ab6c81172fcd9c8b0ed
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 08:21:16 2024 -0400

    test + fixes

commit 16564cfb8e2725b395c624139ce3d878a6dd9d53
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 07:44:15 2024 -0400

    more kojira unit tests

commit 6b55c51302331ea09a126b9f3efbc71da164c0fb
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Apr 3 07:06:20 2024 -0400

    fix unit test

commit 0b000c124b17f965c5606d30da792ba47db542cf
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Apr 2 22:07:08 2024 -0400

    refactor repo delete

commit 0a03623fb018c80c8d38896fc99686cac56307fa
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Apr 2 19:13:15 2024 -0400

    avoid circular import issue

commit 137d699b7653977f63f30041d9f5f1a88ae08d43
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Apr 2 19:03:18 2024 -0400

    some kojira cleanup

commit 252e69d6dd17bb407b88b79efbb243ca5e441765
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Apr 2 17:21:14 2024 -0400

    adjust state transition check

commit 336018081709fd44e7f12933b1ea59e02bff4aed
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Apr 2 16:05:45 2024 -0400

    update RepoQuery

commit 68bb44848d9024c5520d8e7e2cc262adaa083cd1
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Mar 12 11:46:59 2024 -0400

    decode query bytes in log

commit 818431fb9b09db162e73f7cb1adcddc8b151c821
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 29 14:47:16 2024 -0400

    sanity check requests before reusing

commit 63fee0ba1ea9d41d504bb09aeaea064246c16ff9
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 29 11:41:13 2024 -0400

    repo.query api call

commit bcf9a3cf64167612e3cd355aae7c41dd348cb8db
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 29 10:31:58 2024 -0400

    reduce some cli code duplication

commit 3e870cfd088c69c4aaaa9a0f938bcce740b3f42c
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Mar 28 18:27:18 2024 -0400

    tweak warnings in external repo check

commit 0dfda64b806f2377d9c591105c83a4f05851b17a
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Mar 28 14:43:50 2024 -0400

    clean repo queue

commit e5d328faa00c74e087f0b0d20aea7cd79ffb5ee4
Author: Mike McLean <mikem@redhat.com>
Date:   Thu Mar 28 14:05:12 2024 -0400

    implement retry limit for repo queue

commit 2185f3c9e32747c9657f2b9eb9ce6e3ca6d06ff8
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Mar 27 22:40:13 2024 -0400

    cleanup a few TODOs

commit b45be8c44367bca9819561a0e928999b9a9e2428
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Mar 27 22:22:17 2024 -0400

    tweak test

commit 546b161e20d0b310462dda705ae688e25b385cf5
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Mar 27 13:43:06 2024 -0400

    more kojira tests

commit f887fdd12e59e36be561c1a89687a523e112b9d4
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Mar 26 20:16:11 2024 -0400

    unit tests for RepoWatcher

commit e78b41431f3b45ae9e09d9a246982df9bb2c2374
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Mar 26 10:53:14 2024 -0400

    fix unit tests

commit 64328ecb27e5598ec8977617e67d6dd630bc8db7
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Mar 25 14:03:19 2024 -0400

    custom opts sorted out?

commit e3cee8c48bcf585a1a14aa8e56e43aaba2ccd63b
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Mar 25 12:50:34 2024 -0400

    allow containment operator

commit bef7bbc3b2a16a6643bedb47be044c202a2bad2d
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Mar 25 11:59:15 2024 -0400

    partial

commit 01788dfe386a07960c5c7888350e3917b44a0bab
Author: Mike McLean <mikem@redhat.com>
Date:   Sat Mar 23 13:47:22 2024 -0400

    fragment: struggling with repo opt timing

commit 44504bfbde4cf981391ea02127a05c4f0c2fc4a3
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 17:14:57 2024 -0400

    fine to have default values in the class

commit 1bfa520dd599acccd45f221f71c64fbefc3b5554
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 17:14:18 2024 -0400

    option renamed

commit a5db9d015a25f71fdb5e2dadcae55a8c5b7ec956
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 17:04:32 2024 -0400

    flake8

commit c02244f8018b651f309f39eb60f926209454dea2
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 16:59:15 2024 -0400

    more config options in repos.py

commit 9bf3edc0cf2c85a23964b79c4489bc9592656f16
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 15:39:52 2024 -0400

    use requests by default in regen-repo

commit 78c6e8a4459856fa333763b1977633307fd81cc3
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 13:49:00 2024 -0400

    adjust watch_fields

commit eadb2a24b9e0f324ac053c4bdede0865d4ed5bfa
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 12:27:23 2024 -0400

    adjust event validation

commit 3140e73cfccdcc25765c6f330073c991a44cbd9a
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 12:01:24 2024 -0400

    wait-repo tweaks

commit d1a8174cdd917bbf74882c51f1a7eaf4f02e542a
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 10:35:28 2024 -0400

    cli: wait-repo-request command

commit b2d08ac09880a1931b7f40b68d5ca765cd49a3a6
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 10:04:46 2024 -0400

    drop complex request options from wait-repo

commit b4ab55f241a693c0c0d08e386f998394a295fc7c
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 09:36:37 2024 -0400

    fix call

commit c04417439c4684342ac0d4423b341d363bc80e92
Author: Mike McLean <mikem@redhat.com>
Date:   Fri Mar 22 09:32:48 2024 -0400

    typo

commit 29be83b1523d45eb77cfe4959c9d6bc5c940ebbe
Author: Mike McLean <mikem@redhat.com>
Date:   Wed Mar 20 07:28:12 2024 -0400

    partial...

commit cd0ba3b6c2c47fe5bac4cf823b886462e092e2b3
Author: Mike McLean <mikem@redhat.com>
Date:   Tue Mar 19 23:13:47 2024 -0400

    drop event="new" code

commit 7f4f2356eceec03228e4a92b13e5593f956c390d
Author: Mike McLean <mikem@redhat.com>
Date:   Mon Mar 18 21:00:25 2024 -0400

    kojira on demand work

    squashed because the branch was getting unwieldy
    mostly working at this point, but there is a bit out outstanding work

    commit e127878460a932cc77c399f69c40f0993c765dc7
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 18 11:20:33 2024 -0400

        stale comment

    commit d0849d50b865f4f3783ddde5e1e6cf10db56ed39
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 23:58:13 2024 -0400

        don't expire at_event repos

    commit 8866db0e25b072aa12cc2827c62093b000fa7897
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 23:43:24 2024 -0400

        typo

    commit e2a5fd639b88c7b88708e782f0b7398296d2f805
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 23:40:08 2024 -0400

        repos.py: support at_event

    commit 6518f1656976ea2beb2cf732c82db0f159b09d15
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 22:20:35 2024 -0400

        update repo symlink logic

    commit 50d5e179f56393dd52c7225fc6f053d0095e9599
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 22:20:01 2024 -0400

        ...

    commit 429fc85b391e0b5e637e20859f1094a37a5eab39
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 21:18:44 2024 -0400

        block owner opt in makeTask and host.subtask

    commit 40fcfe667ef70987444756f6d5554919d89fb1de
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 20:49:37 2024 -0400

        db lock for repo queue

    commit dfd94fac8fb96328b12bcf2f8f6f7e2d52deea85
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 17:47:39 2024 -0400

        ...

    commit ecd9611e5d84d8a98920c40805616a6376ca652e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 17:45:38 2024 -0400

        move new exports around

    commit a2e086df07f7b03dc4505a61f9b213e6e2ff20a5
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:46:29 2024 -0400

        drop noisy debug line

    commit 497bd773baa274d205df3bba317ee80617cc56a0
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:20:56 2024 -0400

        ...

    commit 457c986894de754a927bc4880687e0f47c29cbdd
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:19:12 2024 -0400

        ...

    commit 3aa0fa4862b37b7d178b1b7bb9a521ea01e7dded
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:18:30 2024 -0400

        ...

    commit 391c2009671dea1270cce01666d04ad2ade0c323
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:15:32 2024 -0400

        ...

    commit f3794e2acc8eef38e0c65fb27d3b2b3a58f53311
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:12:53 2024 -0400

        ...

    commit aea5e1a91f9246cce5f162bbea3d4846e87b9811
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:11:53 2024 -0400

        ...

    commit dc68ed8f0a43c9418c0c813f05a761bc8303c2b0
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:10:34 2024 -0400

        typo

    commit 73c72c8ed08744a188e4ae977b7ba2d92c75401b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 16:08:15 2024 -0400

        pruning tweaks

    commit d3a10f8d5ef77a86db0e64a845f360d9f2cc2e17
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 15:50:57 2024 -0400

        kojira: use ordered dict for delete queue

    commit f6d7d44bac22840ee3ae1a93375c3b5ad430869c
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 14:59:05 2024 -0400

        rework repo expiration and lifetimes a bit

    commit 8bb91611c05ccb5d91910718a07494c08665ec22
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 00:27:34 2024 -0400

        more kojira rework

    commit 368d25a31d61eae8712591183bd2db1ff78f59d1
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 17 00:27:17 2024 -0400

        cleanup

    commit 292a1e4fdcc4098137156a42072e5bfda2f711df
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 23:51:45 2024 -0400

        track update time for repos

    commit 01a7469ef7bcd952f45d732e4bb3b5f4bab2338a
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 17:42:42 2024 -0400

        factor in implicit joins for fields="*"

    commit f9aba4557108b2005cf518e4bf316befa7f29911
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 15:25:34 2024 -0400

        partial repo docs

    commit 74eae7104849237a4049a78c94b05187a2219f74
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 13:17:36 2024 -0400

        remove some obsolete code from kojira

    commit d883807967a0d6d67a6e262a119ff5e03b8a947e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 11:42:48 2024 -0400

        ...

    commit 3bc3aa98913463aa209bba1cecc71fc30f6ef42f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Mar 16 11:12:50 2024 -0400

        do_auto_repos

    commit da69f05555f05ded973b4ade064ed7e5f7e70acd
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 23 14:56:30 2024 -0500

        fakehub: option to override config

    commit 13a4ffdf9cd915b6af7b85120d87d50b8f6db5ed
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 15 22:35:50 2024 -0400

        tweak logging

    commit 01af487cced25c0edaa9e98e5dc7bb7dc9c4d6bd
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 15 22:16:21 2024 -0400

        adjust archlist for external repo check

    commit eb1c66f57a508f65dcac0e32cfaa3e178ed40bad
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 15 18:45:53 2024 -0400

        tweak logging; wait-repo --new

    commit 3dab52d497926a6be80a3c98cc29f0cb6478926f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 15 15:03:23 2024 -0400

        typo

    commit 503365a79998aa2ee0eb2bd9b412747cdec50ab1
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 14 00:17:24 2024 -0400

        ...

    commit 46ec62e96334690344de18d535f7b9c4fd87d877
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 14 00:16:09 2024 -0400

        separate get/set for erepo data

    commit 25c2861509cfebcfc38be5fff6c0b382dfcca224
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 09:08:45 2024 -0400

        only update erepo data in db if it changed

    commit bc5db7494a486ae39b99dba4875547a8e8bc1ee0
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 09:03:03 2024 -0400

        ...

    commit 55b947fe2889dcb3b6112e9e80de926ef0ab70fa
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 08:48:45 2024 -0400

        partial work

    commit 7e91985a378754ae2ba88e0e2182bdf6302416ef
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 08:22:23 2024 -0400

        handle external_repo_data history in cli

    commit 0aeae31215af98ea8580307750389873f1e2521e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 08:15:50 2024 -0400

        set_external_repo_data

    commit d85e93c0c294770d2384a41a3f2c09b4a64ae3c4
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 13 07:58:18 2024 -0400

        support external_repo_data in query_history

    commit 88fcf7ac5b8893bd045af017df1eb22a3cce8cb0
    Merge: 8449ebfeb eba8de247
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Mar 12 00:01:57 2024 -0400

        Merge remote-tracking branch 'origin' into kojira-on-demand

    commit 8449ebfeb7976f5a5bfea78322c536cf0db6aa54
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 23:56:25 2024 -0400

        drop stray file

    commit 3d3716454b9f12c1807f8992ecd01cde3d9aade9
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 23:49:20 2024 -0400

        flake8

    commit f9014b6b689e5a1baf355842cf13905b8c50c3d8
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 23:44:32 2024 -0400

        handle deleted tags sanely in tag_last_change_event

    commit 7d584e99a1a580039d18210c2cc857eb3419394f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 14:50:07 2024 -0400

        typo

    commit 6ac5921ce55ed356ba8c66466ebf56bb424591a9
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 14:49:35 2024 -0400

        add external_repo_data table. check ext repo tables for first/last tag change events

    commit e107400463679113971daaa400d75ec006f4dca5
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Mar 11 12:14:21 2024 -0400

        fix newer_than logic in WaitrepoTask

    commit 4a1175a35e6ad7c59b3622a6028e2cd68e29bb79
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 23:47:29 2024 -0400

        todos

    commit c13d9e99d19bc40e59fd136b540b6a8c6e12a50f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 23:30:59 2024 -0400

        AllowNewRepo hub config

    commit e3176cda238d3357fed0b905b03dfc0319dab12e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 23:00:45 2024 -0400

        fixes

    commit d486960a441fbb517492a61ef2529370035a765a
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 22:48:00 2024 -0400

        request min_event never null or in future

    commit 4cc0d38b8e4bf1254bb156d085614f83929e1161
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 22:32:45 2024 -0400

        ...

    commit bb0dc41cd6be4c42d4cd033e07210f1184c2c385
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 22:23:52 2024 -0400

        default min_event. don't allow future events

    commit 1dccf0a56b1e3f83107760111264249527abeb68
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 17:27:11 2024 -0400

        use BulkUpdateProcessor in update_end_events

    commit 03c791edd3bb49359f2a01eaf53cbb717c53833e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Mar 10 17:26:26 2024 -0400

        BulkUpdateProcessor

    commit 4bd2a0da1c998ce14fd856e68318551747867e06
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 14:53:53 2024 -0500

        update_end_events()

    commit b45b13bcba141ea6b30618fb76c1a94593dfe569
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 13:03:33 2024 -0500

        record begin/end events in repo_init

    commit 6f1adf51d9e24f80369df8b96010c0d6d123b448
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 12:33:40 2024 -0500

        QueryView: accept single field value

    commit 6b292d9a4b1bda56ff8091fbcb126749f952d045
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 12:28:02 2024 -0500

        adjust query fields

    commit e9e8e74703de8b6c531944c05d54447f0d7cb13f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 12:18:12 2024 -0500

        QueryView: adjust special field name handling

    commit 97d910d70634183a3d5ae804176a5c8691882b7a
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Mar 8 11:45:54 2024 -0500

        adjust event fields

    commit c70d34805227a61ab96176537dae64db3883e58f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 23:37:29 2024 -0500

        honor owner opt to make_task

    commit 40601d220179eb9718023002f8811ce5cbd09860
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 23:29:50 2024 -0500

        ...

    commit 6f84ca3aa8c24d4618294027dce7a23620a3e2d7
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 23:24:22 2024 -0500

        typo

    commit c423b8a4cc5fd4ed5c762e7b5adc06449c72ea70
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 23:22:18 2024 -0500

        use kojira user for repo tasks

    commit 63dacff462ce064bbdf0b5c6e8ef14b2abe08e0c
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 23:05:12 2024 -0500

        hook to fulfill requests when repos are marked ready

    commit aa79055c1e404a4c4fa9ac894fe978c8f9827f72
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 01:08:19 2024 -0500

        no more data field

    commit 7dd029fb94e24004793e2d1232b3225b3cee5c97
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 01:01:41 2024 -0500

        use full opts in request entries too

    commit 73dc2f232b231467d12355af0ace14284f5422a8
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 00:54:41 2024 -0500

        ...

    commit 414d0a55cf66d93b6fb79e9677f68fd141edc655
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 00:54:01 2024 -0500

        propagate opts in repo_init

    commit 99c1dde4771164d215f8c9a9acc0dadb678d047b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 00:20:57 2024 -0500

        include opts in query

    commit 08289b3444612920856e6a949a379f61cb46b5e7
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 00:15:12 2024 -0500

        missing import

    commit bc3ca72c084b8e8de678ecbdcf6bbcfe972363e1
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Mar 7 00:10:45 2024 -0500

        more opts support

    commit f7c12cfe5f5b6c6c7895cd5eb4cdeb45757022a1
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 23:59:08 2024 -0500

        handle repo opts in request call

    commit 02a75f3996d59ae36f046327fca766e8799ef35b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 22:01:06 2024 -0500

        fix import

    commit 7fe52dc83a80c0f68580d274bd2e60c57ab2e26d
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 21:58:59 2024 -0500

        fix fields

    commit f016c3a46d901ca762f5e8824fcd5efad2eede57
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 21:47:40 2024 -0500

        move code into kojihub/repos

    commit 9953009d3cc6f08cd16cbaa593ae79796ac86fa2
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 21:15:17 2024 -0500

        more unit test fixes

    commit f5decfaff3f56601262752e8a06b6f97bc4cfb33
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 20:51:07 2024 -0500

        unit test

    commit b51d4979824abe6ddc402011d21394854f46687e
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Mar 6 20:19:06 2024 -0500

        flake8

    commit aeee5b59df4e9da93db83874f022419c24b37162
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 20 18:05:25 2024 -0500

        stub: tracking opts

    commit b5c150b52f575c681bdacb4c87e690653edc465a
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 15:11:40 2024 -0500

        different approach for raw clauses

    commit a9001c97935f3ad90571589688b1f291242bad08
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 14:32:57 2024 -0500

        and any necessary values and joins

    commit 84a46633b7dc1303e48367b614b99de3730a865d
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 14:17:12 2024 -0500

        give hub code a way to raw clauses with QueryView

    commit 5d43c18f56563fc14f12d12c57f044125a5b33f9
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 14:09:27 2024 -0500

        private vars

    commit 91992f2e7b0a6cdd5e7cf8b99f6c37cfb20b08a6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 14:02:07 2024 -0500

        saner data from get_fields

    commit 1e581cd5a5f3a6e257c3147a8ea763987984403c
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 13:26:34 2024 -0500

        update test and include tag_first_change_event()

    commit 3509300b0b1c6bb516b5552f2b1d37008231efae
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 12:42:53 2024 -0500

        revert global verbose option

    commit 4173e8610b0beed3dcea14849da1f115eb43c293
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 19 07:59:48 2024 -0500

        better ordering support in QueryView

    commit 359543b95cd524d5f4d8d82854680452ee07fd00
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Feb 18 01:19:30 2024 -0500

        also include test from multirepo

    commit 1ceb8c01f92cfe5029c78688b14f643e1fa8be12
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Feb 18 00:18:39 2024 -0500

        constraint

    commit 064bfc18b3a07edd602192bc4f48ac52adeedc3f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sun Feb 18 00:00:15 2024 -0500

        tagFirstChangeEvent, plus fix

    commit 0efbfed21ec3b66841a7e4996e59bc8aaeed352b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 22:37:08 2024 -0500

        fix

    commit 3ead49b9ed7f643e7ba2db2077993eb515f10e38
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 21:54:05 2024 -0500

        cleanup

    commit be2beb37fd35b46a5b4d60f39c8040640dfc7800
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 21:20:29 2024 -0500

        rename request field, clean up Watcher args

    commit d392a974a1cbba119abc6a9e99e54d45a0cf0d62
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 18:38:21 2024 -0500

        ...

    commit 70ee37dbafc6c4e77a62aac44f11747c0f6bfc25
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 18:37:08 2024 -0500

        use tagLastChangeEvent for min_event=last

    commit 82d0d77679afc163bb5c36e43f834c109d7e6371
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 18:33:04 2024 -0500

        tag_last_change_event: support inheritance

    commit c3c87f8ccf4feea321d9bfa54cc1f223431a8d13
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 17:55:10 2024 -0500

        waitrepo anon mode (no request)

    commit c6994353d8daa4cb615eae4dde0368b97ea33d18
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 09:32:39 2024 -0500

        don't reuse a request for a future event

    commit 22abfadc57adcf11229336eede6459585a293da6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 09:16:47 2024 -0500

        ...

    commit c7b899c4a62d667d96e8320b6fa96106972f5859
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 09:10:22 2024 -0500

        ...

    commit a185fd86766c283fd9c18a4d95546a8e36fd21c9
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 09:08:31 2024 -0500

        ...

    commit 87401bddac38ebb658f2e9e4fbe36af2e6010e42
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 09:06:48 2024 -0500

        ...

    commit bb72bd0e2d78f2d21168144a976e772473efeb16
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 08:59:44 2024 -0500

        ...

    commit 4dbeb0edfa55cf39f4c897b3c15345e2daf9dad6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 08:59:10 2024 -0500

        ...

    commit 994e13d538d580ea9f7499310b8a0e4cd841af07
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 08:57:22 2024 -0500

        ...

    commit 1fee9331e72e4d48eccfd640183563a909181af6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 08:53:06 2024 -0500

        ...

    commit e74eea41048a5ec6f4a9c52025c2e452f640a808
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 00:57:11 2024 -0500

        ...

    commit ec1a581ba23b292ab840b740dabd1f3e4854fe33
    Author: Mike McLean <mikem@redhat.com>
    Date:   Sat Feb 17 00:48:48 2024 -0500

        attempting to wire this up into newRepo and waitrepo task

    commit 7eee457230a2b0e6aa9b974e94e4ca516227a196
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 18:58:18 2024 -0500

        ...

    commit 1c719d642da5f5c2ca0b7ce9af170054767423c6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 18:56:11 2024 -0500

        adjust checkRepoRequest return

    commit e6e5f15961c7801b1777743b799fbe2c96a08138
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 18:00:27 2024 -0500

        handle repo requests in scheduler loop

    commit a0dde4e3625110671bcea7abbdab0f0c03142cbc
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 11:06:00 2024 -0500

        tweak repo report in taginfo cli

    commit 2d860a17caf770507c67a89ac234d17c200c30ab
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 10:46:13 2024 -0500

        enable/clarify new repo fields

    commit 7204ce3753450981300bf78102fc40f1b41786b4
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 09:38:59 2024 -0500

        syntax

    commit 96236f4ef93e5babeb0800b5b4a16117a3e8c1df
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 10:20:34 2024 -0500

        pull tag_last_change_event and repo fields from multirepo branch

    commit a707c19eda9bc6efc22ce004367cbee960fcccb6
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 16 09:26:07 2024 -0500

        partial: check_repo_queue

    commit a208d128e60bdb4ad531938d55b2c793b65ab24b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 19:35:03 2024 -0500

        ...

    commit e9a601059fb9ceb89ec9b84680afd6dc276424f9
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 19:22:55 2024 -0500

        ...

    commit 067e385861766d7a355d5671a1e1e73ebd737b97
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 19:14:11 2024 -0500

        use RepoView more

    commit e5b4a58b65c6f195f724fb135acea6dd18abc3c2
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 17:37:47 2024 -0500

        executeOne

    commit 45aecfeb0a32c097fc65574296958573e6405009
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 17:29:06 2024 -0500

        ...

    commit 41314dc10c3a1a13f39628de5caedc7486193c7b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 17:27:40 2024 -0500

        only return one req

    commit c44ed9e4e3bc349e4107df79847049503a2c75be
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 14:57:11 2024 -0500

        ...

    commit cfd60878ada8196616fd401fb6cbaf7aa2dcc98b
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 11:10:31 2024 -0500

        ...

    commit 11f65335ca9c6167b8f457460a58471c37ae4098
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 15 09:12:34 2024 -0500

        testing

    commit c05f8f3b3f64c3aeef5ff0296dc181123c756952
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Feb 14 22:52:14 2024 -0500

        flesh out stub

    commit fd9c57c2c95bb5a1bd051d9d1e7e73e2f3fcb9b0
    Author: Mike McLean <mikem@redhat.com>
    Date:   Wed Feb 14 22:26:19 2024 -0500

        ...

    commit d59f38a5adc90607556a1671c85b808209389edd
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 22:19:36 2024 -0500

        more fragments

    commit 2d1b45c66e1cc3f41f6812b7b6d4bd66c4acf419
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 20:38:04 2024 -0500

        XXX DEBUG CODE

    commit d8e3a4bd205acb5ec1940fa30e29701f0a358d51
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 20:37:52 2024 -0500

        ...

    commit 0744a29bd303bf9b381aa48e3e5dd98e8b7373ef
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 20:37:40 2024 -0500

        ...

    commit 0726f8d22b227e002f7ddd927829a1e3ec66681f
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 20:27:22 2024 -0500

        RepoWatcher stub

    commit a74a74ef9688b1d27b528dd8e2de8ff3b63f97ae
    Author: Mike McLean <mikem@redhat.com>
    Date:   Tue Feb 6 00:05:49 2024 -0500

        ...

    commit d68c2902015a4998f59355aa224924e5ace21b0a
    Author: Mike McLean <mikem@redhat.com>
    Date:   Mon Feb 5 08:18:56 2024 -0500

        ...

    commit ff8538344e1bf24d7b94ad45f26fb1548be4782d
    Author: Mike McLean <mikem@redhat.com>
    Date:   Fri Feb 2 00:00:41 2024 -0500

        partial

    commit f618ed321108e0094ab95e054cb5d53fb2e0dfe1
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 1 23:54:57 2024 -0500

        tweak unit test

    commit 208a2f441401cefd65a7a92d91b6b76bf5dd97d3
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 1 22:52:37 2024 -0500

        comments

    commit 8fe5b4f0d773f190c037ab95520623a3d250c069
    Author: Mike McLean <mikem@redhat.com>
    Date:   Thu Feb 1 01:43:28 2024 -0500

        repo_queue stub
2024-06-21 14:35:59 -04:00

1427 lines
54 KiB
Python

import datetime
import json
import mock
import shutil
import tempfile
import unittest
import koji
import kojihub
import kojihub.db
from kojihub import repos
QP = repos.QueryProcessor
IP = repos.InsertProcessor
UP = repos.UpdateProcessor
TASK = kojihub.Task
class MyError(Exception):
pass
class BaseTest(unittest.TestCase):
def setUp(self):
self.context = mock.MagicMock()
self.context.session.assertLogin = mock.MagicMock()
self.getLastEvent = mock.MagicMock()
self.getEvent = mock.MagicMock()
self.context.handlers = {
'getLastEvent': self.getLastEvent,
'getEvent': self.getEvent,
}
mock.patch('kojihub.repos.context', new=self.context).start()
mock.patch('kojihub.db.context', new=self.context).start()
mock.patch('kojihub.kojihub.context', new=self.context).start()
self.context.opts = {
# duplicating hub defaults
'MaxRepoTasks': 10,
'MaxRepoTasksMaven': 2,
'RepoRetries': 3,
'RequestCleanTime': 60 * 24,
'RepoLag': 3600,
'RepoAutoLag': 7200,
'RepoLagWindow': 600,
'RepoQueueUser': 'kojira',
'DebuginfoTags': '',
'SourceTags': '',
'SeparateSourceTags': '',
'EnableMaven': False,
}
self.QueryProcessor = mock.patch('kojihub.repos.QueryProcessor',
side_effect=self.getQuery).start()
self.queries = []
self.InsertProcessor = mock.patch('kojihub.repos.InsertProcessor',
side_effect=self.getInsert).start()
self.inserts = []
self.UpdateProcessor = mock.patch('kojihub.repos.UpdateProcessor',
side_effect=self.getUpdate).start()
self.updates = []
self._dml = mock.patch('kojihub.db._dml').start()
self.exports = kojihub.RootExports()
self.get_tag = mock.patch('kojihub.kojihub.get_tag').start()
self.get_id = mock.patch('kojihub.kojihub.get_id').start()
self.make_task = mock.patch('kojihub.kojihub.make_task').start()
self.tag_last_change_event = mock.patch('kojihub.kojihub.tag_last_change_event').start()
self.query_execute = mock.MagicMock()
self.query_executeOne = mock.MagicMock()
self.query_singleValue = mock.MagicMock()
self.RepoQueueQuery = mock.patch('kojihub.repos.RepoQueueQuery').start()
self.RepoQuery = mock.patch('kojihub.repos.RepoQuery').start()
self.nextval = mock.patch('kojihub.repos.nextval').start()
def tearDown(self):
mock.patch.stopall()
def getQuery(self, *args, **kwargs):
query = QP(*args, **kwargs)
query.execute = self.query_execute
query.executeOne = self.query_executeOne
query.singleValue = self.query_singleValue
self.queries.append(query)
return query
def getInsert(self, *args, **kwargs):
insert = IP(*args, **kwargs)
insert.execute = mock.MagicMock()
self.inserts.append(insert)
return insert
def getUpdate(self, *args, **kwargs):
update = UP(*args, **kwargs)
update.execute = mock.MagicMock()
self.updates.append(update)
return update
class TestRepoQueue(BaseTest):
def setUp(self):
super(TestRepoQueue, self).setUp()
self.clean_repo_queue = mock.patch('kojihub.repos.clean_repo_queue').start()
self.repo_queue_task = mock.patch('kojihub.repos.repo_queue_task').start()
self.get_repo_from_task = mock.patch('kojihub.repos.get_repo_from_task').start()
self.valid_repo = mock.patch('kojihub.repos.valid_repo').start()
self.db_lock = mock.patch('kojihub.repos.db_lock').start()
self.db_lock.return_value = True
def test_nolock(self):
self.db_lock.return_value = False
repos.check_repo_queue()
self.db_lock.assert_called_once()
self.RepoQueueQuery.assert_not_called()
def test_check_queue_full(self):
self.context.opts['MaxRepoTasks'] = 10
basereq = {'task_state': koji.TASK_STATES['FREE'], 'opts': {}, 'tries': 1}
# 10 reqs with free tasks
reqs = [dict({'id': n, 'task_id': 100 + n}, **basereq) for n in range(10)]
# plus one with no task
reqs.append({'id': 99, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1})
self.RepoQueueQuery.return_value.execute.return_value = reqs
repos.check_repo_queue()
self.repo_queue_task.assert_not_called()
self.UpdateProcessor.assert_not_called()
self.clean_repo_queue.assert_not_called()
def test_check_maven_full(self):
self.context.opts['MaxRepoTasksMaven'] = 2
basereq = {'task_state': koji.TASK_STATES['FREE'], 'opts': {'maven': True}, 'tries': 1}
# 2 maven reqs with free tasks
reqs = [dict({'id': n, 'task_id': 100 + n}, **basereq) for n in range(2)]
# plus two more, one maven, one not
req_a = {'id': 98, 'task_id': None, 'task_state': None, 'opts': {'maven': True}, 'tries': 1}
req_b = {'id': 99, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1}
reqs.extend([req_a, req_b])
self.RepoQueueQuery.return_value.execute.return_value = reqs
repos.check_repo_queue()
# only the non-maven should get a task
self.repo_queue_task.assert_called_once_with(req_b)
self.UpdateProcessor.assert_called_once()
self.clean_repo_queue.assert_called_once()
def test_check_queue_filled(self):
# fill up the queue
self.context.opts['MaxRepoTasks'] = 10
basereq = {'task_state': koji.TASK_STATES['FREE'], 'opts': {}, 'tries': 1}
# 9 reqs with free tasks
reqs = [dict({'id': n, 'task_id': 100 + n}, **basereq) for n in range(9)]
# plus two more
req_a = {'id': 98, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1}
req_b = {'id': 99, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1}
reqs.extend([req_a, req_b])
self.RepoQueueQuery.return_value.execute.return_value = reqs
repos.check_repo_queue()
# req_a should be fulfilled, but not req_b
self.repo_queue_task.assert_called_once_with(req_a)
self.UpdateProcessor.assert_called_once()
self.clean_repo_queue.assert_called_once()
def test_check_queue_filled_maven(self):
# fill up the queue
self.context.opts['MaxRepoTasks'] = 10
self.context.opts['MaxRepoTasksMaven'] = 2
base1 = {'task_state': koji.TASK_STATES['FREE'], 'opts': {}, 'tries': 1}
base2 = {'task_state': koji.TASK_STATES['FREE'], 'opts': {'maven': True}, 'tries': 1}
# 7 reqs with free tasks
reqs = [dict({'id': n, 'task_id': 100 + n}, **base1) for n in range(7)]
# 1 maven req with free tasks
reqs.append(dict({'id': 7, 'task_id': 107}, **base2))
# plus 4 more, two maven, two not
req_a = {'id': 96, 'task_id': None, 'task_state': None, 'opts': {'maven': True}, 'tries': 1}
req_b = {'id': 97, 'task_id': None, 'task_state': None, 'opts': {'maven': True}, 'tries': 1}
req_c = {'id': 98, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1}
req_d = {'id': 99, 'task_id': None, 'task_state': None, 'opts': {}, 'tries': 1}
reqs.extend([req_a, req_b, req_c, req_d])
self.RepoQueueQuery.return_value.execute.return_value = reqs
repos.check_repo_queue()
# req_a and req_c should be fulfilled, but not b or d
expected = [mock.call(req_a), mock.call(req_c)]
self.assertEqual(self.repo_queue_task.call_args_list, expected)
self.clean_repo_queue.assert_called_once()
def test_check_queue_retry(self):
self.context.opts['MaxRepoTasks'] = 10
self.context.opts['MaxRepoTasksMaven'] = 2
self.context.opts['RepoRetries'] = 3
base = {'id': 100, 'task_id': 200, 'task_state': koji.TASK_STATES['FREE'], 'opts': {},
'tries': 1}
# these should get retries
reqs1 = [
dict(base, task_state=koji.TASK_STATES['CANCELED']),
dict(base, task_state=koji.TASK_STATES['CANCELED'], tries=3),
dict(base, task_state=koji.TASK_STATES['FAILED']),
dict(base, task_state=koji.TASK_STATES['FAILED'], tries=3),
]
# these should not
reqs2 = [
dict(base, task_state=koji.TASK_STATES['OPEN']),
dict(base, task_state=koji.TASK_STATES['FREE']),
dict(base, task_state=koji.TASK_STATES['CANCELED'], tries=4),
dict(base, task_state=koji.TASK_STATES['FAILED'], tries=4),
]
self.RepoQueueQuery.return_value.execute.return_value = reqs1 + reqs2
repos.check_repo_queue()
expected = [mock.call(r) for r in reqs1]
self.assertEqual(self.repo_queue_task.call_args_list, expected)
self.assertEqual(len(self.UpdateProcessor.mock_calls), 8)
self.clean_repo_queue.assert_called_once()
def test_check_queue_badrepo1(self):
req = {'id': 100, 'task_id': 200, 'task_state': koji.TASK_STATES['CLOSED'], 'opts': {},
'tries': 1}
self.RepoQueueQuery.return_value.execute.return_value = [req]
self.get_repo_from_task.return_value = None
# should retry
repos.check_repo_queue()
self.repo_queue_task.assert_called_once_with(req)
self.UpdateProcessor.assert_called_once()
self.clean_repo_queue.assert_called_once()
def test_check_queue_badrepo2(self):
req = {'id': 100, 'task_id': 200, 'task_state': koji.TASK_STATES['CLOSED'], 'opts': {},
'tries': 1}
self.RepoQueueQuery.return_value.execute.return_value = [req]
self.get_repo_from_task.return_value = 'REPO'
self.valid_repo.return_value = False
# should retry
repos.check_repo_queue()
self.repo_queue_task.assert_called_once_with(req)
self.UpdateProcessor.assert_called_once()
self.clean_repo_queue.assert_called_once()
def test_check_queue_goodrepo(self):
req = {'id': 100, 'task_id': 200, 'task_state': koji.TASK_STATES['CLOSED'], 'opts': {},
'tries': 1}
self.RepoQueueQuery.return_value.execute.return_value = [req]
repo = {'id': 123, 'sentinel': 'hello 123dfs'}
self.get_repo_from_task.return_value = repo
self.valid_repo.return_value = True
# should update, not retry
repos.check_repo_queue()
self.repo_queue_task.assert_not_called()
self.UpdateProcessor.assert_called_once()
self.clean_repo_queue.assert_called_once()
class TestRepoFromTask(BaseTest):
def setUp(self):
super(TestRepoFromTask, self).setUp()
self.Task = mock.patch('kojihub.kojihub.Task').start()
def test_valid(self):
result = [1234, "ignored event id"]
self.Task.return_value.getResult.return_value = result
self.RepoQuery.return_value.execute.return_value = ["REPO"]
repo = repos.get_repo_from_task("TASK_ID")
self.assertEqual(repo, "REPO")
self.Task.assert_called_once_with("TASK_ID")
self.RepoQuery.assert_called_once_with([['id', '=', 1234]])
def test_missing(self):
result = [1234, "ignored event id"]
self.Task.return_value.getResult.return_value = result
self.RepoQuery.return_value.execute.return_value = []
repo = repos.get_repo_from_task("TASK_ID")
self.assertEqual(repo, None)
self.Task.assert_called_once_with("TASK_ID")
self.RepoQuery.assert_called_once_with([['id', '=', 1234]])
def test_invalid(self):
result = ["invalid: not an int", "ignored event id"]
self.Task.return_value.getResult.return_value = result
self.RepoQuery.return_value.execute.return_value = []
repo = repos.get_repo_from_task("TASK_ID")
self.assertEqual(repo, None)
self.Task.assert_called_once_with("TASK_ID")
self.RepoQuery.assert_not_called()
class TestRepoRequests(BaseTest):
def test_clean_queue(self):
repos.clean_repo_queue()
def test_valid_repo(self):
# match
req = {'id': 101,
'at_event': None,
'min_event': 101010,
'opts': {},
'tag_id': 42,
'tag_name': 'TAG'}
repo = {'id': 999,
'tag_id': 42,
'begin_event': 497440,
'create_event': 101020,
'custom_opts': {},
'dist': False,
'opts': {'debuginfo': False, 'separate_src': False, 'src': False},
'state': 1}
check = repos.valid_repo(req, repo)
self.assertTrue(check)
# wrong tag
bad = repo.copy()
bad['tag_id'] = 99
check = repos.valid_repo(req, bad)
self.assertFalse(check)
# wrong state
bad = repo.copy()
bad['state'] = 2
check = repos.valid_repo(req, bad)
self.assertFalse(check)
# wrong event
bad = repo.copy()
bad['create_event'] = 101000
check = repos.valid_repo(req, bad)
self.assertFalse(check)
# wrong at_event
req2 = req.copy()
req2.update(min_event=None, at_event=10000)
bad = repo.copy()
bad['create_event'] = 101000
check = repos.valid_repo(req2, bad)
self.assertFalse(check)
# different opt value
bad = repo.copy()
bad['opts'] = {'debuginfo': True, 'separate_src': False, 'src': False}
bad['custom_opts'] = {'debuginfo': True}
check = repos.valid_repo(req, bad)
self.assertFalse(check)
# missing opt value
req2 = req.copy()
req2.update(opts={'debuginfo':True})
bad = repo.copy()
bad['opts'] = {'separate_src': False, 'src': False}
bad['custom_opts'] = {'debuginfo': True}
check = repos.valid_repo(req2, bad)
self.assertFalse(check)
# wrong custom opts
req2 = req.copy()
req2.update(opts={'src':True})
bad = repo.copy()
bad['opts'] = {'debuginfo': True, 'separate_src': False, 'src': False}
bad['custom_opts'] = {'debuginfo': True}
check = repos.valid_repo(req2, bad)
self.assertFalse(check)
# invalid opts
req2 = req.copy()
req2.update(opts={'src':True})
bad = repo.copy()
bad['opts'] = {}
# opts field should never be blank
bad['custom_opts'] = {}
check = repos.valid_repo(req2, bad)
self.assertFalse(check)
class TestDoneHook(BaseTest):
def setUp(self):
super(TestDoneHook, self).setUp()
self.Savepoint = mock.patch('kojihub.repos.Savepoint').start()
def test_simple(self):
repos.repo_done_hook(100)
def test_no_repo(self):
self.RepoQuery.return_value.executeOne.return_value = None
# should return without error
repos.repo_done_hook(100)
# should not query further or update
self.RepoQueueQuery.assert_not_called()
self.UpdateProcessor.assert_not_called()
# no exception
self.Savepoint.return_value.rollback.assert_not_called()
def test_dist_repo(self):
self.RepoQuery.return_value.executeOne.return_value = {'dist': True}
# hook should not process dist repos
repos.repo_done_hook(100)
# should not query further or update
self.RepoQueueQuery.assert_not_called()
self.UpdateProcessor.assert_not_called()
# no exception
self.Savepoint.return_value.rollback.assert_not_called()
def test_invalid_repo(self):
# hook should not process invalid repos
self.RepoQuery.return_value.executeOne.return_value = {'dist': False, 'opts': None, 'custom_opts': {}}
repos.repo_done_hook(100)
# should not query further or update
self.RepoQueueQuery.assert_not_called()
self.UpdateProcessor.assert_not_called()
# no exception
self.Savepoint.return_value.rollback.assert_not_called()
def test_no_match(self):
repo = {'dist': False, 'opts': {}, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010}
self.RepoQuery.return_value.executeOne.return_value = repo
self.RepoQueueQuery.return_value.execute.return_value = []
repos.repo_done_hook(100)
self.assertEqual(len(self.RepoQueueQuery.call_args_list), 2)
# should not update
self.UpdateProcessor.assert_not_called()
# no exception
self.Savepoint.return_value.rollback.assert_not_called()
def test_match(self):
repo = {'id': 55, 'dist': False, 'opts': {}, 'custom_opts': {}, 'tag_id': 'TAGID',
'create_event': 101010}
self.RepoQuery.return_value.executeOne.return_value = repo
req= {'id': 'REQ_ID'}
self.RepoQueueQuery.return_value.execute.side_effect = [[req], []]
repos.repo_done_hook(100)
self.assertEqual(len(self.RepoQueueQuery.call_args_list), 2)
# should not update
self.UpdateProcessor.assert_called_once()
update = self.updates[0]
self.assertEqual(update.table, 'repo_queue')
self.assertEqual(update.values, {'ids': ['REQ_ID']})
self.assertEqual(update.data, {'repo_id': 55, 'active': False})
# no exception
self.Savepoint.return_value.rollback.assert_not_called()
def test_exception(self):
self.RepoQuery.side_effect = MyError()
# should return without error
repos.repo_done_hook(100)
# should not query further or update
self.RepoQueueQuery.assert_not_called()
self.UpdateProcessor.assert_not_called()
# rollback should be called
self.Savepoint.return_value.rollback.assert_called_once()
class TestSymlink(BaseTest):
def setUp(self):
super(TestSymlink, self).setUp()
self.tempdir = tempfile.mkdtemp()
self.pathinfo = koji.PathInfo(self.tempdir)
mock.patch('koji.pathinfo', new=self.pathinfo).start()
self.symlink = mock.patch('os.symlink').start()
self.lexists = mock.patch('os.path.lexists').start()
self.unlink = mock.patch('os.unlink').start()
self.lexists.return_value = False
def tearDown(self):
super(TestSymlink, self).tearDown()
shutil.rmtree(self.tempdir)
def test_skip_custom(self):
repo = {'dist': False, 'custom_opts': {'src': True}}
result = repos.symlink_if_latest(repo)
self.assertFalse(result)
self.RepoQuery.assert_not_called()
self.symlink.assert_not_called()
def test_skip_old(self):
repo = {'dist': False, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010}
self.RepoQuery.return_value.execute.return_value = ['REPO']
result = repos.symlink_if_latest(repo)
self.assertFalse(result)
self.symlink.assert_not_called()
# and same for a dist repo
repo['dist'] = True
result = repos.symlink_if_latest(repo)
self.assertFalse(result)
self.symlink.assert_not_called()
def test_symlink(self):
repo = {'id': 99, 'dist': False, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010,
'tag_name': 'MYTAG'}
self.RepoQuery.return_value.execute.return_value = []
self.lexists.return_value = False
result = repos.symlink_if_latest(repo)
self.assertTrue(result)
expect = self.tempdir + '/repos/MYTAG/latest'
self.symlink.assert_called_with('99', expect)
self.unlink.assert_not_called()
def test_symlink_dist(self):
repo = {'id': 99, 'dist': True, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010,
'tag_name': 'MYTAG'}
self.RepoQuery.return_value.execute.return_value = []
result = repos.symlink_if_latest(repo)
self.assertTrue(result)
expect = self.tempdir + '/repos-dist/MYTAG/latest'
self.symlink.assert_called_with('99', expect)
def test_symlink_replace(self):
repo = {'id': 99, 'dist': False, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010,
'tag_name': 'MYTAG'}
self.RepoQuery.return_value.execute.return_value = []
self.lexists.return_value = True
result = repos.symlink_if_latest(repo)
self.assertTrue(result)
expect = self.tempdir + '/repos/MYTAG/latest'
self.unlink.assert_called_once_with(expect)
self.symlink.assert_called_with('99', expect)
def test_symlink_fail(self):
repo = {'id': 99, 'dist': False, 'custom_opts': {}, 'tag_id': 'TAGID', 'create_event': 101010,
'tag_name': 'MYTAG'}
self.RepoQuery.return_value.execute.return_value = []
self.symlink.side_effect = OSError('failed')
result = repos.symlink_if_latest(repo)
self.assertFalse(result)
self.symlink.assert_called_once()
class TestQueueTask(BaseTest):
def test_queue_task(self):
req = {'id': 100, 'tag_id': 42, 'min_event': None, 'at_event': None, 'opts': None}
req['opts'] = {}
repos.repo_queue_task(req)
self.make_task.assert_called_once()
def test_queue_task_event(self):
req = {'id': 100, 'tag_id': 42, 'min_event': None, 'at_event': 101010, 'opts': None}
req['opts'] = {}
repos.repo_queue_task(req)
self.make_task.assert_called_once()
method, args = self.make_task.call_args.args
taskopts = self.make_task.call_args.kwargs
self.assertEqual(method, 'newRepo')
self.assertEqual(taskopts['channel'], 'createrepo')
params = koji.tasks.parse_task_params('newRepo', args)
self.assertEqual(params['event'], 101010)
class TestUpdateEndEvents(BaseTest):
def setUp(self):
super(TestUpdateEndEvents, self).setUp()
self.BulkUpdateProcessor = mock.patch('kojihub.repos.BulkUpdateProcessor').start()
self.tag_first_change_event = mock.patch('kojihub.kojihub.tag_first_change_event').start()
self.tag_last_change_event = mock.patch('kojihub.kojihub.tag_last_change_event').start()
def test_no_update(self):
repo = {'id': 1, 'tag_id': 99, 'create_event': 1000}
self.RepoQuery.return_value.execute.return_value = [repo]
self.tag_first_change_event.return_value = None
self.tag_last_change_event.return_value = 1000
repos.update_end_events()
self.BulkUpdateProcessor.assert_not_called()
def test_update(self):
repo = {'id': 1, 'tag_id': 99, 'create_event': 1000}
self.RepoQuery.return_value.execute.return_value = [repo]
self.tag_first_change_event.return_value = 1001
repos.update_end_events()
self.tag_last_change_event.assert_not_called()
expect = [{'id': 1, 'end_event': 1001}]
self.BulkUpdateProcessor.assert_called_once()
updates = self.BulkUpdateProcessor.call_args.kwargs['data']
self.assertEqual(updates, expect)
def test_event_cache(self):
# two current and one obsolete. all same tag
repolist = [
{'id': 1, 'tag_id': 99, 'create_event': 1000},
# first is current, populates tag_last cache
{'id': 2, 'tag_id': 99, 'create_event': 1000},
{'id': 3, 'tag_id': 99, 'create_event': 1000},
# 2 and 3 avoid checking tag due to cache
{'id': 4, 'tag_id': 99, 'create_event': 999},
# 4 is obsolete
]
self.tag_last_change_event.return_value = 1000
self.RepoQuery.return_value.execute.return_value = repolist
self.tag_first_change_event.side_effect = [None, 1000]
# the latter should only be called twice due to cache
repos.update_end_events()
self.tag_last_change_event.assert_called_once_with(99)
expect_calls = [
mock.call(99, after=1000),
mock.call(99, after=999),
]
self.assertEqual(self.tag_first_change_event.mock_calls, expect_calls)
expect_updates = [{'id': 4, 'end_event': 1000}]
self.BulkUpdateProcessor.assert_called_once()
updates = self.BulkUpdateProcessor.call_args.kwargs['data']
self.assertEqual(updates, expect_updates)
class TestExternalRepo(BaseTest):
def setUp(self):
super(TestExternalRepo, self).setUp()
self.get_external_repo_id = mock.patch('kojihub.kojihub.get_external_repo_id').start()
def test_get_external(self):
self.get_external_repo_id.return_value = 42
self.query_singleValue.return_value = 'DATA'
data = repos.get_external_repo_data('my_ext_repo')
self.assertEqual(data, 'DATA')
self.QueryProcessor.assert_called_once()
query = self.queries[0]
self.assertEqual(query.tables, ['external_repo_data'])
self.assertEqual(query.values, {'id': 42})
def test_set_external(self):
self.get_external_repo_id.return_value = 42
self.query_singleValue.return_value = 'DATA'
data = {'max_ts': 1717171717}
repos.set_external_repo_data('my_ext_repo', data)
self.UpdateProcessor.assert_called_once()
self.InsertProcessor.assert_called_once()
insert = self.inserts[0]
self.assertEqual(insert.data['external_repo_id'], 42)
self.assertEqual(json.loads(insert.data['data']), data)
class TestAutoRequests(BaseTest):
def setUp(self):
super(TestAutoRequests, self).setUp()
self.request_repo = mock.patch('kojihub.repos.request_repo').start()
self.tag_last_change_event = mock.patch('kojihub.kojihub.tag_last_change_event').start()
self.time = mock.patch('time.time').start()
def test_auto_requests(self):
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
]
self.query_execute.return_value = autokeys
self.getLastEvent.return_value = {'id': 1050}
self.tag_last_change_event.return_value = 1000
self.request_repo.return_value = {'repo': None, 'request': 'REQ', 'duplicate': False}
repos.do_auto_requests()
self.request_repo.called_once_with(99, min_event=1000, priority=5)
def test_no_tags(self):
autokeys = []
self.query_execute.return_value = autokeys
self.request_repo.assert_not_called()
self.tag_last_change_event.assert_not_called()
def test_bad_row(self):
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
{'tag_id': 98, 'key': 'repo.auto', 'value': 'not+valid+json'},
{'tag_id': 98, 'key': 'repo.lag', 'value': '"valid json, but not valid int"'},
]
# the bad rows should be ignored without blocking other auto requests
self.query_execute.return_value = autokeys
self.getLastEvent.return_value = {'id': 1050}
self.tag_last_change_event.return_value = 1000
self.request_repo.return_value = {'repo': None, 'request': 'REQ', 'duplicate': False}
repos.do_auto_requests()
self.request_repo.called_once_with(99, min_event=1000, priority=5)
def test_blocked_row(self):
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
{'tag_id': 98, 'key': 'repo.auto', 'value': None},
]
# the blocked row should be ignored without blocking other auto requests
self.query_execute.return_value = autokeys
self.getLastEvent.return_value = {'id': 1050}
self.tag_last_change_event.return_value = 1000
self.request_repo.return_value = {'repo': None, 'request': 'REQ', 'duplicate': False}
repos.do_auto_requests()
self.request_repo.called_once_with(99, min_event=1000, priority=5)
def test_auto_lag(self):
# use a trivial window to simplify the lag calculation
self.context.opts['RepoLagWindow'] = 1
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
{'tag_id': 99, 'key': 'repo.lag', 'value': '0'},
]
now = 1717171717
self.time.return_value = now
self.query_execute.return_value = autokeys
self.getLastEvent.return_value = {'id': 1050}
self.tag_last_change_event.return_value = 1000
self.request_repo.return_value = {'repo': None, 'request': 'REQ', 'duplicate': True}
repos.do_auto_requests()
self.request_repo.called_once_with(99, min_event=1000, priority=5)
# with zero lag, getLastEvent should be called with current time
self.getLastEvent.assert_called_once_with(before=now)
def test_auto_lag_window(self):
self.context.opts['RepoLagWindow'] = 600
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
{'tag_id': 99, 'key': 'repo.lag', 'value': '0'},
]
now = 1717171717
self.time.return_value = now
self.query_execute.return_value = autokeys
self.getLastEvent.return_value = {'id': 1050}
self.tag_last_change_event.return_value = 1000
self.request_repo.return_value = {'repo': None, 'request': 'REQ', 'duplicate': False}
repos.do_auto_requests()
self.request_repo.called_once_with(99, min_event=1000, priority=5)
# with zero lag, getLastEvent should be called with current time
self.getLastEvent.assert_called_once()
before = self.getLastEvent.call_args.kwargs['before']
# should be earlier than current time, but within lag window
if before > now or before < now - 600:
raise Exception('Invalid lag calculation')
def test_no_last_event(self):
# corner case that should not happen
autokeys = [
{'tag_id': 99, 'key': 'repo.auto', 'value': 'true'},
]
self.query_execute.return_value = autokeys
self.tag_last_change_event.return_value = None
repos.do_auto_requests()
self.request_repo.assert_not_called()
self.tag_last_change_event.assert_called_once()
class TestGetRepo(BaseTest):
def test_get_repo_simple(self):
self.RepoQuery.return_value.executeOne.return_value = 'REPO'
repo = repos.get_repo('TAGID')
self.assertEqual(repo, 'REPO')
self.RepoQuery.assert_called_once()
def test_get_repo_at_event(self):
repos.get_repo('TAGID', at_event=101010)
self.RepoQuery.assert_called_once()
clauses, fields, qopts = self.RepoQuery.call_args.args
self.assertIn(['create_event', '=', 101010], clauses)
def test_get_repo_min_event(self):
repos.get_repo('TAGID', min_event=101010)
self.RepoQuery.assert_called_once()
clauses, fields, qopts = self.RepoQuery.call_args.args
self.assertIn(['create_event', '>=', 101010], clauses)
class TestGetRepoOpts(BaseTest):
def test_basic(self):
taginfo = {'extra': {}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_override(self):
taginfo = {'extra': {}}
override = {'src': True}
opts, custom = repos.get_repo_opts(taginfo, override)
expect = {'src': True, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, override)
def test_override_redundant(self):
taginfo = {'extra': {}}
override = {'src': False} # default setting, shouldn't be reported as custom
opts, custom = repos.get_repo_opts(taginfo, override)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_pattern_debug(self):
self.context.opts['DebuginfoTags'] = 'TAG*'
taginfo = {'name': 'TAG123', 'extra': {}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': True, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_pattern_source(self):
self.context.opts['SourceTags'] = 'TAG*'
taginfo = {'name': 'TAG123', 'extra': {}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': True, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_pattern_separate_src(self):
self.context.opts['SeparateSourceTags'] = 'TAG*'
taginfo = {'name': 'TAG123', 'extra': {}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': True, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_pattern_nomatch(self):
self.context.opts['DebuginfoTags'] = 'FOO*'
self.context.opts['SourceTags'] = 'FOO*'
self.context.opts['SeparateSourceTags'] = 'FOO*'
# this one shouldn't match
taginfo = {'name': 'bar123', 'extra': {}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_tag_config(self):
taginfo = {'extra': {'repo.opts': {'debuginfo': True}}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': True, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
# old debuginfo should still work
taginfo = {'extra': {'with_debuginfo': True}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': True, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
# but repo.opts should win
taginfo = {'extra': {'repo.opts': {}, 'with_debuginfo': True}}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_old_maven(self):
self.context.opts['EnableMaven'] = True
taginfo = {'extra': {}, 'maven_support': True}
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': True}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_maven_disabled(self):
self.context.opts['EnableMaven'] = False
taginfo = {'extra': {}, 'maven_support': True}
taginfo = {'extra': {'repo.opts': {'maven': True}, 'maven_support': True}}
# should report maven=false regardless of other settings
opts, custom = repos.get_repo_opts(taginfo)
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': False}
self.assertEqual(opts, expect)
self.assertEqual(custom, {})
def test_maven_disabled_override(self):
self.context.opts['EnableMaven'] = False
taginfo = {'extra': {}}
override = {'maven': True}
opts, custom = repos.get_repo_opts(taginfo, override)
# should report the override anyway
expect = {'src': False, 'debuginfo': False, 'separate_src': False, 'maven': True}
self.assertEqual(opts, expect)
self.assertEqual(custom, override)
class TestConvertRepoOpts(BaseTest):
def test_basic(self):
value = {'debuginfo': False, 'src': True}
# correctly formatted opts should not change
opts = repos.convert_repo_opts(value)
self.assertEqual(opts, value)
def test_wrong_type(self):
opts = repos.convert_repo_opts('STRING')
self.assertEqual(opts, {})
with self.assertRaises(koji.ParameterError):
repos.convert_repo_opts('STRING', strict=True)
def test_bad_key(self):
bad = {'XYZ': True, 'src': True}
opts = repos.convert_repo_opts(bad)
self.assertEqual(opts, {'src':True})
with self.assertRaises(koji.ParameterError):
repos.convert_repo_opts(bad, strict=True)
def test_null_value(self):
value = {'debuginfo': None, 'src': True}
opts = repos.convert_repo_opts(value)
self.assertEqual(opts, {'src':True})
class TestRequestRepo(BaseTest):
def setUp(self):
super(TestRequestRepo, self).setUp()
self.get_repo = mock.patch('kojihub.repos.get_repo').start()
self.set_request_priority = mock.patch('kojihub.repos.set_request_priority').start()
def test_basic_request(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.getLastEvent.return_value = {'id': 101010}
self.tag_last_change_event.return_value = 100000
repos.request_repo('TAGID')
def test_request_last(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.getLastEvent.return_value = {'id': 101010}
last = 100001
self.tag_last_change_event.return_value = last
self.get_repo.return_value = None
self.RepoQueueQuery.return_value.execute.return_value = []
repos.request_repo('TAGID', min_event="last")
# check all the calls made with the value
self.get_repo.assert_called_once()
ev = self.get_repo.call_args.kwargs['min_event']
self.assertEqual(ev, last)
clauses = self.RepoQueueQuery.call_args_list[0].args[0]
self.assertIn(['min_event', '>=', last], clauses)
self.InsertProcessor.assert_called_once()
data = self.InsertProcessor.call_args.kwargs['data']
self.assertEqual(data['min_event'], last)
def test_request_priority(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
ev = 100001
self.get_repo.return_value = None
self.RepoQueueQuery.return_value.execute.return_value = []
repos.request_repo('TAGID', min_event=ev, priority=5)
# check all the calls made with the value
self.InsertProcessor.assert_called_once()
data = self.InsertProcessor.call_args.kwargs['data']
self.assertEqual(data['min_event'], ev)
self.assertEqual(data['priority'], 25) # default + 5
def test_request_priority_lower_than_existing(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
ev = 100001
self.get_repo.return_value = None
oldreq = {'priority': 20, 'id': 424242} # default
self.RepoQueueQuery.return_value.execute.return_value = [oldreq]
ret = repos.request_repo('TAGID', min_event=ev, priority=5)
# we should return the existing entry
# we should not update the priority since it is higher
self.assertEqual(ret['request']['id'], 424242)
self.assertEqual(ret['request']['priority'], 20)
self.assertEqual(ret['duplicate'], True)
self.InsertProcessor.assert_not_called()
self.set_request_priority.assert_not_called()
def test_request_priority_higher_not_allowed(self):
self.context.session.hasPerm.return_value = False
with self.assertRaises(koji.ActionNotAllowed):
ret = repos.request_repo('TAGID', min_event=101010, priority=-5)
self.get_repo.assert_not_called()
self.InsertProcessor.assert_not_called()
self.set_request_priority.assert_not_called()
def test_request_priority_lower_than_existing(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
ev = 100001
self.get_repo.return_value = None
oldreq = {'priority': 20, 'id': 424242} # default
self.RepoQueueQuery.return_value.execute.return_value = [oldreq]
ret = repos.request_repo('TAGID', min_event=ev, priority=-5)
# we should return the existing entry
# we should update the priority
self.assertEqual(ret['request']['id'], 424242)
self.assertEqual(ret['request']['priority'], 15)
self.assertEqual(ret['duplicate'], True)
self.InsertProcessor.assert_not_called()
self.set_request_priority.assert_called_once_with(424242, 15)
def test_maven_disabled(self):
self.context.opts['EnableMaven'] = False
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
with self.assertRaises(koji.GenericError):
repos.request_repo('TAGID', opts={'maven': True})
self.InsertProcessor.assert_not_called()
self.get_repo.assert_not_called()
def test_event_conflict(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
with self.assertRaises(koji.ParameterError):
repos.request_repo('TAGID', min_event=100, at_event=101)
self.InsertProcessor.assert_not_called()
self.get_repo.assert_not_called()
def test_bad_at_event(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.getEvent.return_value = None
with self.assertRaises(koji.ParameterError):
repos.request_repo('TAGID', at_event=101)
self.InsertProcessor.assert_not_called()
self.get_repo.assert_not_called()
self.getEvent.assert_called_once_with(101, strict=False)
def test_bad_min_event(self):
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.getEvent.return_value = None
with self.assertRaises(koji.ParameterError):
repos.request_repo('TAGID', min_event=101)
self.InsertProcessor.assert_not_called()
self.get_repo.assert_not_called()
self.getEvent.assert_called_once_with(101, strict=False)
def test_request_existing_repo(self):
# if a matching repo exists, we should return it
self.get_repo.return_value = 'MY-REPO'
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
result = repos.request_repo('TAGID', min_event=101010)
self.assertEqual(result['repo'], 'MY-REPO')
self.get_repo.assert_called_with(100, min_event=101010, at_event=None, opts={})
self.RepoQueueQuery.assert_not_called()
self.nextval.assert_not_called()
self.assertEqual(self.inserts, [])
def test_request_existing_req(self):
# if a matching request exists, we should return it
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.get_repo.return_value = None
req = {'repo_id': None, 'priority': 20, 'sentinel': 'hello'}
self.RepoQueueQuery.return_value.execute.return_value = [req]
result = repos.request_repo('TAG', min_event=101010)
self.assertEqual(result['request'], req)
self.get_repo.assert_called_with(100, min_event=101010, at_event=None, opts={})
self.RepoQueueQuery.assert_called_once()
expect = [['tag_id', '=', 100],
['active', 'IS', True],
['opts', '=', '{}'],
['min_event', '>=', 101010]]
clauses = self.RepoQueueQuery.mock_calls[0][1][0]
self.assertEqual(clauses, expect)
self.nextval.assert_not_called()
self.assertEqual(self.inserts, [])
def test_request_new_req(self):
# if a matching request exists, we should return it
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.get_repo.return_value = None
self.RepoQueueQuery.return_value.execute.return_value = []
self.RepoQueueQuery.return_value.executeOne.return_value = 'NEW-REQ'
self.nextval.return_value = 'NEW-ID'
self.context.session.user_id = 'USER'
result = repos.request_repo('TAG', min_event=101010)
self.get_repo.assert_called_with(100, min_event=101010, at_event=None, opts={})
self.assertEqual(len(self.inserts), 1)
expect = {
'id': 'NEW-ID',
'owner': 'USER',
'priority': 20,
'tag_id': 100,
'at_event': None,
'min_event': 101010,
'opts': '{}',
}
self.assertEqual(self.inserts[0].data, expect)
self.assertEqual(self.RepoQueueQuery.call_count, 2)
# clauses for final query
clauses = self.RepoQueueQuery.call_args[1]['clauses']
self.assertEqual(clauses, [['id', '=', 'NEW-ID']])
self.assertEqual(result['request'], 'NEW-REQ')
def test_request_at_event(self):
# similate an at_event request that finds an existing matching request to return
self.get_tag.return_value = {'id': 100, 'name': 'TAG', 'extra': {}}
self.get_repo.return_value = None
req = {'repo_id': None, 'priority': 20, 'sentinel': 'hello'}
self.RepoQueueQuery.return_value.execute.return_value = [req]
result = repos.request_repo('TAG', at_event=101010)
self.assertEqual(result['request'], req)
self.get_repo.assert_called_with(100, min_event=None, at_event=101010, opts={})
self.RepoQueueQuery.assert_called_once()
expect = [['tag_id', '=', 100],
['active', 'IS', True],
['opts', '=', '{}'],
['at_event', '=', 101010]]
clauses = self.RepoQueueQuery.mock_calls[0][1][0]
self.assertEqual(clauses, expect)
self.nextval.assert_not_called()
self.assertEqual(self.inserts, [])
class TestDefaultMinEvent(BaseTest):
def setUp(self):
super(TestDefaultMinEvent, self).setUp()
self.time = mock.patch('time.time').start()
def test_simple_lag(self):
now = 1717171717
self.time.return_value = now
self.context.opts['RepoLag'] = 3600
self.context.opts['RepoLagWindow'] = 1
taginfo = {'id': 55, 'name': 'MYTAG', 'extra': {}} # no lag override
self.tag_last_change_event.return_value = 10000
self.getLastEvent.return_value = {'id': 9999}
ev = repos.default_min_event(taginfo)
# we should report the ts from the last event, minus lag
self.assertEqual(ev, 9999)
self.getLastEvent.assert_called_once()
base_ts = self.getLastEvent.call_args.kwargs['before']
self.assertEqual(base_ts, now - 3600)
def test_tag_older(self):
now = 1717171717
self.time.return_value = now
self.context.opts['RepoLag'] = 3600
self.context.opts['RepoLagWindow'] = 1
taginfo = {'id': 55, 'name': 'MYTAG', 'extra': {}} # no lag override
self.tag_last_change_event.return_value = 9900
self.getLastEvent.return_value = {'id': 9999}
ev = repos.default_min_event(taginfo)
# we should report the ts for the tag, since it is older
self.assertEqual(ev, 9900)
self.getLastEvent.assert_called_once()
base_ts = self.getLastEvent.call_args.kwargs['before']
self.assertEqual(base_ts, now - 3600)
def test_window(self):
now = 1717171717
self.time.return_value = now
self.context.opts['RepoLag'] = 3600
self.context.opts['RepoLagWindow'] = 300
taginfo = {'id': 55, 'name': 'MYTAG', 'extra': {}} # no lag override
self.tag_last_change_event.return_value = 9900
self.getLastEvent.return_value = {'id': 9999}
ev = repos.default_min_event(taginfo)
# we should report the ts for the tag, since it is older
self.assertEqual(ev, 9900)
self.getLastEvent.assert_called_once()
base_ts = self.getLastEvent.call_args.kwargs['before']
# should be earlier than target time, but within lag window
lag_ts = now - 3600
if base_ts > lag_ts or base_ts < lag_ts - 600:
raise Exception('Invalid lag window calculation')
def test_lag_override(self):
now = 1717171717
self.time.return_value = now
self.context.opts['RepoLag'] = 3600
self.context.opts['RepoLagWindow'] = 1
taginfo = {'id': 55, 'name': 'MYTAG', 'extra': {'repo.lag': 1800}}
self.tag_last_change_event.return_value = 10000
self.getLastEvent.return_value = {'id': 9999}
ev = repos.default_min_event(taginfo)
# we should report the ts from the last event, minus lag
self.assertEqual(ev, 9999)
self.getLastEvent.assert_called_once()
base_ts = self.getLastEvent.call_args.kwargs['before']
self.assertEqual(base_ts, now - 1800)
def test_lag_override_invalid(self):
now = 1717171717
self.time.return_value = now
self.context.opts['RepoLag'] = 3600
self.context.opts['RepoLagWindow'] = 1
taginfo = {'id': 55, 'name': 'MYTAG', 'extra': {'repo.lag': 'not an int'}}
self.tag_last_change_event.return_value = 10000
self.getLastEvent.return_value = {'id': 9999}
ev = repos.default_min_event(taginfo)
# we should report the ts from the last event, minus lag
self.assertEqual(ev, 9999)
self.getLastEvent.assert_called_once()
base_ts = self.getLastEvent.call_args.kwargs['before']
self.assertEqual(base_ts, now - 3600)
class TestCheckRequest(BaseTest):
def setUp(self):
super(TestCheckRequest, self).setUp()
self.repo_info = mock.patch('kojihub.kojihub.repo_info').start()
self.Task = mock.patch('kojihub.kojihub.Task').start()
def test_have_repo(self):
req = {'repo_id': 'REPOID', 'task_id': 'TASKID'}
self.RepoQueueQuery.return_value.executeOne.return_value = req
self.repo_info.return_value = 'REPO'
ret = repos.check_repo_request(99)
self.RepoQueueQuery.assert_called_once()
self.repo_info.assert_called_once_with('REPOID')
expect = {'request': req, 'repo': 'REPO'}
self.assertEqual(ret, expect)
def test_have_task(self):
req = {'repo_id': None, 'task_id': 'TASKID'}
self.RepoQueueQuery.return_value.executeOne.return_value = req
self.Task.return_value.getInfo.return_value = 'TASK'
ret = repos.check_repo_request(99)
self.RepoQueueQuery.assert_called_once()
self.repo_info.assert_not_called()
self.Task.assert_called_once_with('TASKID')
expect = {'repo': None, 'request': req, 'task': 'TASK'}
self.assertEqual(ret, expect)
def test_no_match(self):
self.RepoQueueQuery.return_value.executeOne.return_value = None
with self.assertRaises(koji.GenericError):
repos.check_repo_request(99)
self.RepoQueueQuery.assert_called_once()
self.repo_info.assert_not_called()
self.Task.assert_not_called()
class TestSetPriority(BaseTest):
def test_set_request_priority(self):
repos.set_request_priority(99, 15)
self.UpdateProcessor.assert_called_once()
update = self.updates[0]
self.assertEqual(update.data, {'priority': 15})
self.assertEqual(update.values, {'id': 99})
class TestExports(BaseTest):
def setUp(self):
super(TestExports, self).setUp()
self.set_request_priority = mock.patch('kojihub.repos.set_request_priority').start()
self.RepoQuery = mock.patch('kojihub.repos.RepoQuery').start()
self.set_external_repo_data = mock.patch('kojihub.repos.set_external_repo_data').start()
self.do_auto_requests = mock.patch('kojihub.repos.do_auto_requests').start()
self.check_repo_queue = mock.patch('kojihub.repos.check_repo_queue').start()
self.RepoQueueQuery = mock.patch('kojihub.repos.RepoQueueQuery').start()
self.update_end_events = mock.patch('kojihub.repos.update_end_events').start()
self.repo_references = mock.patch('kojihub.kojihub.repo_references').start()
self.repo_set_state = mock.patch('kojihub.kojihub.repo_set_state').start()
self.exports = repos.RepoExports()
self.assertPerm = mock.MagicMock()
self.context.session.assertPerm = self.assertPerm
def test_no_perm(self):
self.assertPerm.side_effect = koji.ActionNotAllowed('...')
self.exports.references('REPO')
self.exports.query('CLAUSES')
self.exports.queryQueue('CLAUSES')
def test_require_perm(self):
self.assertPerm.side_effect = koji.ActionNotAllowed('...')
with self.assertRaises(koji.ActionNotAllowed):
self.exports.setRequestPriority(99, 1)
self.set_request_priority.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('admin',))
with self.assertRaises(koji.ActionNotAllowed):
self.exports.setState(99, 1)
self.repo_set_state.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('repo',))
with self.assertRaises(koji.ActionNotAllowed):
self.exports.setExternalRepoData(99, 1)
self.set_external_repo_data.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('repo',))
with self.assertRaises(koji.ActionNotAllowed):
self.exports.autoRequests()
self.do_auto_requests.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('repo',))
with self.assertRaises(koji.ActionNotAllowed):
self.exports.checkQueue()
self.check_repo_queue.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('repo',))
with self.assertRaises(koji.ActionNotAllowed):
self.exports.updateEndEvents()
self.update_end_events.assert_not_called()
self.assertEqual(self.assertPerm.call_args.args, ('repo',))
def test_with_perm(self):
# assertPerm does not raise
self.exports.setRequestPriority(99, 1)
self.exports.setState(99, 1)
self.exports.setExternalRepoData(99, 1)
self.exports.autoRequests()
self.exports.checkQueue()
self.exports.updateEndEvents()
# the end