diff --git a/CHANGELOG.md b/CHANGELOG.md index c5941b9..02bcc4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ -# CHANGELOG +# Changelog -## 0.1.0 +All notable changes to this project will be documented in this file. -- Initial tagged release of the action +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.2.0] - 2023-07-20 + +### Added + +- Added increased logging during initial information gathering +- Added better handling of encountering a rate limit while the action is executing + +### Changed + +- Bump `httpx` from 0.24.0 to 0.24.1 +- Changelog format updated to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) +- HTTP connection to the API now uses HTTP/2 if possible +- Updated `pipenv` from 2023.4.20 to 2023.6.26 + +## [0.1.0] - 2023-06-30 + +- Initial versioned release of the actions diff --git a/Pipfile.lock b/Pipfile.lock index a9e3392..b29ce0d 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,11 +18,11 @@ "default": { "anyio": { "hashes": [ - "sha256:25ea0d673ae30af41a0c442f81cf3b38c7e79fdc7b60335a4c14e05eb0947421", - "sha256:fbbe32bd270d2a2ef3ed1c5d45041250284e31fc0a4df4a5a6071842051a51e3" + "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780", + "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5" ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.6.2" + "markers": "python_version >= '3.7'", + "version": "==3.7.1" }, "brotli": { "hashes": [ @@ -113,11 +113,19 @@ }, "certifi": { "hashes": [ - "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", - "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" + "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7", + "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716" ], - "markers": "python_version >= '3.6'", - "version": "==2022.12.7" + "markers": "python_full_version >= '3.6.0'", + "version": "==2023.5.7" + }, + "exceptiongroup": { + "hashes": [ + "sha256:12c3e887d6485d16943a309616de20ae5582633e0a2eda17f4e10fd61c1e8af5", + "sha256:e346e69d186172ca7cf029c8c1d16235aa0e04035e5750b4b95039e65204328f" + ], + "markers": "python_version < '3.11'", + "version": "==1.1.2" }, "github-action-utils": { "hashes": [ @@ -152,11 +160,11 @@ }, "httpcore": { "hashes": [ - "sha256:0fdfea45e94f0c9fd96eab9286077f9ff788dd186635ae61b312693e4d943599", - "sha256:cc045a3241afbf60ce056202301b4d8b6af08845e3294055eb26b09913ef903c" + "sha256:a6f30213335e34c1ade7be6ec7c47f19f50c56db36abef1a9dfa3815b1cb3888", + "sha256:c2789b767ddddfa2a5782e3199b2b7f6894540b17b16ec26b2c4d8e103510b87" ], "markers": "python_version >= '3.7'", - "version": "==0.17.0" + "version": "==0.17.3" }, "httpx": { "extras": [ @@ -164,11 +172,11 @@ "http2" ], "hashes": [ - "sha256:447556b50c1921c351ea54b4fe79d91b724ed2b027462ab9a329465d147d5a4e", - "sha256:507d676fc3e26110d41df7d35ebd8b3b8585052450f4097401c9be59d928c63e" + "sha256:06781eb9ac53cde990577af654bd990a4949de37a28bdb4a230d434f3a30b9bd", + "sha256:5853a43053df830c20f8110c5e69fe44d035d850b2dfe795e196f00fdb774bdd" ], "index": "pypi", - "version": "==0.24.0" + "version": "==0.24.1" }, "hyperframe": { "hashes": [ @@ -198,34 +206,31 @@ "develop": { "black": { "hashes": [ - "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5", - "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915", - "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326", - "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940", - "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b", - "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30", - "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c", - "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c", - "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab", - "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27", - "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2", - "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961", - "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9", - "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb", - "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70", - "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331", - "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2", - "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266", - "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d", - "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6", - "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b", - "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925", - "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8", - "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4", - "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3" + "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3", + "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb", + "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087", + "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320", + "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6", + "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3", + "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc", + "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f", + "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587", + "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91", + "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a", + "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad", + "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926", + "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9", + "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be", + "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd", + "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96", + "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491", + "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2", + "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a", + "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f", + "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995" ], "index": "pypi", - "version": "==23.3.0" + "version": "==23.7.0" }, "cfgv": { "hashes": [ @@ -237,66 +242,66 @@ }, "click": { "hashes": [ - "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", - "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + "sha256:4be4b1af8d665c6d942909916d31a213a106800c47d0eeba73d34da3cbc11367", + "sha256:e576aa487d679441d7d30abb87e1b43d24fc53bffb8758443b1a9e1cee504548" ], "markers": "python_version >= '3.7'", - "version": "==8.1.3" + "version": "==8.1.5" }, "distlib": { "hashes": [ - "sha256:14bad2d9b04d3a36127ac97f30b12a19268f211063d8f8ee4f47108896e11b46", - "sha256:f35c4b692542ca110de7ef0bea44d73981caeb34ca0b9b6b2e6d7790dda8f80e" + "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057", + "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8" ], - "version": "==0.3.6" + "version": "==0.3.7" }, "filelock": { "hashes": [ - "sha256:ad98852315c2ab702aeb628412cbf7e95b7ce8c3bf9565670b4eaecf1db370a9", - "sha256:fc03ae43288c013d2ea83c8597001b1129db351aad9c57fe2409327916b8e718" + "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81", + "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec" ], "markers": "python_version >= '3.7'", - "version": "==3.12.0" + "version": "==3.12.2" }, "identify": { "hashes": [ - "sha256:17d9351c028a781456965e781ed2a435755cac655df1ebd930f7186b54399312", - "sha256:50b01b9d5f73c6b53e5fa2caf9f543d3e657a9d0bbdeb203ebb8d45960ba7433" + "sha256:0aac67d5b4812498056d28a9a512a483f5085cc28640b02b258a59dac34301d4", + "sha256:986dbfb38b1140e763e413e6feb44cd731faf72d1909543178aa79b0e258265d" ], "markers": "python_version >= '3.7'", - "version": "==2.5.23" + "version": "==2.5.24" }, "mypy": { "hashes": [ - "sha256:023fe9e618182ca6317ae89833ba422c411469156b690fde6a315ad10695a521", - "sha256:031fc69c9a7e12bcc5660b74122ed84b3f1c505e762cc4296884096c6d8ee140", - "sha256:2de7babe398cb7a85ac7f1fd5c42f396c215ab3eff731b4d761d68d0f6a80f48", - "sha256:2e93a8a553e0394b26c4ca683923b85a69f7ccdc0139e6acd1354cc884fe0128", - "sha256:390bc685ec209ada4e9d35068ac6988c60160b2b703072d2850457b62499e336", - "sha256:3a2d219775a120581a0ae8ca392b31f238d452729adbcb6892fa89688cb8306a", - "sha256:3efde4af6f2d3ccf58ae825495dbb8d74abd6d176ee686ce2ab19bd025273f41", - "sha256:4a99fe1768925e4a139aace8f3fb66db3576ee1c30b9c0f70f744ead7e329c9f", - "sha256:4b41412df69ec06ab141808d12e0bf2823717b1c363bd77b4c0820feaa37249e", - "sha256:4c8d8c6b80aa4a1689f2a179d31d86ae1367ea4a12855cc13aa3ba24bb36b2d8", - "sha256:4d19f1a239d59f10fdc31263d48b7937c585810288376671eaf75380b074f238", - "sha256:4e4a682b3f2489d218751981639cffc4e281d548f9d517addfd5a2917ac78119", - "sha256:695c45cea7e8abb6f088a34a6034b1d273122e5530aeebb9c09626cea6dca4cb", - "sha256:701189408b460a2ff42b984e6bd45c3f41f0ac9f5f58b8873bbedc511900086d", - "sha256:70894c5345bea98321a2fe84df35f43ee7bb0feec117a71420c60459fc3e1eed", - "sha256:8293a216e902ac12779eb7a08f2bc39ec6c878d7c6025aa59464e0c4c16f7eb9", - "sha256:8d26b513225ffd3eacece727f4387bdce6469192ef029ca9dd469940158bc89e", - "sha256:a197ad3a774f8e74f21e428f0de7f60ad26a8d23437b69638aac2764d1e06a6a", - "sha256:bea55fc25b96c53affab852ad94bf111a3083bc1d8b0c76a61dd101d8a388cf5", - "sha256:c9a084bce1061e55cdc0493a2ad890375af359c766b8ac311ac8120d3a472950", - "sha256:d0e9464a0af6715852267bf29c9553e4555b61f5904a4fc538547a4d67617937", - "sha256:d8e9187bfcd5ffedbe87403195e1fc340189a68463903c39e2b63307c9fa0394", - "sha256:eaeaa0888b7f3ccb7bcd40b50497ca30923dba14f385bde4af78fac713d6d6f6", - "sha256:f46af8d162f3d470d8ffc997aaf7a269996d205f9d746124a179d3abe05ac602", - "sha256:f70a40410d774ae23fcb4afbbeca652905a04de7948eaf0b1789c8d1426b72d1", - "sha256:fe91be1c51c90e2afe6827601ca14353bbf3953f343c2129fa1e247d55fd95ba" + "sha256:01fd2e9f85622d981fd9063bfaef1aed6e336eaacca00892cd2d82801ab7c042", + "sha256:0dde1d180cd84f0624c5dcaaa89c89775550a675aff96b5848de78fb11adabcd", + "sha256:141dedfdbfe8a04142881ff30ce6e6653c9685b354876b12e4fe6c78598b45e2", + "sha256:16f0db5b641ba159eff72cff08edc3875f2b62b2fa2bc24f68c1e7a4e8232d01", + "sha256:190b6bab0302cec4e9e6767d3eb66085aef2a1cc98fe04936d8a42ed2ba77bb7", + "sha256:2460a58faeea905aeb1b9b36f5065f2dc9a9c6e4c992a6499a2360c6c74ceca3", + "sha256:34a9239d5b3502c17f07fd7c0b2ae6b7dd7d7f6af35fbb5072c6208e76295816", + "sha256:43b592511672017f5b1a483527fd2684347fdffc041c9ef53428c8dc530f79a3", + "sha256:43d24f6437925ce50139a310a64b2ab048cb2d3694c84c71c3f2a1626d8101dc", + "sha256:45d32cec14e7b97af848bddd97d85ea4f0db4d5a149ed9676caa4eb2f7402bb4", + "sha256:470c969bb3f9a9efcedbadcd19a74ffb34a25f8e6b0e02dae7c0e71f8372f97b", + "sha256:566e72b0cd6598503e48ea610e0052d1b8168e60a46e0bfd34b3acf2d57f96a8", + "sha256:5703097c4936bbb9e9bce41478c8d08edd2865e177dc4c52be759f81ee4dd26c", + "sha256:7549fbf655e5825d787bbc9ecf6028731973f78088fbca3a1f4145c39ef09462", + "sha256:8207b7105829eca6f3d774f64a904190bb2231de91b8b186d21ffd98005f14a7", + "sha256:8c4d8e89aa7de683e2056a581ce63c46a0c41e31bd2b6d34144e2c80f5ea53dc", + "sha256:98324ec3ecf12296e6422939e54763faedbfcc502ea4a4c38502082711867258", + "sha256:9bbcd9ab8ea1f2e1c8031c21445b511442cc45c89951e49bbf852cbb70755b1b", + "sha256:9d40652cc4fe33871ad3338581dca3297ff5f2213d0df345bcfbde5162abf0c9", + "sha256:a2746d69a8196698146a3dbe29104f9eb6a2a4d8a27878d92169a6c0b74435b6", + "sha256:ae704dcfaa180ff7c4cfbad23e74321a2b774f92ca77fd94ce1049175a21c97f", + "sha256:bfdca17c36ae01a21274a3c387a63aa1aafe72bff976522886869ef131b937f1", + "sha256:c482e1246726616088532b5e964e39765b6d1520791348e6c9dc3af25b233828", + "sha256:ca637024ca67ab24a7fd6f65d280572c3794665eaf5edcc7e90a866544076878", + "sha256:e02d700ec8d9b1859790c0475df4e4092c7bf3272a4fd2c9f33d87fac4427b8f", + "sha256:e5952d2d18b79f7dc25e62e014fe5a23eb1a3d2bc66318df8988a01b1a037c5b" ], "index": "pypi", - "version": "==1.2.0" + "version": "==1.4.1" }, "mypy-extensions": { "hashes": [ @@ -308,11 +313,11 @@ }, "nodeenv": { "hashes": [ - "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e", - "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b" + "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2", + "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", - "version": "==1.7.0" + "version": "==1.8.0" }, "packaging": { "hashes": [ @@ -332,19 +337,19 @@ }, "platformdirs": { "hashes": [ - "sha256:64370d47dc3fca65b4879f89bdead8197e93e05d696d6d1816243ebae8595da5", - "sha256:ea61fd7b85554beecbbd3e9b37fb26689b227ffae38f73353cbcc1cf8bd01878" + "sha256:1b42b450ad933e981d56e59f1b97495428c9bd60698baab9f3eb3d00d5822421", + "sha256:ad8291ae0ae5072f66c16945166cb11c63394c7a3ad1b1bc9828ca3162da8c2f" ], "markers": "python_version >= '3.7'", - "version": "==3.3.0" + "version": "==3.9.1" }, "pre-commit": { "hashes": [ - "sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4", - "sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d" + "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb", + "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023" ], "index": "pypi", - "version": "==3.2.2" + "version": "==3.3.3" }, "pyyaml": { "hashes": [ @@ -394,34 +399,34 @@ }, "ruff": { "hashes": [ - "sha256:04e0b280dd246448564c892bce5607d820ad1f14944f3d535db98692e2a7ac07", - "sha256:1008f211ad8aa1d998517ac5bf3d68fbc68ec516d1da89b6081f25ff2f30b687", - "sha256:15386933dd8e03aafa3186f9e996d6823105492817311338fbcb64d0ecbcd95f", - "sha256:3e9fcee3f81129eabc75da005d839235e32d7d374f2d4c0db0c708dad4703d6e", - "sha256:4010b156f2e9fa6e74b5581098467f6ff68beac48945599b3a9239481e578ab4", - "sha256:4f75fa1632ea065b8f10678e7b6ae9873f84d5046bdf146990112751e98af42a", - "sha256:7890499c2c3dcb1e60de2a8b4c5f5775b2bfcdff7d3e68e38db5cb2d65b12006", - "sha256:82c41f276106017b6f075dd2f2cc68e1a0b434cc75488f816fc98bd41982628d", - "sha256:981e3c4d773f7ff52479c4fd74a65e408f1e13fa5f889b72214d400cd1299ce4", - "sha256:9af932f665e177de62e172901704257fd6e5bfabb95893867ff7382a851459d3", - "sha256:bed1d3fba306e3f7e13ce226927b84200350e25abd1e754e06ee361c6d41de15", - "sha256:c2b79919ebd93674b93dfc2c843e264bf8e52fbe737467e9b58521775c85f4ad", - "sha256:c3b7d4b365207f3e4c40d235127091478e595b31e35b6cd57d940920cdfae68b", - "sha256:ddcee0d91629a4fa4bc9faebf5b94d4615d50d1cd76d1098fa71fbe1c54f4104", - "sha256:ddf4503595b560bfa5fae92fa2e4cb09ec465ee4cf88cc248f10ad2e956deec3", - "sha256:ebc778d95f29c9917e6e7608b2b67815707e6ab8eb5af9341617beda479c3edf", - "sha256:ee6c7a77f142c427fa73e1f5f603fc1a39413a36fe6966ed0fc55e97f6921d9c" + "sha256:1078125123a3c68e92463afacedb7e41b15ccafc09e510c6c755a23087afc8de", + "sha256:1a90ebd8f2a554db1ee8d12b2f3aa575acbd310a02cd1a9295b3511a4874cf98", + "sha256:1a9f1d925204cfba81b18368b7ac943befcfccc3a41e170c91353b674c6b7a66", + "sha256:1cae4c07d334eb588f171f1363fa89a8911047eb93184276be11a24dbbc996c7", + "sha256:2c62a0bde4d20d087cabce2fa8b012d74c2e985da86d00fb3359880469b90e31", + "sha256:38ca1c0c8c1221fe64c0a66784c91501d09a8ed02a4dbfdc117c0ce32a81eefc", + "sha256:3ce0d620e257b4cad16e2f0c103b2f43a07981668a3763380542e8a131d11537", + "sha256:666e739fb2685277b879d493848afe6933e3be30d40f41fe0e571ad479d57d77", + "sha256:70d39f5599d8449082ab8ce542fa98e16413145eb411dd1dc16575b44565d52d", + "sha256:737a0cfb6c36aaa92d97a46957dfd5e55329299074ad06ed12663b98e0c6fc82", + "sha256:7545bb037823cd63dca19280f75a523a68bd3e78e003de74609320d6822b5a52", + "sha256:8cb380d2d6fdb60656a0b5fa78305535db513fc72ce11f4532cc1641204ef380", + "sha256:a48621f5f372d5019662db5b3dbfc5f1450f927683d75f1153fe0ebf20eb9698", + "sha256:c25b96602695a147d62a572865b753ef56aff1524abab13b9436724df30f9bd7", + "sha256:d11149c7b186f224f2055e437a030cd83b164a43cc0211314c33ad1553ed9c4c", + "sha256:e131595ab7f4ce61a1650463bd2fe304b49e7d0deb0dfa664b92817c97cdba5f", + "sha256:ec8b0469b54315803aaf1fbf9a37162a3849424cab6182496f972ad56e0ea702" ], "index": "pypi", - "version": "==0.0.263" + "version": "==0.0.278" }, "setuptools": { "hashes": [ - "sha256:23aaf86b85ca52ceb801d32703f12d77517b2556af839621c641fca11287952b", - "sha256:f104fa03692a2602fa0fec6c6a9e63b6c8a968de13e17c026957dd1f53d80990" + "sha256:11e52c67415a381d10d6b462ced9cfb97066179f0e871399e006c4ab101fc85f", + "sha256:baf1fdb41c6da4cd2eae722e135500da913332ab3f2f5c7d33af9b492acb5235" ], "markers": "python_version >= '3.7'", - "version": "==67.7.2" + "version": "==68.0.0" }, "tomli": { "hashes": [ @@ -433,19 +438,19 @@ }, "typing-extensions": { "hashes": [ - "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb", - "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4" + "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36", + "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2" ], "markers": "python_version >= '3.7'", - "version": "==4.5.0" + "version": "==4.7.1" }, "virtualenv": { "hashes": [ - "sha256:278753c47aaef1a0f14e6db8a4c5e1e040e90aea654d0fc1dc7e0d8a42616cc3", - "sha256:48fd3b907b5149c5aab7c23d9790bea4cac6bc6b150af8635febc4cfeab1275a" + "sha256:18d1b37fc75cc2670625702d76849a91ebd383768b4e91382a8d51be3246049e", + "sha256:e2a7cef9da880d693b933db7654367754f14e20650dc60e8ee7385571f8593a3" ], "markers": "python_version >= '3.7'", - "version": "==20.22.0" + "version": "==20.24.0" } } } diff --git a/ephemeral/action.yml b/ephemeral/action.yml index 6f93550..646818e 100644 --- a/ephemeral/action.yml +++ b/ephemeral/action.yml @@ -45,7 +45,7 @@ runs: name: Install pipenv shell: bash run: | - pip3 --quiet install --user pipenv==2023.4.20 + pip3 --quiet install --user pipenv==2023.6.26 - name: Install dependencies shell: bash diff --git a/github/base.py b/github/base.py index 4a10822..33a8d61 100644 --- a/github/base.py +++ b/github/base.py @@ -7,10 +7,13 @@ """ import logging +from http import HTTPStatus import github_action_utils as gha_utils import httpx +from utils.errors import RateLimitError + logger = logging.getLogger(__name__) @@ -27,6 +30,7 @@ def __init__(self, token: str) -> None: # Create the client for connection pooling, add headers for type # version and authorization self._client: httpx.Client = httpx.Client( + http2=True, base_url=self.API_BASE_URL, timeout=30.0, headers={ @@ -64,7 +68,7 @@ def _read_all_pages(self, endpoint: str, query_params: dict | None = None): while True: resp = self._client.get(endpoint, params=query_params) - if resp.status_code == 200: + if resp.status_code == HTTPStatus.OK: internal_data += resp.json() if "next" in resp.links: endpoint = resp.links["next"]["url"] @@ -75,6 +79,15 @@ def _read_all_pages(self, endpoint: str, query_params: dict | None = None): msg = f"Request to {endpoint} return HTTP {resp.status_code}" gha_utils.error(message=msg, title=f"HTTP Error {resp.status_code}") logger.error(msg) + + # If forbidden, check if it is rate limiting + if ( + resp.status_code == HTTPStatus.FORBIDDEN + and "X-RateLimit-Remaining" in resp.headers + ): + remaining = int(resp.headers["X-RateLimit-Remaining"]) + if remaining <= 0: + raise RateLimitError resp.raise_for_status() return internal_data diff --git a/github/packages.py b/github/packages.py index 1fc1d06..0d99385 100644 --- a/github/packages.py +++ b/github/packages.py @@ -2,11 +2,13 @@ import logging import re import urllib.parse +from http import HTTPStatus import github_action_utils as gha_utils from github.base import GithubApiBase from github.base import GithubEndpointResponse +from utils.errors import RateLimitError logger = logging.getLogger(__name__) @@ -123,15 +125,22 @@ def delete(self, package_data: ContainerPackage): Deletes the given package version from the GHCR """ resp = self._client.delete(package_data.url) - if resp.status_code != 204: - msg = ( - f"Request to delete {package_data.url} returned HTTP {resp.status_code}" - ) - gha_utils.warning( - message=msg, - title=f"Unexpected delete status: {resp.status_code}", - ) - logger.warning(msg) + if resp.status_code != HTTPStatus.NO_CONTENT: + # If forbidden, check if it is rate limiting + if ( + resp.status_code == HTTPStatus.FORBIDDEN + and "X-RateLimit-Remaining" in resp.headers + ): + remaining = int(resp.headers["X-RateLimit-Remaining"]) + if remaining <= 0: + raise RateLimitError + else: + msg = f"Request to delete {package_data.url} returned HTTP {resp.status_code}" + gha_utils.warning( + message=msg, + title=f"Unexpected delete status: {resp.status_code}", + ) + logger.warning(msg) def restore( self, @@ -147,13 +156,22 @@ def restore( ) resp = self._client.post(endpoint) - if resp.status_code != 204: - msg = f"Request to restore id {id} returned HTTP {resp.status_code}" - gha_utils.warning( - message=msg, - title=f"Unexpected restore status: {resp.status_code}", - ) - logger.warning(msg) + if resp.status_code != HTTPStatus.NO_CONTENT: + # If forbidden, check if it is rate limiting + if ( + resp.status_code == HTTPStatus.FORBIDDEN + and "X-RateLimit-Remaining" in resp.headers + ): + remaining = int(resp.headers["X-RateLimit-Remaining"]) + if remaining <= 0: + raise RateLimitError + else: + msg = f"Request to restore id {id} returned HTTP {resp.status_code}" + gha_utils.warning( + message=msg, + title=f"Unexpected restore status: {resp.status_code}", + ) + logger.warning(msg) class GithubContainerRegistryOrgApi(_GithubContainerRegistryApiBase): diff --git a/main_ephemeral.py b/main_ephemeral.py index 62861d3..5dbd9f9 100755 --- a/main_ephemeral.py +++ b/main_ephemeral.py @@ -3,6 +3,8 @@ import logging import re +import github_action_utils as gha_utils + from github.branches import GithubBranchApi from github.packages import ContainerPackage from github.packages import GithubContainerRegistryOrgApi @@ -13,6 +15,7 @@ from utils import coerce_to_bool from utils import common_args from utils import get_log_level +from utils.errors import RateLimitError logger = logging.getLogger("image-cleaner") @@ -155,8 +158,10 @@ def _main() -> None: config.owner_or_org, config.is_org, ) as api: + logger.info("Getting active packages") # Get the active (not deleted) packages active_versions = api.active_versions(config.package_name) + logger.info(f"{len(active_versions)} active packages") # # Step 2 - Filter the packages to those which are: @@ -166,6 +171,7 @@ def _main() -> None: # pkgs_matching_re: list[ContainerPackage] = [] all_pkgs_tags_to_version: dict[str, ContainerPackage] = {} + logger.info("Filtering packages to those matching the regex") for pkg in active_versions: if pkg.untagged or len(pkg.tags) > 1: continue @@ -184,15 +190,22 @@ def _main() -> None: # Step 3 - Gather the packages to remove (those where the source is gone or closed) # if config.scheme == "branch": + logger.info("Looking at branches for deletion considerations") tags_to_delete = _get_tag_to_delete_branch(config, pkgs_matching_re) elif config.scheme == "pull_request": + logger.info("Looking at pull requests for deletion considerations") tags_to_delete = _get_tags_to_delete_pull_request(config, pkgs_matching_re) + else: + # Configuration validation prevents any other option + pass tags_to_keep = list(set(all_pkgs_tags_to_version.keys()) - set(tags_to_delete)) if not len(tags_to_delete): logger.info("No images to remove") return + logger.info(f"Will remove {len(set(tags_to_delete))} tagged packages") + logger.info(f"Will keep {len(tags_to_keep)} packages") # # Step 4 - Delete the stale packages @@ -225,11 +238,14 @@ def _main() -> None: for tag in tags_to_keep: check_tag_still_valid(config.owner_or_org, config.package_name, tag) else: - logger.info("Dry run, not checking images") + logger.info("Dry run, not checking image manifests") if __name__ == "__main__": try: _main() + except RateLimitError: + logger.error("Rate limit hit during execution") + gha_utils.error("Rate limit hit during execution") finally: logging.shutdown() diff --git a/main_untagged.py b/main_untagged.py index d1ece20..f535aef 100755 --- a/main_untagged.py +++ b/main_untagged.py @@ -2,6 +2,8 @@ import logging +import github_action_utils as gha_utils + from github.packages import ContainerPackage from github.packages import GithubContainerRegistryOrgApi from github.packages import GithubContainerRegistryUserApi @@ -11,6 +13,7 @@ from utils import coerce_to_bool from utils import common_args from utils import get_log_level +from utils.errors import RateLimitError logger = logging.getLogger("image-cleaner") @@ -70,10 +73,12 @@ def _main() -> None: config.owner_or_org, config.is_org, ) as api: + logger.info("Getting active packages") # Get the active (not deleted) packages active_versions = api.active_versions(config.package_name) + logger.info(f"{len(active_versions)} active packages") - # Map the tag (eg latest) to its package and simplify the untagged data + # Map the tag (e.g. latest) to its package and simplify the untagged data # mapping name (which is a digest) to the version # These just make it easier to do some lookups later tag_to_pkgs: dict[str, ContainerPackage] = {} @@ -84,6 +89,8 @@ def _main() -> None: for tag in pkg.tags: tag_to_pkgs[tag] = pkg + logger.info(f"Found {len(untagged_versions)} packages which look untagged") + # # Step 2 - Find actually untagged packages # @@ -119,13 +126,19 @@ def _main() -> None: # TODO Make it clear for digests which are multi-tagged (latest, x.x.y) # they are not being deleted too + if not len(untagged_versions): + logger.info("Nothing to do") + return + + logger.info( + f"After multi-arch, there are {len(untagged_versions)} untagged packages", + ) + # # Step 4 - Delete the actually untagged packages # # Delete the untagged and not pointed at packages logger.info(f"Deleting untagged packages of {config.package_name}") - if not len(untagged_versions): - logger.info("Nothing to do") with container_reg_class( config.token, config.owner_or_org, @@ -160,5 +173,8 @@ def _main() -> None: if __name__ == "__main__": try: _main() + except RateLimitError: + logger.error("Rate limit hit during execution") + gha_utils.error("Rate limit hit during execution") finally: logging.shutdown() diff --git a/untagged/action.yml b/untagged/action.yml index 43bc4fa..c47e4b7 100644 --- a/untagged/action.yml +++ b/untagged/action.yml @@ -34,7 +34,7 @@ runs: name: Install pipenv shell: bash run: | - pip3 --quiet install --user pipenv==2023.4.20 + pip3 --quiet install --user pipenv==2023.6.26 - name: Install dependencies shell: bash diff --git a/utils/errors.py b/utils/errors.py new file mode 100644 index 0000000..32482fb --- /dev/null +++ b/utils/errors.py @@ -0,0 +1,2 @@ +class RateLimitError(Exception): + pass