|
43 | 43 | import atr.storage as storage |
44 | 44 | import atr.storage.outcome as outcome |
45 | 45 | import atr.storage.types as types |
| 46 | +import atr.tasks as tasks |
46 | 47 | import atr.user as user |
47 | 48 | import atr.util as util |
48 | 49 |
|
@@ -226,6 +227,7 @@ async def delete_key(self, fingerprint: str) -> outcome.Outcome[sql.PublicSignin |
226 | 227 | ) |
227 | 228 | for committee_key in sorted(affected_committee_keys): |
228 | 229 | await self._sync_committee_keys_file(committee_key) |
| 230 | + await self._recheck_committee_drafts(*affected_committee_keys) |
229 | 231 | return outcome.Result(key) |
230 | 232 | except Exception as e: |
231 | 233 | return outcome.Error(e) |
@@ -310,6 +312,29 @@ async def _keys_file_text(self, committee: sql.Committee) -> str: |
310 | 312 | def _committee_keys_path(self, committee: sql.Committee) -> safe.StatePath: |
311 | 313 | return paths.committee_downloads_dir(committee) / "KEYS" |
312 | 314 |
|
| 315 | + async def _recheck_committee_drafts(self, *committee_keys: str) -> None: |
| 316 | + # A KEYS change only invalidates signature checks, so we limit the re-queue to .asc files |
| 317 | + affected = {committee_key for committee_key in committee_keys if committee_key} |
| 318 | + if not affected: |
| 319 | + return |
| 320 | + drafts = await self.__data.release( |
| 321 | + phase=sql.ReleasePhase.RELEASE_CANDIDATE_DRAFT, |
| 322 | + _committee=True, |
| 323 | + ).all() |
| 324 | + for draft in drafts: |
| 325 | + committee = draft.project.committee |
| 326 | + if (committee is None) or (committee.key not in affected): |
| 327 | + continue |
| 328 | + if not draft.latest_revision_number: |
| 329 | + continue |
| 330 | + await tasks.draft_checks( |
| 331 | + self.__asf_uid, |
| 332 | + draft.safe_project_key, |
| 333 | + draft.safe_version_key, |
| 334 | + draft.safe_latest_revision_number, |
| 335 | + suffix_filter=[".asc"], |
| 336 | + ) |
| 337 | + |
313 | 338 | async def _sync_committee_keys_file(self, committee_key: str) -> str | None: |
314 | 339 | committee = await self.__data.committee(key=committee_key, _public_signing_keys=True).demand( |
315 | 340 | storage.AccessError(f"Committee not found: {committee_key}", status=404) |
@@ -439,6 +464,8 @@ async def update_committee_associations( |
439 | 464 | for committee_key in sorted(affected): |
440 | 465 | await self._sync_committee_keys_file(committee_key) |
441 | 466 |
|
| 467 | + await self._recheck_committee_drafts(*affected) |
| 468 | + |
442 | 469 | return affected |
443 | 470 |
|
444 | 471 | def __block_model(self, key_block: str, ldap_data: cache.EmailUidLookup) -> types.Key: |
@@ -640,6 +667,7 @@ async def associate_fingerprint(self, fingerprint: str) -> outcome.Outcome[types |
640 | 667 | fingerprint=fingerprint, |
641 | 668 | committee_key=self.__committee_key, |
642 | 669 | ) |
| 670 | + await self._recheck_committee_drafts(self.__committee_key) |
643 | 671 | try: |
644 | 672 | autogenerated_outcome = await self.autogenerate_keys_file() |
645 | 673 | except Exception as e: |
@@ -854,6 +882,8 @@ def replace_with_linked(key: types.Key) -> types.Key: |
854 | 882 | inserted_fingerprints=sorted(key_inserts), |
855 | 883 | linked_fingerprints=sorted(link_inserts), |
856 | 884 | ) |
| 885 | + if link_inserts: |
| 886 | + await self._recheck_committee_drafts(self.__committee_key) |
857 | 887 | return outcomes |
858 | 888 |
|
859 | 889 | async def __ensure( |
@@ -974,6 +1004,7 @@ async def delete_committee_keys(self) -> tuple[int, int]: |
974 | 1004 | ) |
975 | 1005 | raise |
976 | 1006 |
|
| 1007 | + await self._recheck_committee_drafts(self.__committee_key) |
977 | 1008 | return (num_unlinked, num_deleted) |
978 | 1009 |
|
979 | 1010 |
|
|
0 commit comments