From afa86eb08bbf99064f613e7d255393012575c101 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 4 Apr 2017 06:07:32 -0400 Subject: [PATCH 001/319] Initial commit --- COPYING | 502 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 503 insertions(+) create mode 100644 COPYING create mode 100644 README.md diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..4362b49 --- /dev/null +++ b/COPYING @@ -0,0 +1,502 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/README.md b/README.md new file mode 100644 index 0000000..5d530ba --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +This is where the magic happens. From 9f723058d07ae6006988914032e96be96673fc40 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 4 Apr 2017 06:16:07 -0400 Subject: [PATCH 002/319] Add some instructions --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5d530ba..4ee9dce 100644 --- a/README.md +++ b/README.md @@ -1 +1,6 @@ This is where the magic happens. + +Application manifests should go in their own branches, named after the application ID. + +For example, for gnome-recipes, there is a branch named org.gnome.Recipes which has +the org.gnome.Recipes.json file at the toplevel. From e22c6dd3612208c0b9fca964eea9722f572e1f52 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 4 Apr 2017 07:15:07 -0400 Subject: [PATCH 003/319] Mention stable releases --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 4ee9dce..df6a958 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,6 @@ Application manifests should go in their own branches, named after the applicati For example, for gnome-recipes, there is a branch named org.gnome.Recipes which has the org.gnome.Recipes.json file at the toplevel. + +The manifests should build releases, not development snapshots, so please use +tarballs or git tags, not just the tip of a branch. From 1d4f01e95d2048efd1ea8e91c163688bde147851 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 10 Apr 2017 17:33:35 +0200 Subject: [PATCH 004/319] Update README --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index df6a958..b66caac 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,16 @@ the org.gnome.Recipes.json file at the toplevel. The manifests should build releases, not development snapshots, so please use tarballs or git tags, not just the tip of a branch. + +In case you build from a git tag, please specify both the tag name and the commit id, liks so: +``` + "branch": "1.0.4", + "commit": "cdfb19b90587bc0c44404fae30c139f9ec1cca5c" +``` +This makes the build repeatable, since a tag can otherwise change its value over time. +You can also use only a commit, but specifing a tag name if there is one is good for readability. + +Flathub always builds in the flatpak branchname "stable", and it always passes --default-name=stable, +so you don't need to specify a branch key. But if you do (not recommended), it must be "stable". + +All applications in flathub should ship with appstream data. From 9b8c45fdd411d54607e8f339ae0c00d84fb69be1 Mon Sep 17 00:00:00 2001 From: AsciiWolf Date: Mon, 10 Apr 2017 18:26:01 +0200 Subject: [PATCH 005/319] Update README.md Fix typos --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b66caac..a584fdc 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,13 @@ the org.gnome.Recipes.json file at the toplevel. The manifests should build releases, not development snapshots, so please use tarballs or git tags, not just the tip of a branch. -In case you build from a git tag, please specify both the tag name and the commit id, liks so: +In case you build from a git tag, please specify both the tag name and the commit id, like so: ``` "branch": "1.0.4", "commit": "cdfb19b90587bc0c44404fae30c139f9ec1cca5c" ``` This makes the build repeatable, since a tag can otherwise change its value over time. -You can also use only a commit, but specifing a tag name if there is one is good for readability. +You can also use only a commit, but specifying a tag name if there is one is good for readability. Flathub always builds in the flatpak branchname "stable", and it always passes --default-name=stable, so you don't need to specify a branch key. But if you do (not recommended), it must be "stable". From 23b1138a96307d694662ee999094622fa677ea31 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Apr 2017 21:51:39 -0400 Subject: [PATCH 006/319] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a584fdc..916e726 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,7 @@ You can also use only a commit, but specifying a tag name if there is one is goo Flathub always builds in the flatpak branchname "stable", and it always passes --default-name=stable, so you don't need to specify a branch key. But if you do (not recommended), it must be "stable". +Flathub requires that you build against an sdk that is itself hosted on Flathub. The same goes for +sdk extensions that may be required to build your application. + All applications in flathub should ship with appstream data. From 0bf9e913bd7273029729e8ae718b8420a6dfcadd Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Apr 2017 22:01:50 -0400 Subject: [PATCH 007/319] Update README.md Add more requirements for building applications, and explain how to install apps that are hosted here. --- README.md | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 916e726..6c11e92 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,10 @@ -This is where the magic happens. +Flathub +------- + +Flathub is the central place for building and hosting flatpak builds. + +Building applications +--------------------- Application manifests should go in their own branches, named after the application ID. @@ -20,6 +26,19 @@ Flathub always builds in the flatpak branchname "stable", and it always passes - so you don't need to specify a branch key. But if you do (not recommended), it must be "stable". Flathub requires that you build against an sdk that is itself hosted on Flathub. The same goes for -sdk extensions that may be required to build your application. - +sdk extensions that may be required to build your application. The easiest way to see what runtimes +are currently available is to install the flathub remote and use +``` +flatpak remote-ls --runtime flathub +``` All applications in flathub should ship with appstream data. + +Using the flathub repository +---------------------------- + +To install applications that are hosted on flathub, use the following: +``` +flatpak remote-add flathub http://flathub.org/repo/flathub.flatpakrepo +flatpak --user install flathub org.gnome.Recipes +``` + From 5a8773f8ab9d6899cafa6114b6ed7f35ac926f7e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 10 Apr 2017 22:11:13 -0400 Subject: [PATCH 008/319] Update README.md Add a link to the website. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6c11e92..7bc08d0 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Flathub ------- Flathub is the central place for building and hosting flatpak builds. +Go to http://flathub.org/builds/#/ to see Flathub in action. Building applications --------------------- @@ -36,7 +37,7 @@ All applications in flathub should ship with appstream data. Using the flathub repository ---------------------------- -To install applications that are hosted on flathub, use the following: +To install applications that are hosted on Flathub, use the following: ``` flatpak remote-add flathub http://flathub.org/repo/flathub.flatpakrepo flatpak --user install flathub org.gnome.Recipes From b55dbed2025a6170202ba05c0e88b89c87ef74a1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 13 Apr 2017 08:26:41 -0400 Subject: [PATCH 009/319] Refer to the review guidelines Reduce the duplication. We still explain the basic setup here, but refer to the review guidelines for details. --- README.md | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 7bc08d0..c71ef7c 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,24 @@ Flathub ------- -Flathub is the central place for building and hosting flatpak builds. +Flathub is the central place for building and hosting Flatpak builds. Go to http://flathub.org/builds/#/ to see Flathub in action. Building applications --------------------- -Application manifests should go in their own branches, named after the application ID. +Application manifests should go in their own repository in the [Flathub](http://github.com/flathub) organization, +named after the application ID. -For example, for gnome-recipes, there is a branch named org.gnome.Recipes which has -the org.gnome.Recipes.json file at the toplevel. +For example, for gnome-recipes, there is a repository named org.gnome.Recipes which has the org.gnome.Recipes.json +file at the toplevel. -The manifests should build releases, not development snapshots, so please use -tarballs or git tags, not just the tip of a branch. +Hosted builds should be stable releases, not development snapshots, so please use tarballs or git tags, not just +the tip of a branch. -In case you build from a git tag, please specify both the tag name and the commit id, like so: -``` - "branch": "1.0.4", - "commit": "cdfb19b90587bc0c44404fae30c139f9ec1cca5c" -``` -This makes the build repeatable, since a tag can otherwise change its value over time. -You can also use only a commit, but specifying a tag name if there is one is good for readability. +More detailed requirements can be found in the [Review Guidelines](https://github.com/flatpak/flathub/wiki/Review-Guidelines) -Flathub always builds in the flatpak branchname "stable", and it always passes --default-name=stable, -so you don't need to specify a branch key. But if you do (not recommended), it must be "stable". - -Flathub requires that you build against an sdk that is itself hosted on Flathub. The same goes for -sdk extensions that may be required to build your application. The easiest way to see what runtimes -are currently available is to install the flathub remote and use -``` -flatpak remote-ls --runtime flathub -``` -All applications in flathub should ship with appstream data. - -Using the flathub repository +Using the Flathub repository ---------------------------- To install applications that are hosted on Flathub, use the following: From 746ea89cc4ff85ad2dbc05fb47efde23de4062f8 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 4 Apr 2017 06:07:32 -0400 Subject: [PATCH 010/319] Initial commit From 83d42eb331f4b06ebb40c719e89464eb3cc7bdee Mon Sep 17 00:00:00 2001 From: Juraj Fiala Date: Sun, 30 Apr 2017 14:17:09 +0200 Subject: [PATCH 011/319] README style fixes Make URL nicer, remove newlines from the end --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index c71ef7c..cfcc793 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Flathub ------- Flathub is the central place for building and hosting Flatpak builds. -Go to http://flathub.org/builds/#/ to see Flathub in action. +Go to http://flathub.org/builds/ to see Flathub in action. Building applications --------------------- @@ -26,4 +26,3 @@ To install applications that are hosted on Flathub, use the following: flatpak remote-add flathub http://flathub.org/repo/flathub.flatpakrepo flatpak --user install flathub org.gnome.Recipes ``` - From 7692efdb672d281a2aca09f67d8db33ca828e5e1 Mon Sep 17 00:00:00 2001 From: Jakub Bittner Date: Tue, 23 May 2017 07:16:48 +0200 Subject: [PATCH 012/319] Update README.md Changed protocol from http to https on flathub url because on http flathub reports errors. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cfcc793..9468bf0 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ Flathub ------- Flathub is the central place for building and hosting Flatpak builds. -Go to http://flathub.org/builds/ to see Flathub in action. +Go to https://flathub.org/builds/ to see Flathub in action. Building applications --------------------- -Application manifests should go in their own repository in the [Flathub](http://github.com/flathub) organization, +Application manifests should go in their own repository in the [Flathub](https://github.com/flathub) organization, named after the application ID. For example, for gnome-recipes, there is a repository named org.gnome.Recipes which has the org.gnome.Recipes.json From e12feaffbb609c8cd764dc40688e78d2bc9c8375 Mon Sep 17 00:00:00 2001 From: TingPing Date: Tue, 30 May 2017 09:30:42 -0400 Subject: [PATCH 013/319] README.md: Use https for repo url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9468bf0..99afd5a 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,6 @@ Using the Flathub repository To install applications that are hosted on Flathub, use the following: ``` -flatpak remote-add flathub http://flathub.org/repo/flathub.flatpakrepo +flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo flatpak --user install flathub org.gnome.Recipes ``` From f76db4180ace02cdaf7206541199ea0eb6f0a048 Mon Sep 17 00:00:00 2001 From: TingPing Date: Sun, 25 Jun 2017 13:08:11 -0400 Subject: [PATCH 014/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 99afd5a..20f9247 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ file at the toplevel. Hosted builds should be stable releases, not development snapshots, so please use tarballs or git tags, not just the tip of a branch. -More detailed requirements can be found in the [Review Guidelines](https://github.com/flatpak/flathub/wiki/Review-Guidelines) +More detailed requirements can be found in the [Review Guidelines](https://github.com/flathub/flathub/wiki/Review-Guidelines) Using the Flathub repository ---------------------------- From 1d51601f4e9767486336a0a4719354caf5c2e8e4 Mon Sep 17 00:00:00 2001 From: TingPing Date: Fri, 21 Jul 2017 18:00:53 -0400 Subject: [PATCH 015/319] README: Fix example Closes #60 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 20f9247..cf8fa89 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,5 @@ Using the Flathub repository To install applications that are hosted on Flathub, use the following: ``` flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo -flatpak --user install flathub org.gnome.Recipes +flatpak install flathub org.gnome.Recipes ``` From eac592fec995ae6acc8512c73016c5abdef17bf4 Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 17 Jan 2018 00:08:26 -0500 Subject: [PATCH 016/319] Create CONTRIBUTORS.md Closes #199 --- CONTRIBUTORS.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 CONTRIBUTORS.md diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000..dbc5776 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,16 @@ +### Submitting a new package + +If you are submitting a new package please read the [submission](https://github.com/flathub/flathub/wiki/Submission-Guidelines) +and [review](https://github.com/flathub/flathub/wiki/Review-Guidelines) guidelines in the wiki. + +Also double-check that your PR is against the `new-pr` branch. + +### Reporting a bug on a package + +Please open bugs for packages on their respective repositories you can search for them here: https://github.com/flathub + +### Requesting a new package + +Please do not open issues requesting packages. As long as a package meets the guidelines above and works it will be +generally be accepted. If you want to create a Flatpak see the [documentation](https://flatpak.readthedocs.io/en/latest/) +or join ircs://chat.freenode.net/flatpak for help. From d3d04097eb5c30c745632279d02bba6707e8444e Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 17 Jan 2018 00:09:30 -0500 Subject: [PATCH 017/319] Rename CONTRIBUTORS.md to CONTRIBUTING.md --- CONTRIBUTORS.md => CONTRIBUTING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTORS.md => CONTRIBUTING.md (100%) diff --git a/CONTRIBUTORS.md b/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTORS.md rename to CONTRIBUTING.md From bcb234d99e3d360cc84876bcbc786fd4a4bac240 Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 17 Jan 2018 04:29:23 -0500 Subject: [PATCH 018/319] Update README.md Closes #170 --- README.md | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index cf8fa89..d51395e 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,6 @@ -Flathub -------- +# Flathub Flathub is the central place for building and hosting Flatpak builds. -Go to https://flathub.org/builds/ to see Flathub in action. - -Building applications ---------------------- - -Application manifests should go in their own repository in the [Flathub](https://github.com/flathub) organization, -named after the application ID. - -For example, for gnome-recipes, there is a repository named org.gnome.Recipes which has the org.gnome.Recipes.json -file at the toplevel. - -Hosted builds should be stable releases, not development snapshots, so please use tarballs or git tags, not just -the tip of a branch. - -More detailed requirements can be found in the [Review Guidelines](https://github.com/flathub/flathub/wiki/Review-Guidelines) Using the Flathub repository ---------------------------- @@ -26,3 +10,10 @@ To install applications that are hosted on Flathub, use the following: flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo flatpak install flathub org.gnome.Recipes ``` + +For more information and more applications see https://flathub.org/apps.html + +Contributing to Flathub +----------------------- + +For information on creating packages or reporting issues please see the [contributing page](/CONTRIBUTING.md). From 2ff247f8392e29b2981773b82ab74495312fd7a0 Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 17 Jan 2018 04:30:12 -0500 Subject: [PATCH 019/319] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d51395e..3afec22 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo flatpak install flathub org.gnome.Recipes ``` -For more information and more applications see https://flathub.org/apps.html +For more information and more applications see https://flathub.org Contributing to Flathub ----------------------- From ddf677af31105334e3d418f1e3315f6c129c9c89 Mon Sep 17 00:00:00 2001 From: TingPing Date: Thu, 18 Jan 2018 12:34:21 -0500 Subject: [PATCH 020/319] Update CONTRIBUTING.md --- CONTRIBUTING.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dbc5776..006b123 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,6 @@ ### Submitting a new package -If you are submitting a new package please read the [submission](https://github.com/flathub/flathub/wiki/Submission-Guidelines) -and [review](https://github.com/flathub/flathub/wiki/Review-Guidelines) guidelines in the wiki. +If you are submitting a new package please read the [package guidelines](https://github.com/flathub/flathub/wiki/Package-Guidelines) in the wiki. Also double-check that your PR is against the `new-pr` branch. From 704071e93608ccaf629bda5fb2a7470d47b0af13 Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 24 Jan 2018 10:08:16 -0500 Subject: [PATCH 021/319] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 006b123..fc9e1fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ ### Submitting a new package -If you are submitting a new package please read the [package guidelines](https://github.com/flathub/flathub/wiki/Package-Guidelines) in the wiki. +If you are submitting a new package please read the [app submission](https://github.com/flathub/flathub/wiki/App-Submission) and [package guidelines](https://github.com/flathub/flathub/wiki/Package-Guidelines) pages in the wiki. Also double-check that your PR is against the `new-pr` branch. From b8734daf92b70b75ee1ebf89ea85f73938b3f3a1 Mon Sep 17 00:00:00 2001 From: TingPing Date: Wed, 24 Jan 2018 12:26:02 -0500 Subject: [PATCH 022/319] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fc9e1fd..849532b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ ### Submitting a new package -If you are submitting a new package please read the [app submission](https://github.com/flathub/flathub/wiki/App-Submission) and [package guidelines](https://github.com/flathub/flathub/wiki/Package-Guidelines) pages in the wiki. +If you are submitting a new package please read the [app submission](https://github.com/flathub/flathub/wiki/App-Submission) and [app requirements](https://github.com/flathub/flathub/wiki/App-Requirements) pages in the wiki. Also double-check that your PR is against the `new-pr` branch. From 1a3cfd198382efc33620bc4860bb2d5d63a256ad Mon Sep 17 00:00:00 2001 From: Job van der Zwan Date: Tue, 19 Feb 2019 14:25:24 +0100 Subject: [PATCH 023/319] README.md: send people looking for website repo to linux-store-frontend I almost opened an issue here due to misunderstanding what this repo is for. See also: https://github.com/flathub/linux-store-frontend/issues/167 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 3afec22..2dbd878 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,5 @@ Contributing to Flathub ----------------------- For information on creating packages or reporting issues please see the [contributing page](/CONTRIBUTING.md). + +***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/linux-store-frontend* From c7c70b06c15bd83363be529ecafdb5c1162a149c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Fri, 4 Oct 2019 12:16:26 +0200 Subject: [PATCH 024/319] Add GitHub action for merging new apps --- .github/workflows/merge.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/merge.yml diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml new file mode 100644 index 0000000..1653d74 --- /dev/null +++ b/.github/workflows/merge.yml @@ -0,0 +1,14 @@ +on: + issue_comment: + types: [created] +name: Automatic application merge +jobs: + merge: + name: Merge + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Automatic Rebase + uses: flathub-actions/merge@master + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 547f7ba08914725d4d7d6c521764c2d77b2c498c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Fri, 4 Oct 2019 15:10:13 +0200 Subject: [PATCH 025/319] Set proper step name for flathub-actions/merge --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 1653d74..f5ebd33 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@master - - name: Automatic Rebase + - name: Merge application uses: flathub-actions/merge@master env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From f0f0bf5e2d226ec186f4e75afd8eed4a9a368fa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Thu, 24 Oct 2019 10:09:07 +0200 Subject: [PATCH 026/319] Switch merge action to flathub/actions --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index f5ebd33..e919e03 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -9,6 +9,6 @@ jobs: steps: - uses: actions/checkout@master - name: Merge application - uses: flathub-actions/merge@master + uses: flathub/actions/merge@master env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 4d37a75ca68a2cc2d98cf3866ce7d67469f3fc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Fri, 25 Oct 2019 09:53:43 +0200 Subject: [PATCH 027/319] Remove actions/checkout as we clone repo on our own --- .github/workflows/merge.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index e919e03..382abe9 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -7,7 +7,6 @@ jobs: name: Merge runs-on: ubuntu-latest steps: - - uses: actions/checkout@master - name: Merge application uses: flathub/actions/merge@master env: From 3476de66bd072681e643618f0292d05b5b17d8e0 Mon Sep 17 00:00:00 2001 From: eszlari Date: Mon, 11 Nov 2019 22:29:19 +0100 Subject: [PATCH 028/319] README.md: add info about flathub beta --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2dbd878..428e9b9 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,12 @@ flatpak remote-add flathub https://flathub.org/repo/flathub.flatpakrepo flatpak install flathub org.gnome.Recipes ``` +To install applications from the beta branch, use the following: +``` +flatpak remote-add flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo +flatpak install flathub-beta org.godotengine.Godot +``` + For more information and more applications see https://flathub.org Contributing to Flathub From 1e09d9dc71fccddceccb28283c6709d4359f1abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Thu, 21 Nov 2019 11:49:51 +0100 Subject: [PATCH 029/319] Add flathub-data-checker action --- .github/workflows/flathub-data-checker.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/flathub-data-checker.yml diff --git a/.github/workflows/flathub-data-checker.yml b/.github/workflows/flathub-data-checker.yml new file mode 100644 index 0000000..ff10b9d --- /dev/null +++ b/.github/workflows/flathub-data-checker.yml @@ -0,0 +1,10 @@ +name: 'Check if external data changed' +on: deployment + +jobs: + flathub-data-checker: + runs-on: ubuntu-latest + steps: + - uses: flathub/actions/flathub-data-checker@master + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From a1cfebd795d64946460fb4b86e5be83e524ae806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Fri, 22 Nov 2019 15:19:02 +0100 Subject: [PATCH 030/319] Run flathub-data-checker hourly --- .github/workflows/flathub-data-checker.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/flathub-data-checker.yml b/.github/workflows/flathub-data-checker.yml index ff10b9d..bbc51f8 100644 --- a/.github/workflows/flathub-data-checker.yml +++ b/.github/workflows/flathub-data-checker.yml @@ -1,5 +1,7 @@ name: 'Check if external data changed' -on: deployment +on: + schedule: + - cron: '0 * * * *' jobs: flathub-data-checker: From 298f9aa63dbd6b077b3448b42668fc3800d80a7b Mon Sep 17 00:00:00 2001 From: Bilal Elmoussaoui Date: Mon, 23 Dec 2019 17:55:18 +0100 Subject: [PATCH 031/319] Actions: add stale to auto close old stalled PR --- .github/workflows/stale.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000..c2781fe --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,15 @@ +name: "Close stale PR" +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v1 + with: + repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} + stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 14 days. Feel free to re-open it if you plan to continue working on that pull request or think it deserves attention from Flathub admins" + days-before-stale: 365 + days-before-close: 14 From 7296f4edd542804f9cdbebc98faa400e0c6b5fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Wed, 8 Apr 2020 12:05:21 +0200 Subject: [PATCH 032/319] flathub-data-checker action was renamed to external-data-checker --- .../{flathub-data-checker.yml => external-data-checker.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{flathub-data-checker.yml => external-data-checker.yml} (78%) diff --git a/.github/workflows/flathub-data-checker.yml b/.github/workflows/external-data-checker.yml similarity index 78% rename from .github/workflows/flathub-data-checker.yml rename to .github/workflows/external-data-checker.yml index bbc51f8..cd434c5 100644 --- a/.github/workflows/flathub-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -7,6 +7,6 @@ jobs: flathub-data-checker: runs-on: ubuntu-latest steps: - - uses: flathub/actions/flathub-data-checker@master + - uses: flathub/actions/external-data-checker@master env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 497e4f539f70e2e88044d6cb68efd3df99b8eb13 Mon Sep 17 00:00:00 2001 From: Nick Richards Date: Thu, 29 Oct 2020 09:44:51 +0000 Subject: [PATCH 033/319] Initial Pull Request Template --- .github/pull_request_template.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..dee9998 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,14 @@ +I have read the guidelines at +https://github.com/flathub/flathub/wiki/App-Requirements and https://github.com/flathub/flathub/wiki/App-Maintenance and this PR follows the instructions at https://github.com/flathub/flathub/wiki/App-Submission + +as a pull request template https://docs.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository + +I am using only the minimal set of permissions. If not, the reasons the application needs each permission are + +All content stored in the flathub is redistributible by any party. If not, the unredistributable parts are using an extra-data source type + +I am an upstream contributor to the project. If not I link a request for upstream to submit their software to Flathub directly + +I own the domain used in the application id or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge) + +Any additional patches or files have been submitted to the upstream projects concerned. If not, explain why. \ No newline at end of file From 35e337888b70a98637c13d35d37ff55a1cc49b6a Mon Sep 17 00:00:00 2001 From: Nick Richards Date: Sat, 19 Dec 2020 21:05:57 +0000 Subject: [PATCH 034/319] remove placeholder text --- .github/pull_request_template.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index dee9998..8e7ffe7 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,14 @@ +## Please confirm your submission meets all the criteria ## + I have read the guidelines at https://github.com/flathub/flathub/wiki/App-Requirements and https://github.com/flathub/flathub/wiki/App-Maintenance and this PR follows the instructions at https://github.com/flathub/flathub/wiki/App-Submission -as a pull request template https://docs.github.com/en/github/building-a-strong-community/creating-a-pull-request-template-for-your-repository +I am using only the minimal set of permissions. If not, the reasons the application needs each permission are: -I am using only the minimal set of permissions. If not, the reasons the application needs each permission are +All content stored in the flathub is redistributible by any party. If not, the unredistributable parts are using an extra-data source type. -All content stored in the flathub is redistributible by any party. If not, the unredistributable parts are using an extra-data source type +I am an upstream contributor to the project. If not I link to a request for upstream to submit their software to Flathub directly. -I am an upstream contributor to the project. If not I link a request for upstream to submit their software to Flathub directly - -I own the domain used in the application id or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge) +I own the domain used in the application id or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). Any additional patches or files have been submitted to the upstream projects concerned. If not, explain why. \ No newline at end of file From 27b01db0e4626911055ed606da75d06137e130ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Mon, 21 Dec 2020 08:48:40 +0100 Subject: [PATCH 035/319] Switch pull request template to check list --- .github/pull_request_template.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 8e7ffe7..617249a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,14 +1,13 @@ -## Please confirm your submission meets all the criteria ## +### Please confirm your submission meets all the criteria -I have read the guidelines at -https://github.com/flathub/flathub/wiki/App-Requirements and https://github.com/flathub/flathub/wiki/App-Maintenance and this PR follows the instructions at https://github.com/flathub/flathub/wiki/App-Submission +- [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. +- [ ] My pull request follows the instructions at [App Submission][submission]. +- [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* +- [ ] All assets referenced in the manifest are redistributible by any party. If not, the unredistributable parts are using an extra-data source type. +- [ ] I am an upstream contributor to the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** +- [ ] I own the domain used in the application ID or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). +- [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* -I am using only the minimal set of permissions. If not, the reasons the application needs each permission are: - -All content stored in the flathub is redistributible by any party. If not, the unredistributable parts are using an extra-data source type. - -I am an upstream contributor to the project. If not I link to a request for upstream to submit their software to Flathub directly. - -I own the domain used in the application id or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). - -Any additional patches or files have been submitted to the upstream projects concerned. If not, explain why. \ No newline at end of file +[reqs]: https://github.com/flathub/flathub/wiki/App-Requirements +[maint]: https://github.com/flathub/flathub/wiki/App-Maintenance +[submission]: https://github.com/flathub/flathub/wiki/App-Submission From 2c633d3b6f74ee11527af87a2588531ee000919e Mon Sep 17 00:00:00 2001 From: AsciiWolf Date: Sat, 2 Jan 2021 21:56:09 +0100 Subject: [PATCH 036/319] Fix typo --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 617249a..3b75009 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -3,7 +3,7 @@ - [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. - [ ] My pull request follows the instructions at [App Submission][submission]. - [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* -- [ ] All assets referenced in the manifest are redistributible by any party. If not, the unredistributable parts are using an extra-data source type. +- [ ] All assets referenced in the manifest are redistributable by any party. If not, the unredistributable parts are using an extra-data source type. - [ ] I am an upstream contributor to the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** - [ ] I own the domain used in the application ID or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). - [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* From 671d9733f7c4eb2eab123b42723a42b0c10030ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Tue, 16 Feb 2021 18:43:23 +0100 Subject: [PATCH 037/319] ci: Use ghcr.io/flathub/actions/merge Docker image --- .github/workflows/merge.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 382abe9..7c6c407 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -1,13 +1,16 @@ +name: Automatic application merge + on: issue_comment: - types: [created] -name: Automatic application merge + types: + - created + jobs: merge: - name: Merge runs-on: ubuntu-latest + container: + image: ghcr.io/flathub/actions/merge:latest steps: - - name: Merge application - uses: flathub/actions/merge@master - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + - run: /entrypoint.py + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 46a416ef98a210fb09b3890a531eaa4131dcceb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Fri, 19 Feb 2021 09:59:29 +0100 Subject: [PATCH 038/319] ci: Switch to the renamed flathub-external-data-checker action --- .github/workflows/external-data-checker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index cd434c5..7ded744 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -1,12 +1,12 @@ -name: 'Check if external data changed' +name: 'Check if external data changed across Flathub org' on: schedule: - cron: '0 * * * *' jobs: - flathub-data-checker: + flathub-data-checker-global: runs-on: ubuntu-latest steps: - - uses: flathub/actions/external-data-checker@master + - uses: flathub/actions/flathub-external-data-checker@master env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From a57bbfba1cb7ddc25c08a0f8d41216f87bedef46 Mon Sep 17 00:00:00 2001 From: Lionir Date: Sun, 6 Jun 2021 01:20:15 -0400 Subject: [PATCH 039/319] Change IRC link to Matrix Related to https://github.com/flatpak/flatpak.github.io/commit/7650ec07b8a1990b2f5ab8418d6bf740615fc3c7 Fix https://github.com/flathub/flathub/issues/2366 --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 849532b..00b9c84 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,4 +12,4 @@ Please open bugs for packages on their respective repositories you can search fo Please do not open issues requesting packages. As long as a package meets the guidelines above and works it will be generally be accepted. If you want to create a Flatpak see the [documentation](https://flatpak.readthedocs.io/en/latest/) -or join ircs://chat.freenode.net/flatpak for help. +or join [#flatpak:matrix.org](https://matrix.to/#/#flatpak:matrix.org) for help. From f26263950d1eb43d996f6b043a41b1eca75394ce Mon Sep 17 00:00:00 2001 From: Kolja Lampe Date: Mon, 7 Mar 2022 20:42:24 +0100 Subject: [PATCH 040/319] Change link to new frontend --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 428e9b9..d112f57 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ Contributing to Flathub For information on creating packages or reporting issues please see the [contributing page](/CONTRIBUTING.md). -***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/linux-store-frontend* +***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/frontend* From 3bdaf6572689f494c26303ff89a0b771465e1401 Mon Sep 17 00:00:00 2001 From: Kolja Lampe Date: Fri, 25 Mar 2022 12:30:12 +0100 Subject: [PATCH 041/319] Update website link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d112f57..157c42b 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ Contributing to Flathub For information on creating packages or reporting issues please see the [contributing page](/CONTRIBUTING.md). -***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/frontend* +***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/website* From 180c502b2862c2038734238a39942fa019e62d4b Mon Sep 17 00:00:00 2001 From: Voxel <41875513+VoxelCubes@users.noreply.github.com> Date: Wed, 26 Apr 2023 21:53:21 +0200 Subject: [PATCH 042/319] Fix repeated word This error typically happens when changing the sentence structure mid writing. --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 00b9c84..f2d90f4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,6 +10,6 @@ Please open bugs for packages on their respective repositories you can search fo ### Requesting a new package -Please do not open issues requesting packages. As long as a package meets the guidelines above and works it will be +Please do not open issues requesting packages. As long as a package meets the guidelines above and works it will generally be accepted. If you want to create a Flatpak see the [documentation](https://flatpak.readthedocs.io/en/latest/) or join [#flatpak:matrix.org](https://matrix.to/#/#flatpak:matrix.org) for help. From 1963c8908851feda196fe7f4d588101e066fc9f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Figui=C3=A8re?= Date: Wed, 7 Jun 2023 18:29:23 -0400 Subject: [PATCH 043/319] Change the URL to the new documentation --- .github/pull_request_template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3b75009..38ecee1 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,6 +8,6 @@ - [ ] I own the domain used in the application ID or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). - [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* -[reqs]: https://github.com/flathub/flathub/wiki/App-Requirements -[maint]: https://github.com/flathub/flathub/wiki/App-Maintenance -[submission]: https://github.com/flathub/flathub/wiki/App-Submission +[reqs]: https://docs.flathub.org/docs/for-app-authors/requirements +[maint]: https://docs.flathub.org/docs/for-app-authors/maintanance +[submission]: https://docs.flathub.org/docs/for-app-authors/submission From ce96d7f014f2e68a122627f645ce560c9c1d8422 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 1 Nov 2023 11:13:25 +0530 Subject: [PATCH 044/319] Add locally building and testing to the PR template --- .github/pull_request_template.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 38ecee1..6f59235 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,6 +2,7 @@ - [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. - [ ] My pull request follows the instructions at [App Submission][submission]. +- [ ] I have [built][build] and tested the submission locally. - [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* - [ ] All assets referenced in the manifest are redistributable by any party. If not, the unredistributable parts are using an extra-data source type. - [ ] I am an upstream contributor to the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** @@ -11,3 +12,4 @@ [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [maint]: https://docs.flathub.org/docs/for-app-authors/maintanance [submission]: https://docs.flathub.org/docs/for-app-authors/submission +[build]: https://docs.flatpak.org/en/latest/first-build.html From 482f0b0ffd976b06574ef1e798529b12687a105d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Dec 2023 23:35:34 +0530 Subject: [PATCH 045/319] Switch to Flathub specific build instructions --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 6f59235..3f76991 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,4 +12,4 @@ [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [maint]: https://docs.flathub.org/docs/for-app-authors/maintanance [submission]: https://docs.flathub.org/docs/for-app-authors/submission -[build]: https://docs.flatpak.org/en/latest/first-build.html +[build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission From af29138cf0bfe8c0e3090bd9634cc54f8762a96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Wed, 3 Jan 2024 16:23:56 +0100 Subject: [PATCH 046/319] Import org-wide flatpak-external-data-checker action --- .../flatpak-external-data-checker/Dockerfile | 10 ++++ .../entrypoint.sh | 47 +++++++++++++++++++ .../flatpak-external-data-checker/gh-ls-org | 24 ++++++++++ .github/workflows/external-data-checker.yml | 2 +- 4 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 .github/actions/flatpak-external-data-checker/Dockerfile create mode 100755 .github/actions/flatpak-external-data-checker/entrypoint.sh create mode 100755 .github/actions/flatpak-external-data-checker/gh-ls-org diff --git a/.github/actions/flatpak-external-data-checker/Dockerfile b/.github/actions/flatpak-external-data-checker/Dockerfile new file mode 100644 index 0000000..eb3fc6d --- /dev/null +++ b/.github/actions/flatpak-external-data-checker/Dockerfile @@ -0,0 +1,10 @@ +FROM ghcr.io/flathub/flatpak-external-data-checker:latest + +RUN apt-get update && \ + apt-get install -y parallel && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +ADD gh-ls-org /usr/local/bin/gh-ls-org +ADD entrypoint.sh /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh new file mode 100755 index 0000000..25a7b6e --- /dev/null +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +if [[ -z "$GITHUB_WORKSPACE" || -z "$GITHUB_REPOSITORY" ]]; then + echo "Script is not running in GitHub Actions CI" + exit 1 +fi + +git config --global user.name "flathubbot" && \ +git config --global user.email "sysadmin@flathub.org" + +mkdir flathub +cd flathub + +gh-ls-org flathub | parallel "git clone --depth 1 {}" +mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u ) + +for repo in ${checker_apps[@]}; do + FEDC_OPTS=() + + if [[ -f $repo/flathub.json ]]; then + # check if repo opted out + if ! jq -e '."disable-external-data-checker" | not' < $repo/flathub.json > /dev/null; then + continue + fi + # check if the app is EOL + if ! jq -e '."end-of-life" or ."end-of-life-rebase" | not' < $repo/flathub.json > /dev/null; then + continue + fi + # add repo-specified f-e-d-c args + if jq -e '."require-important-update"' < $repo/flathub.json > /dev/null; then + FEDC_OPTS+=("--require-important-update") + fi + fi + + if [[ -f $repo/${repo}.yml ]]; then + manifest=${repo}.yml + elif [[ -f $repo/${repo}.yaml ]]; then + manifest=${repo}.yaml + elif [[ -f $repo/${repo}.json ]]; then + manifest=${repo}.json + else + continue + fi + + echo "==> checking ${repo}" + /app/flatpak-external-data-checker --verbose --update "${FEDC_OPTS[@]}" "$repo/$manifest" +done diff --git a/.github/actions/flatpak-external-data-checker/gh-ls-org b/.github/actions/flatpak-external-data-checker/gh-ls-org new file mode 100755 index 0000000..3c99dda --- /dev/null +++ b/.github/actions/flatpak-external-data-checker/gh-ls-org @@ -0,0 +1,24 @@ +#!/usr/bin/python3 + +import argparse +import os + +import github + +if __name__ == "__main__": + usage = ( + "lists repositories belonging to github organization\n" + "example: gh-ls-org foobar | xargs -P4 -L1 git clone --recursive" + ) + parser = argparse.ArgumentParser(usage=usage) + parser.add_argument("organization", help="name of github organization") + args = parser.parse_args() + + github_token = os.environ['GITHUB_TOKEN'] + g = github.Github(github_token, per_page=200) + + org = g.get_organization(args.organization) + + for repo in org.get_repos(): + if not repo.archived: + print(repo.html_url) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 7ded744..7acf179 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -7,6 +7,6 @@ jobs: flathub-data-checker-global: runs-on: ubuntu-latest steps: - - uses: flathub/actions/flathub-external-data-checker@master + - uses: ./.github/actions/flatpak-external-data-checker env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From c1a60639fc22a79b5295789e2e67d37d2ca735a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Wed, 3 Jan 2024 16:30:21 +0100 Subject: [PATCH 047/319] Import merge action --- .github/actions/merge/Dockerfile | 10 + .github/actions/merge/entrypoint.py | 247 +++++++++++ .github/actions/merge/requirements.in | 4 + .github/actions/merge/requirements.txt | 548 +++++++++++++++++++++++++ 4 files changed, 809 insertions(+) create mode 100644 .github/actions/merge/Dockerfile create mode 100755 .github/actions/merge/entrypoint.py create mode 100644 .github/actions/merge/requirements.in create mode 100644 .github/actions/merge/requirements.txt diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile new file mode 100644 index 0000000..1dd5751 --- /dev/null +++ b/.github/actions/merge/Dockerfile @@ -0,0 +1,10 @@ +FROM quay.io/fedora/fedora:38 + +RUN dnf install -y flatpak-builder git /usr/bin/pip && \ + dnf clean all + +ADD requirements.txt /requirements.txt +RUN pip install -r /requirements.txt + +ADD entrypoint.py /entrypoint.py +ENTRYPOINT ["/entrypoint.py"] diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py new file mode 100755 index 0000000..00a9654 --- /dev/null +++ b/.github/actions/merge/entrypoint.py @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 + +import glob +import json +import os +import re +import subprocess +import sys +import tempfile +import time + +import github +import pygit2 +import yaml +from gql import Client, gql +from gql.transport.requests import RequestsHTTPTransport + + +def set_protected_branch(token, repo, branch): + transport = RequestsHTTPTransport( + url="https://api.github.com/graphql", + headers={"Authorization": f"Bearer {token}"}, + ) + client = Client(transport=transport, fetch_schema_from_transport=False) + + gql_get_repo_id = gql( + """ + query get_repo_id($repo: String!) { + repository(name: $repo, owner: "flathub") { + id + } + } + """ + ) + + gql_add_branch_protection = gql( + """ + mutation add_branch_protection($repositoryID: ID!, $pattern: String!) { + createBranchProtectionRule( + input: { + allowsDeletions: false + allowsForcePushes: false + dismissesStaleReviews: false + isAdminEnforced: false + pattern: $pattern + repositoryId: $repositoryID + requiresApprovingReviews: true + requiredApprovingReviewCount: 0 + requiresCodeOwnerReviews: false + requiresStatusChecks: true + requiresStrictStatusChecks: true + restrictsReviewDismissals: false + requiredStatusCheckContexts: ["builds/x86_64"] + } + ) { + branchProtectionRule { + id + } + } + } + """ + ) + + repo_id = client.execute(gql_get_repo_id, variable_values={"repo": repo}) + repo_id = repo_id["repository"]["id"] + + result = client.execute( + gql_add_branch_protection, + variable_values={"repositoryID": repo_id, "pattern": branch}, + ) + return result + + +def detect_appid(dirname): + files = [] + ret = (None, None) + + for ext in ("yml", "yaml", "json"): + files.extend(glob.glob(f"{dirname}/*.{ext}")) + + for filename in files: + print(f"Parsing {filename}") + if os.path.isfile(filename): + ext = filename.split(".")[-1] + + with open(filename) as f: + if ext in ("yml", "yaml"): + manifest = yaml.safe_load(f) + else: + result = subprocess.run( + ["flatpak-builder", "--show-manifest", filename], + stdout=subprocess.PIPE, + ) + if result.returncode == 0: + manifest = json.loads(result.stdout.decode("utf-8")) + else: + print( + "flatpak-builder failed to print manifest, falling back to json Python module" + ) + try: + with open(filename) as f: + manifest = json.load(f) + except json.decoder.JSONDecodeError: + ("Manifest is not a valid JSON") + break + + if manifest: + manifest_file = os.path.basename(filename) + if "app-id" in manifest: + appid = manifest["app-id"] + elif "id" in manifest: + appid = manifest["id"] + else: + continue + if os.path.splitext(manifest_file)[0] != appid: + print(f"Skipping {manifest_file}, does not match appid {appid}") + continue + ret = (manifest_file, appid) + + return ret + + +def main(): + github_token = os.environ.get("GITHUB_TOKEN") + if not github_token: + print("GITHUB_TOKEN environment variable is not set") + sys.exit(1) + + github_event_path = os.environ.get("GITHUB_EVENT_PATH") + with open(github_event_path) as f: + github_event = json.load(f) + + if github_event["action"] != "created": + print("The event is not a comment") + sys.exit(0) + + if "pull_request" not in github_event["issue"]: + print("The issue is not a pull request") + sys.exit(0) + + command_re = re.search("^/merge.*", github_event["comment"]["body"], re.M) + if not command_re: + print("The comment doesn't contain '/merge' command") + sys.exit(0) + else: + command = command_re.group() + + gh = github.Github(github_token) + org = gh.get_organization("flathub") + + admins = org.get_team_by_slug("admins") + reviewers = org.get_team_by_slug("reviewers") + comment_author = gh.get_user(github_event["comment"]["user"]["login"]) + + if not admins.has_in_members(comment_author) and not reviewers.has_in_members( + comment_author + ): + print(f"{comment_author} is not a reviewer") + sys.exit(1) + + flathub = org.get_repo("flathub") + pr_id = int(github_event["issue"]["number"]) + pr = flathub.get_pull(pr_id) + pr_author = pr.user.login + branch = pr.head.label.split(":")[1] + fork_url = pr.head.repo.clone_url + + tmpdir = tempfile.TemporaryDirectory() + print(f"Cloning {fork_url} (branch: {branch})") + clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=branch) + clone.update_submodules(init=True) + + manifest_file, appid = detect_appid(tmpdir.name) + if manifest_file is None or appid is None: + print("Failed to detect appid") + sys.exit(1) + + print(f"Detected {appid} as appid from {manifest_file}") + + print("Creating new repo on Flathub") + repo = org.create_repo(appid) + time.sleep(5) + repo.edit(homepage=f"https://flathub.org/apps/details/{appid}") + + print("Adding flathub remote") + clone.remotes.create( + "flathub", f"https://x-access-token:{github_token}@github.com/flathub/{appid}" + ) + + try: + remote_branch = command.split()[0].split(":")[1] + if remote_branch != "beta": + remote_branch = f"branch/{remote_branch}" + except IndexError: + remote_branch = "master" + + print("Pushing changes to the new Flathub repo") + git_push = f"cd {tmpdir.name} && git push flathub {branch}:{remote_branch}" + ret = subprocess.run( + git_push, + shell=True, + check=True, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + print(ret.stdout) + print(ret.stderr) + repo.remove_from_collaborators("flathubbot") + + print("Setting protected branches") + for branch in ("master", "main", "stable", "branch/*", "beta", "beta/*"): + set_protected_branch(github_token, appid, branch) + + print(f"Adding {pr_author} to collaborators") + repo.add_to_collaborators(pr_author, permission="push") + + print("Add trusted maintainers to collaborators") + trusted_maintainers = org.get_team_by_slug("trusted-maintainers") + trusted_maintainers.update_team_repository(repo, "push") + + if repo.name.startswith("org.kde."): + print("Add KDE maintainers to collaborators") + kde_maintainers = org.get_team_by_slug("KDE") + kde_maintainers.update_team_repository(repo, "push") + + collaborators = {user.replace("@", "") for user in command.split()[1:]} + for user in collaborators: + print(f"adding {user} to collaborators") + repo.add_to_collaborators(user, permission="push") + + close_comment = ( + f"A repository for this submission has been created: {repo.html_url}", + "\n", + f"You will receive an invitation to be a collaborator which will grant you write access to the repository above. The invite can be also viewed [here]({repo.html_url}/invitations).", + "\n", + "If you have never maintained an application before, common questions are answered in [the app maintenance guide](https://github.com/flathub/flathub/wiki/App-Maintenance).", + "\n", + "Thanks!", + ) + + print("Closing the pull request") + pr.create_issue_comment("\n".join(close_comment)) + pr.edit(state="closed") + + +if __name__ == "__main__": + main() diff --git a/.github/actions/merge/requirements.in b/.github/actions/merge/requirements.in new file mode 100644 index 0000000..cc15727 --- /dev/null +++ b/.github/actions/merge/requirements.in @@ -0,0 +1,4 @@ +gql[requests] +pygit2 +PyGithub +PyYAML diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt new file mode 100644 index 0000000..3b4aef6 --- /dev/null +++ b/.github/actions/merge/requirements.txt @@ -0,0 +1,548 @@ +# +# This file is autogenerated by pip-compile with Python 3.11 +# by the following command: +# +# pip-compile --generate-hashes requirements.in +# +backoff==2.2.1 \ + --hash=sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba \ + --hash=sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8 + # via gql +certifi==2023.5.7 \ + --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \ + --hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716 + # via requests +cffi==1.15.1 \ + --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ + --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ + --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ + --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ + --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ + --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ + --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ + --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ + --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ + --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ + --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ + --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ + --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ + --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ + --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ + --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ + --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ + --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ + --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ + --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ + --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ + --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ + --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ + --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ + --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ + --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ + --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ + --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ + --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ + --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ + --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ + --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ + --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ + --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ + --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ + --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ + --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ + --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ + --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ + --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ + --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ + --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ + --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ + --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ + --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ + --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ + --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ + --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ + --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ + --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ + --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ + --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ + --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ + --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ + --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ + --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ + --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ + --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ + --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ + --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ + --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ + --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ + --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ + --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 + # via + # cryptography + # pygit2 + # pynacl +charset-normalizer==3.2.0 \ + --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ + --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ + --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ + --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ + --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ + --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ + --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ + --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ + --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ + --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ + --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ + --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ + --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ + --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ + --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ + --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ + --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ + --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ + --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ + --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ + --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ + --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ + --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ + --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ + --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ + --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ + --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ + --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ + --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ + --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ + --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ + --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ + --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ + --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ + --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ + --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ + --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ + --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ + --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ + --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ + --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ + --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ + --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ + --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ + --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ + --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ + --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ + --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ + --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ + --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ + --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ + --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ + --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ + --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ + --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ + --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ + --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ + --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ + --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ + --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ + --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ + --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ + --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ + --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ + --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ + --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ + --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ + --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ + --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ + --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ + --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ + --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ + --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ + --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ + --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa + # via requests +cryptography==41.0.2 \ + --hash=sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711 \ + --hash=sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7 \ + --hash=sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd \ + --hash=sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e \ + --hash=sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58 \ + --hash=sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0 \ + --hash=sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d \ + --hash=sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83 \ + --hash=sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831 \ + --hash=sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766 \ + --hash=sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b \ + --hash=sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c \ + --hash=sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182 \ + --hash=sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f \ + --hash=sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa \ + --hash=sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4 \ + --hash=sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a \ + --hash=sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2 \ + --hash=sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76 \ + --hash=sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5 \ + --hash=sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee \ + --hash=sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f \ + --hash=sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14 + # via pyjwt +deprecated==1.2.14 \ + --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ + --hash=sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3 + # via pygithub +gql[requests]==3.4.1 \ + --hash=sha256:11dc5d8715a827f2c2899593439a4f36449db4f0eafa5b1ea63948f8a2f8c545 \ + --hash=sha256:315624ca0f4d571ef149d455033ebd35e45c1a13f18a059596aeddcea99135cf + # via -r requirements.in +graphql-core==3.2.3 \ + --hash=sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676 \ + --hash=sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3 + # via gql +idna==3.4 \ + --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ + --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 + # via + # requests + # yarl +multidict==6.0.4 \ + --hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \ + --hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \ + --hash=sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03 \ + --hash=sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710 \ + --hash=sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161 \ + --hash=sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664 \ + --hash=sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569 \ + --hash=sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067 \ + --hash=sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313 \ + --hash=sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706 \ + --hash=sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2 \ + --hash=sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636 \ + --hash=sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49 \ + --hash=sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93 \ + --hash=sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603 \ + --hash=sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0 \ + --hash=sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60 \ + --hash=sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4 \ + --hash=sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e \ + --hash=sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1 \ + --hash=sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60 \ + --hash=sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951 \ + --hash=sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc \ + --hash=sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe \ + --hash=sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95 \ + --hash=sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d \ + --hash=sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8 \ + --hash=sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed \ + --hash=sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2 \ + --hash=sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775 \ + --hash=sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87 \ + --hash=sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c \ + --hash=sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2 \ + --hash=sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98 \ + --hash=sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3 \ + --hash=sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe \ + --hash=sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78 \ + --hash=sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660 \ + --hash=sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176 \ + --hash=sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e \ + --hash=sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988 \ + --hash=sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c \ + --hash=sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c \ + --hash=sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0 \ + --hash=sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449 \ + --hash=sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f \ + --hash=sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde \ + --hash=sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5 \ + --hash=sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d \ + --hash=sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac \ + --hash=sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a \ + --hash=sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9 \ + --hash=sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca \ + --hash=sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11 \ + --hash=sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35 \ + --hash=sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063 \ + --hash=sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b \ + --hash=sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982 \ + --hash=sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258 \ + --hash=sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1 \ + --hash=sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52 \ + --hash=sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480 \ + --hash=sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7 \ + --hash=sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461 \ + --hash=sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d \ + --hash=sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc \ + --hash=sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779 \ + --hash=sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a \ + --hash=sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547 \ + --hash=sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0 \ + --hash=sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171 \ + --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ + --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ + --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba + # via yarl +pycparser==2.21 \ + --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ + --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 + # via cffi +pygit2==1.12.2 \ + --hash=sha256:14ae27491347a0ac4bbe8347b09d752cfe7fea1121c14525415e0cca6db4a836 \ + --hash=sha256:214bd214784fcbef7a8494d1d59e0cd3a731c0d24ce0f230dcc843322ee33b08 \ + --hash=sha256:22e7f3ad2b7b0c80be991bb47d8a2f2535cc9bf090746eb8679231ee565fde81 \ + --hash=sha256:25a6548930328c5247bfb7c67d29104e63b036cb5390f032d9f91f63efb70434 \ + --hash=sha256:336c864ac961e7be8ba06e9ed8c999e4f624a8ccd90121cc4e40956d8b57acac \ + --hash=sha256:546091316c9a8c37b9867ddcc6c9f7402ca4d0b9db3f349212a7b5e71988e359 \ + --hash=sha256:56e85d0e66de957d599d1efb2409d39afeefd8f01009bfda0796b42a4b678358 \ + --hash=sha256:5b3ab4d6302990f7adb2b015bcbda1f0715277008d0c66440497e6f8313bf9cb \ + --hash=sha256:5c1e26649e1540b6a774f812e2fc9890320ff4d33f16db1bb02626318b5ceae2 \ + --hash=sha256:5f65483ab5e3563c58f60debe2acc0979fdf6fd633432fcfbddf727a9a265ba4 \ + --hash=sha256:685378852ef8eb081333bc80dbdfc4f1333cf4a8f3baf614c4135e02ad1ee38a \ + --hash=sha256:6a4083ba093c69142e0400114a4ef75e87834637d2bbfd77b964614bf70f624f \ + --hash=sha256:79fbd99d3e08ca7478150eeba28ca4d4103f564148eab8d00aba8f1e6fc60654 \ + --hash=sha256:7bb30ab1fdaa4c30821fed33892958b6d92d50dbd03c76f7775b4e5d62f53a2e \ + --hash=sha256:857c5cde635d470f58803d67bfb281dc4f6336065a0253bfbed001f18e2d0767 \ + --hash=sha256:8bf14196cbfffbcd286f459a1d4fc660c5d5dfa8fb422e21216961df575410d6 \ + --hash=sha256:8da8517809635ea3da950d9cf99c6d1851352d92b6db309382db88a01c3b0bfd \ + --hash=sha256:8f443d3641762b2bb9c76400bb18beb4ba27dd35bc098a8bfae82e6a190c52ab \ + --hash=sha256:926f2e48c4eaa179249d417b8382290b86b0f01dbf41d289f763576209276b9f \ + --hash=sha256:a365ffca23d910381749fdbcc367db52fe808f9aa4852914dd9ef8b711384a32 \ + --hash=sha256:ac2b5f408eb882e79645ebb43039ac37739c3edd25d857cc97d7482a684b613f \ + --hash=sha256:b9c2359b99eed8e7fac30c06e6b4ae277a6a0537d6b4b88a190828c3d7eb9ef2 \ + --hash=sha256:be3bb0139f464947523022a5af343a2e862c4ff250a57ec9f631449e7c0ba7c0 \ + --hash=sha256:c74e7601cb8b8dc3d02fd32274e200a7761cffd20ee531442bf1fa115c8f99a5 \ + --hash=sha256:cdf655e5f801990f5cad721b6ccbe7610962f0a4f1c20373dbf9c0be39374a81 \ + --hash=sha256:e7e705aaecad85b883022e81e054fbd27d26023fc031618ee61c51516580517e \ + --hash=sha256:ec04c27be5d5af1ceecdcc0464e07081222f91f285f156dc53b23751d146569a \ + --hash=sha256:f4df3e5745fdf3111a6ccc905eae99f22f1a180728f714795138ca540cc2a50a \ + --hash=sha256:f8f813d35d836c5b0d1962c387754786bcc7f1c3c8e11207b9eeb30238ac4cc7 \ + --hash=sha256:fb9eb57b75ce586928053692a25aae2a50fef3ad36661c57c07d4902899b1df3 \ + --hash=sha256:fe35a72af61961dbb7fb4abcdaa36d5f1c85b2cd3daae94137eeb9c07215cdd3 + # via -r requirements.in +pygithub==1.59.0 \ + --hash=sha256:126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e \ + --hash=sha256:6e05ff49bac3caa7d1d6177a10c6e55a3e20c85b92424cc198571fd0cf786690 + # via -r requirements.in +pyjwt[crypto]==2.7.0 \ + --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \ + --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074 + # via pygithub +pynacl==1.5.0 \ + --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ + --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ + --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ + --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ + --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ + --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ + --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ + --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ + --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ + --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 + # via pygithub +pyyaml==6.0 \ + --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ + --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ + --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ + --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ + --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ + --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ + --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ + --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ + --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ + --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ + --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ + --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ + --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ + --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ + --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ + --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ + --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ + --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ + --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ + --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ + --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ + --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ + --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ + --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ + --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ + --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ + --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ + --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ + --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ + --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ + --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ + --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ + --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ + --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ + --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ + --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ + --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ + --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ + --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ + --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 + # via -r requirements.in +requests==2.31.0 \ + --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ + --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 + # via + # gql + # pygithub + # requests-toolbelt +requests-toolbelt==0.10.1 \ + --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ + --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d + # via gql +urllib3==1.26.16 \ + --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ + --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 + # via + # gql + # requests +wrapt==1.15.0 \ + --hash=sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0 \ + --hash=sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420 \ + --hash=sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a \ + --hash=sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c \ + --hash=sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079 \ + --hash=sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923 \ + --hash=sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f \ + --hash=sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1 \ + --hash=sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8 \ + --hash=sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86 \ + --hash=sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0 \ + --hash=sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364 \ + --hash=sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e \ + --hash=sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c \ + --hash=sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e \ + --hash=sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c \ + --hash=sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727 \ + --hash=sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff \ + --hash=sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e \ + --hash=sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29 \ + --hash=sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7 \ + --hash=sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72 \ + --hash=sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475 \ + --hash=sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a \ + --hash=sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317 \ + --hash=sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2 \ + --hash=sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd \ + --hash=sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640 \ + --hash=sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98 \ + --hash=sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248 \ + --hash=sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e \ + --hash=sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d \ + --hash=sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec \ + --hash=sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1 \ + --hash=sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e \ + --hash=sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9 \ + --hash=sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92 \ + --hash=sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb \ + --hash=sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094 \ + --hash=sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46 \ + --hash=sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29 \ + --hash=sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd \ + --hash=sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705 \ + --hash=sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8 \ + --hash=sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975 \ + --hash=sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb \ + --hash=sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e \ + --hash=sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b \ + --hash=sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418 \ + --hash=sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019 \ + --hash=sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1 \ + --hash=sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba \ + --hash=sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6 \ + --hash=sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2 \ + --hash=sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3 \ + --hash=sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7 \ + --hash=sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752 \ + --hash=sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416 \ + --hash=sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f \ + --hash=sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1 \ + --hash=sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc \ + --hash=sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145 \ + --hash=sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee \ + --hash=sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a \ + --hash=sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7 \ + --hash=sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b \ + --hash=sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653 \ + --hash=sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0 \ + --hash=sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90 \ + --hash=sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29 \ + --hash=sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6 \ + --hash=sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034 \ + --hash=sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09 \ + --hash=sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559 \ + --hash=sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639 + # via deprecated +yarl==1.9.2 \ + --hash=sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571 \ + --hash=sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3 \ + --hash=sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3 \ + --hash=sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c \ + --hash=sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7 \ + --hash=sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04 \ + --hash=sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191 \ + --hash=sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea \ + --hash=sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4 \ + --hash=sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4 \ + --hash=sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095 \ + --hash=sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e \ + --hash=sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74 \ + --hash=sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef \ + --hash=sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33 \ + --hash=sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde \ + --hash=sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45 \ + --hash=sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf \ + --hash=sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b \ + --hash=sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac \ + --hash=sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0 \ + --hash=sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528 \ + --hash=sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716 \ + --hash=sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb \ + --hash=sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18 \ + --hash=sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72 \ + --hash=sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6 \ + --hash=sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582 \ + --hash=sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5 \ + --hash=sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368 \ + --hash=sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc \ + --hash=sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9 \ + --hash=sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be \ + --hash=sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a \ + --hash=sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80 \ + --hash=sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8 \ + --hash=sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6 \ + --hash=sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417 \ + --hash=sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574 \ + --hash=sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59 \ + --hash=sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608 \ + --hash=sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82 \ + --hash=sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1 \ + --hash=sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3 \ + --hash=sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d \ + --hash=sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8 \ + --hash=sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc \ + --hash=sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac \ + --hash=sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8 \ + --hash=sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955 \ + --hash=sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0 \ + --hash=sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367 \ + --hash=sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb \ + --hash=sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a \ + --hash=sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623 \ + --hash=sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2 \ + --hash=sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6 \ + --hash=sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7 \ + --hash=sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4 \ + --hash=sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051 \ + --hash=sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938 \ + --hash=sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8 \ + --hash=sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9 \ + --hash=sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3 \ + --hash=sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5 \ + --hash=sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9 \ + --hash=sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333 \ + --hash=sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185 \ + --hash=sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3 \ + --hash=sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560 \ + --hash=sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b \ + --hash=sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7 \ + --hash=sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78 \ + --hash=sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7 + # via gql From 7c28a5f4ee654ff99d61b773645780e11cbf23a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Wed, 3 Jan 2024 19:16:56 +0100 Subject: [PATCH 048/319] external-data-checker: Run actions/checkout to reference the local action --- .github/workflows/external-data-checker.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 7acf179..4b77eff 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -7,6 +7,8 @@ jobs: flathub-data-checker-global: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v3 + - uses: ./.github/actions/flatpak-external-data-checker env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 1cdf1e6bd1914758d229284b4bf04773e75fda5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:31:51 +0000 Subject: [PATCH 049/319] Bump urllib3 from 1.26.16 to 1.26.18 in /.github/actions/merge Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.16 to 1.26.18. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/1.26.16...1.26.18) --- updated-dependencies: - dependency-name: urllib3 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 3b4aef6..9c3f1d7 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -321,7 +321,9 @@ pygithub==1.59.0 \ pyjwt[crypto]==2.7.0 \ --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \ --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074 - # via pygithub + # via + # pygithub + # pyjwt pynacl==1.5.0 \ --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ @@ -387,9 +389,9 @@ requests-toolbelt==0.10.1 \ --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d # via gql -urllib3==1.26.16 \ - --hash=sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f \ - --hash=sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14 +urllib3==1.26.18 \ + --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \ + --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0 # via # gql # requests From 69920fd21b846f8c9b79303425e54f6c83f72d81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:32:03 +0000 Subject: [PATCH 050/319] Bump certifi from 2023.5.7 to 2023.7.22 in /.github/actions/merge Bumps [certifi](https://github.com/certifi/python-certifi) from 2023.5.7 to 2023.7.22. - [Commits](https://github.com/certifi/python-certifi/compare/2023.05.07...2023.07.22) --- updated-dependencies: - dependency-name: certifi dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 9c3f1d7..db9c068 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -8,9 +8,9 @@ backoff==2.2.1 \ --hash=sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba \ --hash=sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8 # via gql -certifi==2023.5.7 \ - --hash=sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7 \ - --hash=sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716 +certifi==2023.7.22 \ + --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ + --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 # via requests cffi==1.15.1 \ --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ From f7ce425f105b30bef5b338c304dac824704e0491 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Jan 2024 15:32:22 +0000 Subject: [PATCH 051/319] Bump cryptography from 41.0.2 to 41.0.6 in /.github/actions/merge Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.2 to 41.0.6. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.2...41.0.6) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 48 +++++++++++++------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index db9c068..6cc6b38 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -158,30 +158,30 @@ charset-normalizer==3.2.0 \ --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa # via requests -cryptography==41.0.2 \ - --hash=sha256:01f1d9e537f9a15b037d5d9ee442b8c22e3ae11ce65ea1f3316a41c78756b711 \ - --hash=sha256:079347de771f9282fbfe0e0236c716686950c19dee1b76240ab09ce1624d76d7 \ - --hash=sha256:182be4171f9332b6741ee818ec27daff9fb00349f706629f5cbf417bd50e66fd \ - --hash=sha256:192255f539d7a89f2102d07d7375b1e0a81f7478925b3bc2e0549ebf739dae0e \ - --hash=sha256:2a034bf7d9ca894720f2ec1d8b7b5832d7e363571828037f9e0c4f18c1b58a58 \ - --hash=sha256:342f3767e25876751e14f8459ad85e77e660537ca0a066e10e75df9c9e9099f0 \ - --hash=sha256:439c3cc4c0d42fa999b83ded80a9a1fb54d53c58d6e59234cfe97f241e6c781d \ - --hash=sha256:49c3222bb8f8e800aead2e376cbef687bc9e3cb9b58b29a261210456a7783d83 \ - --hash=sha256:674b669d5daa64206c38e507808aae49904c988fa0a71c935e7006a3e1e83831 \ - --hash=sha256:7a9a3bced53b7f09da251685224d6a260c3cb291768f54954e28f03ef14e3766 \ - --hash=sha256:7af244b012711a26196450d34f483357e42aeddb04128885d95a69bd8b14b69b \ - --hash=sha256:7d230bf856164de164ecb615ccc14c7fc6de6906ddd5b491f3af90d3514c925c \ - --hash=sha256:84609ade00a6ec59a89729e87a503c6e36af98ddcd566d5f3be52e29ba993182 \ - --hash=sha256:9a6673c1828db6270b76b22cc696f40cde9043eb90373da5c2f8f2158957f42f \ - --hash=sha256:9b6d717393dbae53d4e52684ef4f022444fc1cce3c48c38cb74fca29e1f08eaa \ - --hash=sha256:9c3fe6534d59d071ee82081ca3d71eed3210f76ebd0361798c74abc2bcf347d4 \ - --hash=sha256:a719399b99377b218dac6cf547b6ec54e6ef20207b6165126a280b0ce97e0d2a \ - --hash=sha256:b332cba64d99a70c1e0836902720887fb4529ea49ea7f5462cf6640e095e11d2 \ - --hash=sha256:d124682c7a23c9764e54ca9ab5b308b14b18eba02722b8659fb238546de83a76 \ - --hash=sha256:d73f419a56d74fef257955f51b18d046f3506270a5fd2ac5febbfa259d6c0fa5 \ - --hash=sha256:f0dc40e6f7aa37af01aba07277d3d64d5a03dc66d682097541ec4da03cc140ee \ - --hash=sha256:f14ad275364c8b4e525d018f6716537ae7b6d369c094805cae45300847e0894f \ - --hash=sha256:f772610fe364372de33d76edcd313636a25684edb94cee53fd790195f5989d14 +cryptography==41.0.6 \ + --hash=sha256:068bc551698c234742c40049e46840843f3d98ad7ce265fd2bd4ec0d11306596 \ + --hash=sha256:0f27acb55a4e77b9be8d550d762b0513ef3fc658cd3eb15110ebbcbd626db12c \ + --hash=sha256:2132d5865eea673fe6712c2ed5fb4fa49dba10768bb4cc798345748380ee3660 \ + --hash=sha256:3288acccef021e3c3c10d58933f44e8602cf04dba96d9796d70d537bb2f4bbc4 \ + --hash=sha256:35f3f288e83c3f6f10752467c48919a7a94b7d88cc00b0668372a0d2ad4f8ead \ + --hash=sha256:398ae1fc711b5eb78e977daa3cbf47cec20f2c08c5da129b7a296055fbb22aed \ + --hash=sha256:422e3e31d63743855e43e5a6fcc8b4acab860f560f9321b0ee6269cc7ed70cc3 \ + --hash=sha256:48783b7e2bef51224020efb61b42704207dde583d7e371ef8fc2a5fb6c0aabc7 \ + --hash=sha256:4d03186af98b1c01a4eda396b137f29e4e3fb0173e30f885e27acec8823c1b09 \ + --hash=sha256:5daeb18e7886a358064a68dbcaf441c036cbdb7da52ae744e7b9207b04d3908c \ + --hash=sha256:60e746b11b937911dc70d164060d28d273e31853bb359e2b2033c9e93e6f3c43 \ + --hash=sha256:742ae5e9a2310e9dade7932f9576606836ed174da3c7d26bc3d3ab4bd49b9f65 \ + --hash=sha256:7e00fb556bda398b99b0da289ce7053639d33b572847181d6483ad89835115f6 \ + --hash=sha256:85abd057699b98fce40b41737afb234fef05c67e116f6f3650782c10862c43da \ + --hash=sha256:8efb2af8d4ba9dbc9c9dd8f04d19a7abb5b49eab1f3694e7b5a16a5fc2856f5c \ + --hash=sha256:ae236bb8760c1e55b7a39b6d4d32d2279bc6c7c8500b7d5a13b6fb9fc97be35b \ + --hash=sha256:afda76d84b053923c27ede5edc1ed7d53e3c9f475ebaf63c68e69f1403c405a8 \ + --hash=sha256:b27a7fd4229abef715e064269d98a7e2909ebf92eb6912a9603c7e14c181928c \ + --hash=sha256:b648fe2a45e426aaee684ddca2632f62ec4613ef362f4d681a9a6283d10e079d \ + --hash=sha256:c5a550dc7a3b50b116323e3d376241829fd326ac47bc195e04eb33a8170902a9 \ + --hash=sha256:da46e2b5df770070412c46f87bac0849b8d685c5f2679771de277a422c7d0b86 \ + --hash=sha256:f39812f70fc5c71a15aa3c97b2bbe213c3f2a460b79bd21c40d033bb34a9bf36 \ + --hash=sha256:ff369dd19e8fe0528b02e8df9f2aeb2479f89b1270d90f96a63500afe9af5cae # via pyjwt deprecated==1.2.14 \ --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ From 1d625b1311fc0a7d7a95308a43acc2b661931f0a Mon Sep 17 00:00:00 2001 From: JakobDev Date: Tue, 9 Jan 2024 14:08:07 +0100 Subject: [PATCH 052/319] Update Website Link (#4846) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 157c42b..0faf88c 100644 --- a/README.md +++ b/README.md @@ -24,4 +24,4 @@ Contributing to Flathub For information on creating packages or reporting issues please see the [contributing page](/CONTRIBUTING.md). -***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub/website* +***Note:*** *this repository is not for reporting issues related to the flathub.org website itself or contributing to its development. For that, go to https://github.com/flathub-infra/website* From fb1205ef343c4baca954f40894a514e3b28657f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Figui=C3=A8re?= Date: Thu, 11 Jan 2024 17:14:04 -0500 Subject: [PATCH 053/319] PR template: clarify the domain requirements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hubert Figuière --- .github/pull_request_template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3f76991..f017fb6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,10 +6,11 @@ - [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* - [ ] All assets referenced in the manifest are redistributable by any party. If not, the unredistributable parts are using an extra-data source type. - [ ] I am an upstream contributor to the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** -- [ ] I own the domain used in the application ID or the domain has a policy for delegating subdomains (e.g. GitHub, SourceForge). +- [ ] The domain used for the application ID is controlled by the application developers either directly or through the code hosting (e.g. GitHub, GitLab, SourceForge, etc.). The [application id guidelines][app-id] are followed. - [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [maint]: https://docs.flathub.org/docs/for-app-authors/maintanance [submission]: https://docs.flathub.org/docs/for-app-authors/submission [build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission +[app-id]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id From cbb99f14e53aec8474fdc4c5428a9d65848afec3 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Mon, 29 Jan 2024 11:39:50 -0700 Subject: [PATCH 054/319] Merge action: update maintenance guide URL Rather than linking to the wiki, which links to the docs --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 00a9654..10479ac 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -233,7 +233,7 @@ def main(): "\n", f"You will receive an invitation to be a collaborator which will grant you write access to the repository above. The invite can be also viewed [here]({repo.html_url}/invitations).", "\n", - "If you have never maintained an application before, common questions are answered in [the app maintenance guide](https://github.com/flathub/flathub/wiki/App-Maintenance).", + "If you have never maintained an application before, common questions are answered in [the app maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/).", "\n", "Thanks!", ) From 03ea87d5d904fae1ffb7b2fd5f3f2c83d2d5be7e Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Mon, 29 Jan 2024 11:55:50 -0700 Subject: [PATCH 055/319] Merge action: Mention verification Follow-up to https://github.com/flathub/flathub/pull/4900/ Mention verifying your app as the next step. --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 10479ac..7272473 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -233,7 +233,7 @@ def main(): "\n", f"You will receive an invitation to be a collaborator which will grant you write access to the repository above. The invite can be also viewed [here]({repo.html_url}/invitations).", "\n", - "If you have never maintained an application before, common questions are answered in [the app maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/).", + "If you've never maintained an app on Flathub before, common questions are answered in the [app maintenance guide](https://github.com/flathub/flathub/wiki/App-Maintenance). If you're the original developer (or an authorized party), [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) next to let users know it's coming from you.", "\n", "Thanks!", ) From 300dae32e5f394272ec14481071f327ea7ce9243 Mon Sep 17 00:00:00 2001 From: Cassidy James Blaede Date: Mon, 29 Jan 2024 12:32:00 -0700 Subject: [PATCH 056/319] Merge action: correct maintenance guide URL --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 7272473..d30cb7a 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -233,7 +233,7 @@ def main(): "\n", f"You will receive an invitation to be a collaborator which will grant you write access to the repository above. The invite can be also viewed [here]({repo.html_url}/invitations).", "\n", - "If you've never maintained an app on Flathub before, common questions are answered in the [app maintenance guide](https://github.com/flathub/flathub/wiki/App-Maintenance). If you're the original developer (or an authorized party), [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) next to let users know it's coming from you.", + "If you've never maintained an app on Flathub before, common questions are answered in the [app maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/). If you're the original developer (or an authorized party), [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) next to let users know it's coming from you.", "\n", "Thanks!", ) From d2bbeaa8d4927f8f6c10a1691c25597907539e36 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 21 Feb 2024 21:05:39 +0530 Subject: [PATCH 057/319] Improve the PR template - Add info on how to mark items as done - Add author/developer too to the "upstream contributor" contact line - Add section to describe --- .github/pull_request_template.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f017fb6..a6f47c0 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,15 @@ ### Please confirm your submission meets all the criteria + + +Please describe your application briefly below. + - [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. - [ ] My pull request follows the instructions at [App Submission][submission]. - [ ] I have [built][build] and tested the submission locally. - [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* - [ ] All assets referenced in the manifest are redistributable by any party. If not, the unredistributable parts are using an extra-data source type. -- [ ] I am an upstream contributor to the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** +- [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** - [ ] The domain used for the application ID is controlled by the application developers either directly or through the code hosting (e.g. GitHub, GitLab, SourceForge, etc.). The [application id guidelines][app-id] are followed. - [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* From 9582b3bf42daaab3072444e9b0bb9f13071dae59 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 13 Mar 2024 08:12:48 +0530 Subject: [PATCH 058/319] Add a note for proper submission branch --- .github/pull_request_template.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index a6f47c0..0b3411e 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,3 +1,5 @@ + + ### Please confirm your submission meets all the criteria From 0a6b7c0526653e28891c37af4a1c85aa68612994 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 13 Mar 2024 08:22:05 +0530 Subject: [PATCH 059/319] Turn description into a checklist item --- .github/pull_request_template.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 0b3411e..25be108 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,8 +4,7 @@ -Please describe your application briefly below. - +- [ ] Please describe your application briefly. - [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. - [ ] My pull request follows the instructions at [App Submission][submission]. - [ ] I have [built][build] and tested the submission locally. From e747003065b28b019a7cb9b579b4b9a5d37640d1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 30 Mar 2024 22:50:58 +0530 Subject: [PATCH 060/319] CONTRIBUTING.md: Update links to docs sites of Flathub and Flatpak --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2d90f4..1bfec7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ ### Submitting a new package -If you are submitting a new package please read the [app submission](https://github.com/flathub/flathub/wiki/App-Submission) and [app requirements](https://github.com/flathub/flathub/wiki/App-Requirements) pages in the wiki. +If you are submitting a new package please read the [app requirements](https://docs.flathub.org/docs/for-app-authors/requirements) and [app submission](https://docs.flathub.org/docs/for-app-authors/submission) pages. Also double-check that your PR is against the `new-pr` branch. @@ -11,5 +11,5 @@ Please open bugs for packages on their respective repositories you can search fo ### Requesting a new package Please do not open issues requesting packages. As long as a package meets the guidelines above and works it will -generally be accepted. If you want to create a Flatpak see the [documentation](https://flatpak.readthedocs.io/en/latest/) +generally be accepted. If you want to create a Flatpak see the [documentation](https://docs.flatpak.org/) or join [#flatpak:matrix.org](https://matrix.to/#/#flatpak:matrix.org) for help. From 7af4fca2117600739c7c755485dadb3e93c2ff51 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 5 May 2024 07:36:25 +0530 Subject: [PATCH 061/319] Add action to build merge docker image --- .github/workflows/build-merge.yml | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/build-merge.yml diff --git a/.github/workflows/build-merge.yml b/.github/workflows/build-merge.yml new file mode 100644 index 0000000..6de14b0 --- /dev/null +++ b/.github/workflows/build-merge.yml @@ -0,0 +1,37 @@ +name: build-merge + +on: + push: + branches: master + paths: + - ".github/actions/merge/*" + - .github/workflows/merge.yml + - .github/workflows/build-merge.yml + workflow_dispatch: + +jobs: + docker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + id: docker_build + uses: docker/build-push-action@v5 + with: + context: .github/actions/merge + file: .github/actions/merge/Dockerfile + tags: ghcr.io/flathub/actions/merge:latest + push: true + cache-from: type=gha + cache-to: type=gha,mode=max From 2d68de1c02e02322cc210fc02031fa484edb9b96 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 03:39:01 +0000 Subject: [PATCH 062/319] Bump idna from 3.4 to 3.7 in /.github/actions/merge Bumps [idna](https://github.com/kjd/idna) from 3.4 to 3.7. - [Release notes](https://github.com/kjd/idna/releases) - [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst) - [Commits](https://github.com/kjd/idna/compare/v3.4...v3.7) --- updated-dependencies: - dependency-name: idna dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 6cc6b38..6f80cbf 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -195,9 +195,9 @@ graphql-core==3.2.3 \ --hash=sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676 \ --hash=sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3 # via gql -idna==3.4 \ - --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \ - --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2 +idna==3.7 \ + --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ + --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 # via # requests # yarl @@ -321,9 +321,7 @@ pygithub==1.59.0 \ pyjwt[crypto]==2.7.0 \ --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \ --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074 - # via - # pygithub - # pyjwt + # via pygithub pynacl==1.5.0 \ --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ From b23e04c6714cc6c6a1fed0d1e31bd4c0b4a796a6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Feb 2024 20:16:34 +0000 Subject: [PATCH 063/319] Bump cryptography from 41.0.6 to 42.0.4 in /.github/actions/merge Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.6 to 42.0.4. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/41.0.6...42.0.4) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 57 +++++++++++++++----------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 6f80cbf..5854b29 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -158,30 +158,39 @@ charset-normalizer==3.2.0 \ --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa # via requests -cryptography==41.0.6 \ - --hash=sha256:068bc551698c234742c40049e46840843f3d98ad7ce265fd2bd4ec0d11306596 \ - --hash=sha256:0f27acb55a4e77b9be8d550d762b0513ef3fc658cd3eb15110ebbcbd626db12c \ - --hash=sha256:2132d5865eea673fe6712c2ed5fb4fa49dba10768bb4cc798345748380ee3660 \ - --hash=sha256:3288acccef021e3c3c10d58933f44e8602cf04dba96d9796d70d537bb2f4bbc4 \ - --hash=sha256:35f3f288e83c3f6f10752467c48919a7a94b7d88cc00b0668372a0d2ad4f8ead \ - --hash=sha256:398ae1fc711b5eb78e977daa3cbf47cec20f2c08c5da129b7a296055fbb22aed \ - --hash=sha256:422e3e31d63743855e43e5a6fcc8b4acab860f560f9321b0ee6269cc7ed70cc3 \ - --hash=sha256:48783b7e2bef51224020efb61b42704207dde583d7e371ef8fc2a5fb6c0aabc7 \ - --hash=sha256:4d03186af98b1c01a4eda396b137f29e4e3fb0173e30f885e27acec8823c1b09 \ - --hash=sha256:5daeb18e7886a358064a68dbcaf441c036cbdb7da52ae744e7b9207b04d3908c \ - --hash=sha256:60e746b11b937911dc70d164060d28d273e31853bb359e2b2033c9e93e6f3c43 \ - --hash=sha256:742ae5e9a2310e9dade7932f9576606836ed174da3c7d26bc3d3ab4bd49b9f65 \ - --hash=sha256:7e00fb556bda398b99b0da289ce7053639d33b572847181d6483ad89835115f6 \ - --hash=sha256:85abd057699b98fce40b41737afb234fef05c67e116f6f3650782c10862c43da \ - --hash=sha256:8efb2af8d4ba9dbc9c9dd8f04d19a7abb5b49eab1f3694e7b5a16a5fc2856f5c \ - --hash=sha256:ae236bb8760c1e55b7a39b6d4d32d2279bc6c7c8500b7d5a13b6fb9fc97be35b \ - --hash=sha256:afda76d84b053923c27ede5edc1ed7d53e3c9f475ebaf63c68e69f1403c405a8 \ - --hash=sha256:b27a7fd4229abef715e064269d98a7e2909ebf92eb6912a9603c7e14c181928c \ - --hash=sha256:b648fe2a45e426aaee684ddca2632f62ec4613ef362f4d681a9a6283d10e079d \ - --hash=sha256:c5a550dc7a3b50b116323e3d376241829fd326ac47bc195e04eb33a8170902a9 \ - --hash=sha256:da46e2b5df770070412c46f87bac0849b8d685c5f2679771de277a422c7d0b86 \ - --hash=sha256:f39812f70fc5c71a15aa3c97b2bbe213c3f2a460b79bd21c40d033bb34a9bf36 \ - --hash=sha256:ff369dd19e8fe0528b02e8df9f2aeb2479f89b1270d90f96a63500afe9af5cae +cryptography==42.0.4 \ + --hash=sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b \ + --hash=sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce \ + --hash=sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88 \ + --hash=sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7 \ + --hash=sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20 \ + --hash=sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9 \ + --hash=sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff \ + --hash=sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1 \ + --hash=sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764 \ + --hash=sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b \ + --hash=sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298 \ + --hash=sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1 \ + --hash=sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824 \ + --hash=sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257 \ + --hash=sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a \ + --hash=sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129 \ + --hash=sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb \ + --hash=sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929 \ + --hash=sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854 \ + --hash=sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52 \ + --hash=sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923 \ + --hash=sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885 \ + --hash=sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0 \ + --hash=sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd \ + --hash=sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2 \ + --hash=sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18 \ + --hash=sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b \ + --hash=sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992 \ + --hash=sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74 \ + --hash=sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660 \ + --hash=sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925 \ + --hash=sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449 # via pyjwt deprecated==1.2.14 \ --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ From 934779c6f94505c67b1f2d867a35a9bff7966d41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 07:16:14 +0000 Subject: [PATCH 064/319] --- updated-dependencies: - dependency-name: requests dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 5854b29..32c5226 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -385,9 +385,9 @@ pyyaml==6.0 \ --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 # via -r requirements.in -requests==2.31.0 \ - --hash=sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f \ - --hash=sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1 +requests==2.32.0 \ + --hash=sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5 \ + --hash=sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8 # via # gql # pygithub From 66fdbc8c5645ce98fd48b5d0b52fe6d50d2daf33 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 16 Jun 2024 18:37:20 +0530 Subject: [PATCH 065/319] merge: Add a note to follow blog We are announcing changes there --- .github/actions/merge/entrypoint.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index d30cb7a..11d416d 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -235,6 +235,8 @@ def main(): "\n", "If you've never maintained an app on Flathub before, common questions are answered in the [app maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/). If you're the original developer (or an authorized party), [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) next to let users know it's coming from you.", "\n", + "Please follow the [Flathub blog](https://docs.flathub.org/blog) for the latest announcements.", + "\n", "Thanks!", ) From 356942a3c5f01ef5cdb483b94fa70c196d683036 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 16 Jun 2024 18:47:51 +0530 Subject: [PATCH 066/319] merge: Don't error on incorrect usernames Github webui allows teams to be at-ed too, but add_to_collaborators accepts Github usersnames only https://pygithub.readthedocs.io/en/latest/github_objects/Repository.html?highlight=add_to_collaborators#github.Repository.Repository.add_to_collaborators So we should not error on wrong usernames being @-ed. --- .github/actions/merge/entrypoint.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 11d416d..71de188 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -225,8 +225,12 @@ def main(): collaborators = {user.replace("@", "") for user in command.split()[1:]} for user in collaborators: - print(f"adding {user} to collaborators") - repo.add_to_collaborators(user, permission="push") + try: + print(f"adding {user} to collaborators") + repo.add_to_collaborators(user, permission="push") + except github.GithubException: + print(f"Adding {user} failed") + pass close_comment = ( f"A repository for this submission has been created: {repo.html_url}", From c85708d5f8333514667e2359a365421b81bfb71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Mon, 17 Jun 2024 16:03:37 +0200 Subject: [PATCH 067/319] merge: Add pygobject to requirements --- .github/actions/merge/requirements.in | 1 + .github/actions/merge/requirements.txt | 560 ++----------------------- 2 files changed, 38 insertions(+), 523 deletions(-) diff --git a/.github/actions/merge/requirements.in b/.github/actions/merge/requirements.in index cc15727..b4a7ffa 100644 --- a/.github/actions/merge/requirements.in +++ b/.github/actions/merge/requirements.in @@ -2,3 +2,4 @@ gql[requests] pygit2 PyGithub PyYAML +PyGobject diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 32c5226..c1861cd 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -2,556 +2,70 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --generate-hashes requirements.in +# pip-compile requirements.in # -backoff==2.2.1 \ - --hash=sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba \ - --hash=sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8 +anyio==4.4.0 # via gql -certifi==2023.7.22 \ - --hash=sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082 \ - --hash=sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9 +backoff==2.2.1 + # via gql +certifi==2024.6.2 # via requests -cffi==1.15.1 \ - --hash=sha256:00a9ed42e88df81ffae7a8ab6d9356b371399b91dbdf0c3cb1e84c03a13aceb5 \ - --hash=sha256:03425bdae262c76aad70202debd780501fabeaca237cdfddc008987c0e0f59ef \ - --hash=sha256:04ed324bda3cda42b9b695d51bb7d54b680b9719cfab04227cdd1e04e5de3104 \ - --hash=sha256:0e2642fe3142e4cc4af0799748233ad6da94c62a8bec3a6648bf8ee68b1c7426 \ - --hash=sha256:173379135477dc8cac4bc58f45db08ab45d228b3363adb7af79436135d028405 \ - --hash=sha256:198caafb44239b60e252492445da556afafc7d1e3ab7a1fb3f0584ef6d742375 \ - --hash=sha256:1e74c6b51a9ed6589199c787bf5f9875612ca4a8a0785fb2d4a84429badaf22a \ - --hash=sha256:2012c72d854c2d03e45d06ae57f40d78e5770d252f195b93f581acf3ba44496e \ - --hash=sha256:21157295583fe8943475029ed5abdcf71eb3911894724e360acff1d61c1d54bc \ - --hash=sha256:2470043b93ff09bf8fb1d46d1cb756ce6132c54826661a32d4e4d132e1977adf \ - --hash=sha256:285d29981935eb726a4399badae8f0ffdff4f5050eaa6d0cfc3f64b857b77185 \ - --hash=sha256:30d78fbc8ebf9c92c9b7823ee18eb92f2e6ef79b45ac84db507f52fbe3ec4497 \ - --hash=sha256:320dab6e7cb2eacdf0e658569d2575c4dad258c0fcc794f46215e1e39f90f2c3 \ - --hash=sha256:33ab79603146aace82c2427da5ca6e58f2b3f2fb5da893ceac0c42218a40be35 \ - --hash=sha256:3548db281cd7d2561c9ad9984681c95f7b0e38881201e157833a2342c30d5e8c \ - --hash=sha256:3799aecf2e17cf585d977b780ce79ff0dc9b78d799fc694221ce814c2c19db83 \ - --hash=sha256:39d39875251ca8f612b6f33e6b1195af86d1b3e60086068be9cc053aa4376e21 \ - --hash=sha256:3b926aa83d1edb5aa5b427b4053dc420ec295a08e40911296b9eb1b6170f6cca \ - --hash=sha256:3bcde07039e586f91b45c88f8583ea7cf7a0770df3a1649627bf598332cb6984 \ - --hash=sha256:3d08afd128ddaa624a48cf2b859afef385b720bb4b43df214f85616922e6a5ac \ - --hash=sha256:3eb6971dcff08619f8d91607cfc726518b6fa2a9eba42856be181c6d0d9515fd \ - --hash=sha256:40f4774f5a9d4f5e344f31a32b5096977b5d48560c5592e2f3d2c4374bd543ee \ - --hash=sha256:4289fc34b2f5316fbb762d75362931e351941fa95fa18789191b33fc4cf9504a \ - --hash=sha256:470c103ae716238bbe698d67ad020e1db9d9dba34fa5a899b5e21577e6d52ed2 \ - --hash=sha256:4f2c9f67e9821cad2e5f480bc8d83b8742896f1242dba247911072d4fa94c192 \ - --hash=sha256:50a74364d85fd319352182ef59c5c790484a336f6db772c1a9231f1c3ed0cbd7 \ - --hash=sha256:54a2db7b78338edd780e7ef7f9f6c442500fb0d41a5a4ea24fff1c929d5af585 \ - --hash=sha256:5635bd9cb9731e6d4a1132a498dd34f764034a8ce60cef4f5319c0541159392f \ - --hash=sha256:59c0b02d0a6c384d453fece7566d1c7e6b7bae4fc5874ef2ef46d56776d61c9e \ - --hash=sha256:5d598b938678ebf3c67377cdd45e09d431369c3b1a5b331058c338e201f12b27 \ - --hash=sha256:5df2768244d19ab7f60546d0c7c63ce1581f7af8b5de3eb3004b9b6fc8a9f84b \ - --hash=sha256:5ef34d190326c3b1f822a5b7a45f6c4535e2f47ed06fec77d3d799c450b2651e \ - --hash=sha256:6975a3fac6bc83c4a65c9f9fcab9e47019a11d3d2cf7f3c0d03431bf145a941e \ - --hash=sha256:6c9a799e985904922a4d207a94eae35c78ebae90e128f0c4e521ce339396be9d \ - --hash=sha256:70df4e3b545a17496c9b3f41f5115e69a4f2e77e94e1d2a8e1070bc0c38c8a3c \ - --hash=sha256:7473e861101c9e72452f9bf8acb984947aa1661a7704553a9f6e4baa5ba64415 \ - --hash=sha256:8102eaf27e1e448db915d08afa8b41d6c7ca7a04b7d73af6514df10a3e74bd82 \ - --hash=sha256:87c450779d0914f2861b8526e035c5e6da0a3199d8f1add1a665e1cbc6fc6d02 \ - --hash=sha256:8b7ee99e510d7b66cdb6c593f21c043c248537a32e0bedf02e01e9553a172314 \ - --hash=sha256:91fc98adde3d7881af9b59ed0294046f3806221863722ba7d8d120c575314325 \ - --hash=sha256:94411f22c3985acaec6f83c6df553f2dbe17b698cc7f8ae751ff2237d96b9e3c \ - --hash=sha256:98d85c6a2bef81588d9227dde12db8a7f47f639f4a17c9ae08e773aa9c697bf3 \ - --hash=sha256:9ad5db27f9cabae298d151c85cf2bad1d359a1b9c686a275df03385758e2f914 \ - --hash=sha256:a0b71b1b8fbf2b96e41c4d990244165e2c9be83d54962a9a1d118fd8657d2045 \ - --hash=sha256:a0f100c8912c114ff53e1202d0078b425bee3649ae34d7b070e9697f93c5d52d \ - --hash=sha256:a591fe9e525846e4d154205572a029f653ada1a78b93697f3b5a8f1f2bc055b9 \ - --hash=sha256:a5c84c68147988265e60416b57fc83425a78058853509c1b0629c180094904a5 \ - --hash=sha256:a66d3508133af6e8548451b25058d5812812ec3798c886bf38ed24a98216fab2 \ - --hash=sha256:a8c4917bd7ad33e8eb21e9a5bbba979b49d9a97acb3a803092cbc1133e20343c \ - --hash=sha256:b3bbeb01c2b273cca1e1e0c5df57f12dce9a4dd331b4fa1635b8bec26350bde3 \ - --hash=sha256:cba9d6b9a7d64d4bd46167096fc9d2f835e25d7e4c121fb2ddfc6528fb0413b2 \ - --hash=sha256:cc4d65aeeaa04136a12677d3dd0b1c0c94dc43abac5860ab33cceb42b801c1e8 \ - --hash=sha256:ce4bcc037df4fc5e3d184794f27bdaab018943698f4ca31630bc7f84a7b69c6d \ - --hash=sha256:cec7d9412a9102bdc577382c3929b337320c4c4c4849f2c5cdd14d7368c5562d \ - --hash=sha256:d400bfb9a37b1351253cb402671cea7e89bdecc294e8016a707f6d1d8ac934f9 \ - --hash=sha256:d61f4695e6c866a23a21acab0509af1cdfd2c013cf256bbf5b6b5e2695827162 \ - --hash=sha256:db0fbb9c62743ce59a9ff687eb5f4afbe77e5e8403d6697f7446e5f609976f76 \ - --hash=sha256:dd86c085fae2efd48ac91dd7ccffcfc0571387fe1193d33b6394db7ef31fe2a4 \ - --hash=sha256:e00b098126fd45523dd056d2efba6c5a63b71ffe9f2bbe1a4fe1716e1d0c331e \ - --hash=sha256:e229a521186c75c8ad9490854fd8bbdd9a0c9aa3a524326b55be83b54d4e0ad9 \ - --hash=sha256:e263d77ee3dd201c3a142934a086a4450861778baaeeb45db4591ef65550b0a6 \ - --hash=sha256:ed9cb427ba5504c1dc15ede7d516b84757c3e3d7868ccc85121d9310d27eed0b \ - --hash=sha256:fa6693661a4c91757f4412306191b6dc88c1703f780c8234035eac011922bc01 \ - --hash=sha256:fcd131dd944808b5bdb38e6f5b53013c5aa4f334c5cad0c72742f6eba4b73db0 +cffi==1.16.0 # via # cryptography # pygit2 # pynacl -charset-normalizer==3.2.0 \ - --hash=sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96 \ - --hash=sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c \ - --hash=sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710 \ - --hash=sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706 \ - --hash=sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020 \ - --hash=sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252 \ - --hash=sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad \ - --hash=sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329 \ - --hash=sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a \ - --hash=sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f \ - --hash=sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6 \ - --hash=sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4 \ - --hash=sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a \ - --hash=sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46 \ - --hash=sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2 \ - --hash=sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23 \ - --hash=sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace \ - --hash=sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd \ - --hash=sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982 \ - --hash=sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10 \ - --hash=sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2 \ - --hash=sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea \ - --hash=sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09 \ - --hash=sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5 \ - --hash=sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149 \ - --hash=sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489 \ - --hash=sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9 \ - --hash=sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80 \ - --hash=sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592 \ - --hash=sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3 \ - --hash=sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6 \ - --hash=sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed \ - --hash=sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c \ - --hash=sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200 \ - --hash=sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a \ - --hash=sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e \ - --hash=sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d \ - --hash=sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6 \ - --hash=sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623 \ - --hash=sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669 \ - --hash=sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3 \ - --hash=sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa \ - --hash=sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9 \ - --hash=sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2 \ - --hash=sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f \ - --hash=sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1 \ - --hash=sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4 \ - --hash=sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a \ - --hash=sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8 \ - --hash=sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3 \ - --hash=sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029 \ - --hash=sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f \ - --hash=sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959 \ - --hash=sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22 \ - --hash=sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7 \ - --hash=sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952 \ - --hash=sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346 \ - --hash=sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e \ - --hash=sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d \ - --hash=sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299 \ - --hash=sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd \ - --hash=sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a \ - --hash=sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3 \ - --hash=sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037 \ - --hash=sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94 \ - --hash=sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c \ - --hash=sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858 \ - --hash=sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a \ - --hash=sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449 \ - --hash=sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c \ - --hash=sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918 \ - --hash=sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1 \ - --hash=sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c \ - --hash=sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac \ - --hash=sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa +charset-normalizer==3.3.2 # via requests -cryptography==42.0.4 \ - --hash=sha256:01911714117642a3f1792c7f376db572aadadbafcd8d75bb527166009c9f1d1b \ - --hash=sha256:0e89f7b84f421c56e7ff69f11c441ebda73b8a8e6488d322ef71746224c20fce \ - --hash=sha256:12d341bd42cdb7d4937b0cabbdf2a94f949413ac4504904d0cdbdce4a22cbf88 \ - --hash=sha256:15a1fb843c48b4a604663fa30af60818cd28f895572386e5f9b8a665874c26e7 \ - --hash=sha256:1cdcdbd117681c88d717437ada72bdd5be9de117f96e3f4d50dab3f59fd9ab20 \ - --hash=sha256:1df6fcbf60560d2113b5ed90f072dc0b108d64750d4cbd46a21ec882c7aefce9 \ - --hash=sha256:3c6048f217533d89f2f8f4f0fe3044bf0b2090453b7b73d0b77db47b80af8dff \ - --hash=sha256:3e970a2119507d0b104f0a8e281521ad28fc26f2820687b3436b8c9a5fcf20d1 \ - --hash=sha256:44a64043f743485925d3bcac548d05df0f9bb445c5fcca6681889c7c3ab12764 \ - --hash=sha256:4e36685cb634af55e0677d435d425043967ac2f3790ec652b2b88ad03b85c27b \ - --hash=sha256:5f8907fcf57392cd917892ae83708761c6ff3c37a8e835d7246ff0ad251d9298 \ - --hash=sha256:69b22ab6506a3fe483d67d1ed878e1602bdd5912a134e6202c1ec672233241c1 \ - --hash=sha256:6bfadd884e7280df24d26f2186e4e07556a05d37393b0f220a840b083dc6a824 \ - --hash=sha256:6d0fbe73728c44ca3a241eff9aefe6496ab2656d6e7a4ea2459865f2e8613257 \ - --hash=sha256:6ffb03d419edcab93b4b19c22ee80c007fb2d708429cecebf1dd3258956a563a \ - --hash=sha256:810bcf151caefc03e51a3d61e53335cd5c7316c0a105cc695f0959f2c638b129 \ - --hash=sha256:831a4b37accef30cccd34fcb916a5d7b5be3cbbe27268a02832c3e450aea39cb \ - --hash=sha256:887623fe0d70f48ab3f5e4dbf234986b1329a64c066d719432d0698522749929 \ - --hash=sha256:a0298bdc6e98ca21382afe914c642620370ce0470a01e1bef6dd9b5354c36854 \ - --hash=sha256:a1327f280c824ff7885bdeef8578f74690e9079267c1c8bd7dc5cc5aa065ae52 \ - --hash=sha256:c1f25b252d2c87088abc8bbc4f1ecbf7c919e05508a7e8628e6875c40bc70923 \ - --hash=sha256:c3a5cbc620e1e17009f30dd34cb0d85c987afd21c41a74352d1719be33380885 \ - --hash=sha256:ce8613beaffc7c14f091497346ef117c1798c202b01153a8cc7b8e2ebaaf41c0 \ - --hash=sha256:d2a27aca5597c8a71abbe10209184e1a8e91c1fd470b5070a2ea60cafec35bcd \ - --hash=sha256:dad9c385ba8ee025bb0d856714f71d7840020fe176ae0229de618f14dae7a6e2 \ - --hash=sha256:db4b65b02f59035037fde0998974d84244a64c3265bdef32a827ab9b63d61b18 \ - --hash=sha256:e09469a2cec88fb7b078e16d4adec594414397e8879a4341c6ace96013463d5b \ - --hash=sha256:e53dc41cda40b248ebc40b83b31516487f7db95ab8ceac1f042626bc43a2f992 \ - --hash=sha256:f1e85a178384bf19e36779d91ff35c7617c885da487d689b05c1366f9933ad74 \ - --hash=sha256:f47be41843200f7faec0683ad751e5ef11b9a56a220d57f300376cd8aba81660 \ - --hash=sha256:fb0cef872d8193e487fc6bdb08559c3aa41b659a7d9be48b2e10747f47863925 \ - --hash=sha256:ffc73996c4fca3d2b6c1c8c12bfd3ad00def8621da24f547626bf06441400449 +cryptography==42.0.8 # via pyjwt -deprecated==1.2.14 \ - --hash=sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c \ - --hash=sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3 +deprecated==1.2.14 # via pygithub -gql[requests]==3.4.1 \ - --hash=sha256:11dc5d8715a827f2c2899593439a4f36449db4f0eafa5b1ea63948f8a2f8c545 \ - --hash=sha256:315624ca0f4d571ef149d455033ebd35e45c1a13f18a059596aeddcea99135cf +gql[requests]==3.5.0 # via -r requirements.in -graphql-core==3.2.3 \ - --hash=sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676 \ - --hash=sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3 +graphql-core==3.2.3 # via gql -idna==3.7 \ - --hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \ - --hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0 +idna==3.7 # via + # anyio # requests # yarl -multidict==6.0.4 \ - --hash=sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9 \ - --hash=sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8 \ - --hash=sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03 \ - --hash=sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710 \ - --hash=sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161 \ - --hash=sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664 \ - --hash=sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569 \ - --hash=sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067 \ - --hash=sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313 \ - --hash=sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706 \ - --hash=sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2 \ - --hash=sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636 \ - --hash=sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49 \ - --hash=sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93 \ - --hash=sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603 \ - --hash=sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0 \ - --hash=sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60 \ - --hash=sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4 \ - --hash=sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e \ - --hash=sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1 \ - --hash=sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60 \ - --hash=sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951 \ - --hash=sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc \ - --hash=sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe \ - --hash=sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95 \ - --hash=sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d \ - --hash=sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8 \ - --hash=sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed \ - --hash=sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2 \ - --hash=sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775 \ - --hash=sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87 \ - --hash=sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c \ - --hash=sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2 \ - --hash=sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98 \ - --hash=sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3 \ - --hash=sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe \ - --hash=sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78 \ - --hash=sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660 \ - --hash=sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176 \ - --hash=sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e \ - --hash=sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988 \ - --hash=sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c \ - --hash=sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c \ - --hash=sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0 \ - --hash=sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449 \ - --hash=sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f \ - --hash=sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde \ - --hash=sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5 \ - --hash=sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d \ - --hash=sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac \ - --hash=sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a \ - --hash=sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9 \ - --hash=sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca \ - --hash=sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11 \ - --hash=sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35 \ - --hash=sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063 \ - --hash=sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b \ - --hash=sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982 \ - --hash=sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258 \ - --hash=sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1 \ - --hash=sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52 \ - --hash=sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480 \ - --hash=sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7 \ - --hash=sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461 \ - --hash=sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d \ - --hash=sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc \ - --hash=sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779 \ - --hash=sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a \ - --hash=sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547 \ - --hash=sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0 \ - --hash=sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171 \ - --hash=sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf \ - --hash=sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d \ - --hash=sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba +multidict==6.0.5 # via yarl -pycparser==2.21 \ - --hash=sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9 \ - --hash=sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206 +pycairo==1.26.0 + # via pygobject +pycparser==2.22 # via cffi -pygit2==1.12.2 \ - --hash=sha256:14ae27491347a0ac4bbe8347b09d752cfe7fea1121c14525415e0cca6db4a836 \ - --hash=sha256:214bd214784fcbef7a8494d1d59e0cd3a731c0d24ce0f230dcc843322ee33b08 \ - --hash=sha256:22e7f3ad2b7b0c80be991bb47d8a2f2535cc9bf090746eb8679231ee565fde81 \ - --hash=sha256:25a6548930328c5247bfb7c67d29104e63b036cb5390f032d9f91f63efb70434 \ - --hash=sha256:336c864ac961e7be8ba06e9ed8c999e4f624a8ccd90121cc4e40956d8b57acac \ - --hash=sha256:546091316c9a8c37b9867ddcc6c9f7402ca4d0b9db3f349212a7b5e71988e359 \ - --hash=sha256:56e85d0e66de957d599d1efb2409d39afeefd8f01009bfda0796b42a4b678358 \ - --hash=sha256:5b3ab4d6302990f7adb2b015bcbda1f0715277008d0c66440497e6f8313bf9cb \ - --hash=sha256:5c1e26649e1540b6a774f812e2fc9890320ff4d33f16db1bb02626318b5ceae2 \ - --hash=sha256:5f65483ab5e3563c58f60debe2acc0979fdf6fd633432fcfbddf727a9a265ba4 \ - --hash=sha256:685378852ef8eb081333bc80dbdfc4f1333cf4a8f3baf614c4135e02ad1ee38a \ - --hash=sha256:6a4083ba093c69142e0400114a4ef75e87834637d2bbfd77b964614bf70f624f \ - --hash=sha256:79fbd99d3e08ca7478150eeba28ca4d4103f564148eab8d00aba8f1e6fc60654 \ - --hash=sha256:7bb30ab1fdaa4c30821fed33892958b6d92d50dbd03c76f7775b4e5d62f53a2e \ - --hash=sha256:857c5cde635d470f58803d67bfb281dc4f6336065a0253bfbed001f18e2d0767 \ - --hash=sha256:8bf14196cbfffbcd286f459a1d4fc660c5d5dfa8fb422e21216961df575410d6 \ - --hash=sha256:8da8517809635ea3da950d9cf99c6d1851352d92b6db309382db88a01c3b0bfd \ - --hash=sha256:8f443d3641762b2bb9c76400bb18beb4ba27dd35bc098a8bfae82e6a190c52ab \ - --hash=sha256:926f2e48c4eaa179249d417b8382290b86b0f01dbf41d289f763576209276b9f \ - --hash=sha256:a365ffca23d910381749fdbcc367db52fe808f9aa4852914dd9ef8b711384a32 \ - --hash=sha256:ac2b5f408eb882e79645ebb43039ac37739c3edd25d857cc97d7482a684b613f \ - --hash=sha256:b9c2359b99eed8e7fac30c06e6b4ae277a6a0537d6b4b88a190828c3d7eb9ef2 \ - --hash=sha256:be3bb0139f464947523022a5af343a2e862c4ff250a57ec9f631449e7c0ba7c0 \ - --hash=sha256:c74e7601cb8b8dc3d02fd32274e200a7761cffd20ee531442bf1fa115c8f99a5 \ - --hash=sha256:cdf655e5f801990f5cad721b6ccbe7610962f0a4f1c20373dbf9c0be39374a81 \ - --hash=sha256:e7e705aaecad85b883022e81e054fbd27d26023fc031618ee61c51516580517e \ - --hash=sha256:ec04c27be5d5af1ceecdcc0464e07081222f91f285f156dc53b23751d146569a \ - --hash=sha256:f4df3e5745fdf3111a6ccc905eae99f22f1a180728f714795138ca540cc2a50a \ - --hash=sha256:f8f813d35d836c5b0d1962c387754786bcc7f1c3c8e11207b9eeb30238ac4cc7 \ - --hash=sha256:fb9eb57b75ce586928053692a25aae2a50fef3ad36661c57c07d4902899b1df3 \ - --hash=sha256:fe35a72af61961dbb7fb4abcdaa36d5f1c85b2cd3daae94137eeb9c07215cdd3 +pygit2==1.15.0 # via -r requirements.in -pygithub==1.59.0 \ - --hash=sha256:126bdbae72087d8d038b113aab6b059b4553cb59348e3024bb1a1cae406ace9e \ - --hash=sha256:6e05ff49bac3caa7d1d6177a10c6e55a3e20c85b92424cc198571fd0cf786690 +pygithub==2.3.0 # via -r requirements.in -pyjwt[crypto]==2.7.0 \ - --hash=sha256:ba2b425b15ad5ef12f200dc67dd56af4e26de2331f965c5439994dad075876e1 \ - --hash=sha256:bd6ca4a3c4285c1a2d4349e5a035fdf8fb94e04ccd0fcbe6ba289dae9cc3e074 +pygobject==3.48.2 + # via -r requirements.in +pyjwt[crypto]==2.8.0 + # via + # pygithub + # pyjwt +pynacl==1.5.0 # via pygithub -pynacl==1.5.0 \ - --hash=sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858 \ - --hash=sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d \ - --hash=sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93 \ - --hash=sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1 \ - --hash=sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92 \ - --hash=sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff \ - --hash=sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba \ - --hash=sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394 \ - --hash=sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b \ - --hash=sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543 - # via pygithub -pyyaml==6.0 \ - --hash=sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf \ - --hash=sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293 \ - --hash=sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b \ - --hash=sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57 \ - --hash=sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b \ - --hash=sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4 \ - --hash=sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07 \ - --hash=sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba \ - --hash=sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9 \ - --hash=sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287 \ - --hash=sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513 \ - --hash=sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0 \ - --hash=sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782 \ - --hash=sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0 \ - --hash=sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92 \ - --hash=sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f \ - --hash=sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2 \ - --hash=sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc \ - --hash=sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1 \ - --hash=sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c \ - --hash=sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86 \ - --hash=sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4 \ - --hash=sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c \ - --hash=sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34 \ - --hash=sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b \ - --hash=sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d \ - --hash=sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c \ - --hash=sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb \ - --hash=sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7 \ - --hash=sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737 \ - --hash=sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3 \ - --hash=sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d \ - --hash=sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358 \ - --hash=sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53 \ - --hash=sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78 \ - --hash=sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803 \ - --hash=sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a \ - --hash=sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f \ - --hash=sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174 \ - --hash=sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5 +pyyaml==6.0.1 # via -r requirements.in -requests==2.32.0 \ - --hash=sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5 \ - --hash=sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8 +requests==2.32.3 # via # gql # pygithub # requests-toolbelt -requests-toolbelt==0.10.1 \ - --hash=sha256:18565aa58116d9951ac39baa288d3adb5b3ff975c4f25eee78555d89e8f247f7 \ - --hash=sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d +requests-toolbelt==1.0.0 # via gql -urllib3==1.26.18 \ - --hash=sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07 \ - --hash=sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0 +sniffio==1.3.1 + # via anyio +typing-extensions==4.12.2 + # via pygithub +urllib3==2.2.1 # via - # gql + # pygithub # requests -wrapt==1.15.0 \ - --hash=sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0 \ - --hash=sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420 \ - --hash=sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a \ - --hash=sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c \ - --hash=sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079 \ - --hash=sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923 \ - --hash=sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f \ - --hash=sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1 \ - --hash=sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8 \ - --hash=sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86 \ - --hash=sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0 \ - --hash=sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364 \ - --hash=sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e \ - --hash=sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c \ - --hash=sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e \ - --hash=sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c \ - --hash=sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727 \ - --hash=sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff \ - --hash=sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e \ - --hash=sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29 \ - --hash=sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7 \ - --hash=sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72 \ - --hash=sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475 \ - --hash=sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a \ - --hash=sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317 \ - --hash=sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2 \ - --hash=sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd \ - --hash=sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640 \ - --hash=sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98 \ - --hash=sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248 \ - --hash=sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e \ - --hash=sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d \ - --hash=sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec \ - --hash=sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1 \ - --hash=sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e \ - --hash=sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9 \ - --hash=sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92 \ - --hash=sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb \ - --hash=sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094 \ - --hash=sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46 \ - --hash=sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29 \ - --hash=sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd \ - --hash=sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705 \ - --hash=sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8 \ - --hash=sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975 \ - --hash=sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb \ - --hash=sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e \ - --hash=sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b \ - --hash=sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418 \ - --hash=sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019 \ - --hash=sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1 \ - --hash=sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba \ - --hash=sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6 \ - --hash=sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2 \ - --hash=sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3 \ - --hash=sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7 \ - --hash=sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752 \ - --hash=sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416 \ - --hash=sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f \ - --hash=sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1 \ - --hash=sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc \ - --hash=sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145 \ - --hash=sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee \ - --hash=sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a \ - --hash=sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7 \ - --hash=sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b \ - --hash=sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653 \ - --hash=sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0 \ - --hash=sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90 \ - --hash=sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29 \ - --hash=sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6 \ - --hash=sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034 \ - --hash=sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09 \ - --hash=sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559 \ - --hash=sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639 +wrapt==1.16.0 # via deprecated -yarl==1.9.2 \ - --hash=sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571 \ - --hash=sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3 \ - --hash=sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3 \ - --hash=sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c \ - --hash=sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7 \ - --hash=sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04 \ - --hash=sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191 \ - --hash=sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea \ - --hash=sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4 \ - --hash=sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4 \ - --hash=sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095 \ - --hash=sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e \ - --hash=sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74 \ - --hash=sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef \ - --hash=sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33 \ - --hash=sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde \ - --hash=sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45 \ - --hash=sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf \ - --hash=sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b \ - --hash=sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac \ - --hash=sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0 \ - --hash=sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528 \ - --hash=sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716 \ - --hash=sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb \ - --hash=sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18 \ - --hash=sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72 \ - --hash=sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6 \ - --hash=sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582 \ - --hash=sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5 \ - --hash=sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368 \ - --hash=sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc \ - --hash=sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9 \ - --hash=sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be \ - --hash=sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a \ - --hash=sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80 \ - --hash=sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8 \ - --hash=sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6 \ - --hash=sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417 \ - --hash=sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574 \ - --hash=sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59 \ - --hash=sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608 \ - --hash=sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82 \ - --hash=sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1 \ - --hash=sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3 \ - --hash=sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d \ - --hash=sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8 \ - --hash=sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc \ - --hash=sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac \ - --hash=sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8 \ - --hash=sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955 \ - --hash=sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0 \ - --hash=sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367 \ - --hash=sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb \ - --hash=sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a \ - --hash=sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623 \ - --hash=sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2 \ - --hash=sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6 \ - --hash=sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7 \ - --hash=sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4 \ - --hash=sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051 \ - --hash=sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938 \ - --hash=sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8 \ - --hash=sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9 \ - --hash=sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3 \ - --hash=sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5 \ - --hash=sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9 \ - --hash=sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333 \ - --hash=sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185 \ - --hash=sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3 \ - --hash=sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560 \ - --hash=sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b \ - --hash=sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7 \ - --hash=sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78 \ - --hash=sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7 +yarl==1.9.4 # via gql From 1368361275d6604a3acd5ed12b36da903017e6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Mon, 17 Jun 2024 16:04:08 +0200 Subject: [PATCH 068/319] merge: Replace flatpak-builder with json-glib --- .github/actions/merge/entrypoint.py | 45 ++++++++++++++--------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 71de188..79192ae 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -9,12 +9,16 @@ import sys import tempfile import time +import gi import github import pygit2 import yaml from gql import Client, gql from gql.transport.requests import RequestsHTTPTransport +gi.require_version("Json", "1.0") +from gi.repository import Json + def set_protected_branch(token, repo, branch): transport = RequestsHTTPTransport( @@ -74,6 +78,7 @@ def set_protected_branch(token, repo, branch): def detect_appid(dirname): files = [] ret = (None, None) + appid = None for ext in ("yml", "yaml", "json"): files.extend(glob.glob(f"{dirname}/*.{ext}")) @@ -86,32 +91,26 @@ def detect_appid(dirname): with open(filename) as f: if ext in ("yml", "yaml"): manifest = yaml.safe_load(f) + if "app-id" in manifest: + appid = manifest["app-id"] + elif "id" in manifest: + appid = manifest["id"] else: - result = subprocess.run( - ["flatpak-builder", "--show-manifest", filename], - stdout=subprocess.PIPE, - ) - if result.returncode == 0: - manifest = json.loads(result.stdout.decode("utf-8")) - else: - print( - "flatpak-builder failed to print manifest, falling back to json Python module" - ) - try: - with open(filename) as f: - manifest = json.load(f) - except json.decoder.JSONDecodeError: - ("Manifest is not a valid JSON") - break + parser = Json.Parser() + if parser.load_from_file(parser, filename): + root_node = parser.get_root() + if root_node.get_node_type() == Json.NodeType.OBJECT: + json_object = root_node.get_object() + if json_object.has_member("id"): + appid = json_object.get_string_member("id") + elif json_object.has_member("app-id"): + appid = json_object.get_string_member("app-id") - if manifest: + if not appid: + continue + + if appid: manifest_file = os.path.basename(filename) - if "app-id" in manifest: - appid = manifest["app-id"] - elif "id" in manifest: - appid = manifest["id"] - else: - continue if os.path.splitext(manifest_file)[0] != appid: print(f"Skipping {manifest_file}, does not match appid {appid}") continue From c6bf5723f4818e2a157fb77d6b95ed2e30a1f198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Mon, 17 Jun 2024 16:04:34 +0200 Subject: [PATCH 069/319] merge: Rewrite Dockerfile to use python:3.12 --- .github/actions/merge/Dockerfile | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index 1dd5751..2e5049e 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -1,10 +1,24 @@ -FROM quay.io/fedora/fedora:38 +FROM python:3.12 AS builder -RUN dnf install -y flatpak-builder git /usr/bin/pip && \ - dnf clean all +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libcairo2-dev libgirepository1.0-dev -ADD requirements.txt /requirements.txt -RUN pip install -r /requirements.txt +ADD requirements.txt . -ADD entrypoint.py /entrypoint.py -ENTRYPOINT ["/entrypoint.py"] +RUN python -m venv /venv && \ + /venv/bin/python -m pip install -r requirements.txt + +FROM python:3.12-slim +ENV PATH="/venv/bin:$PATH" + +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /venv /venv +COPY . /app +WORKDIR /app + +CMD ["/app/entrypoint.py"] From bb45c5c1b86a8e75bb6686a3ae69cf5507eb8113 Mon Sep 17 00:00:00 2001 From: Bart Piotrowski Date: Mon, 17 Jun 2024 17:04:32 +0200 Subject: [PATCH 070/319] Update .github/actions/merge/entrypoint.py Co-authored-by: bbhtt --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 79192ae..81e99b7 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -97,7 +97,7 @@ def detect_appid(dirname): appid = manifest["id"] else: parser = Json.Parser() - if parser.load_from_file(parser, filename): + if parser.load_from_file(filename): root_node = parser.get_root() if root_node.get_node_type() == Json.NodeType.OBJECT: json_object = root_node.get_object() From b842aaa9269f709c9bf1f331d949394cc1c96a47 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 18 Jun 2024 06:03:40 +0530 Subject: [PATCH 071/319] merge: Fix path to entrypoint --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 7c6c407..992a712 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,6 +11,6 @@ jobs: container: image: ghcr.io/flathub/actions/merge:latest steps: - - run: /entrypoint.py + - run: /app/entrypoint.py env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From e8f5d5bbea328b8883e008b79892b267a001d960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Tue, 18 Jun 2024 13:40:11 +0200 Subject: [PATCH 072/319] merge: Fix cloning submodules --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 81e99b7..b8caaf4 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -167,7 +167,7 @@ def main(): tmpdir = tempfile.TemporaryDirectory() print(f"Cloning {fork_url} (branch: {branch})") clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=branch) - clone.update_submodules(init=True) + clone.submodules.update(init=True) manifest_file, appid = detect_appid(tmpdir.name) if manifest_file is None or appid is None: From 9fa686d437324e0561f3192373591448a7f1a737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Piotrowski?= Date: Tue, 18 Jun 2024 13:47:18 +0200 Subject: [PATCH 073/319] merge: Install git in the final stage --- .github/actions/merge/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index 2e5049e..cfeda01 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -14,7 +14,7 @@ ENV PATH="/venv/bin:$PATH" RUN apt-get update && \ apt-get install -y --no-install-recommends \ - libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ + git libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ apt-get clean && rm -rf /var/lib/apt/lists/* COPY --from=builder /venv /venv From 2b908af10b18be50c0e8cc51a4d60f2535549877 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 28 Jun 2024 16:18:11 +0530 Subject: [PATCH 074/319] Bump stale workflow to v9 --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c2781fe..38a44ef 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v1 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 14 days. Feel free to re-open it if you plan to continue working on that pull request or think it deserves attention from Flathub admins" From b099dd835621e1d488a409ca9e116094e260ba99 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 28 Jun 2024 16:18:23 +0530 Subject: [PATCH 075/319] Bump checkout to v4 --- .github/workflows/external-data-checker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 4b77eff..195806f 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -7,7 +7,7 @@ jobs: flathub-data-checker-global: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ./.github/actions/flatpak-external-data-checker env: From b8da535c4cd0352c6aea40a1c33ebf5d10af1ed8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 28 Jun 2024 16:20:55 +0530 Subject: [PATCH 076/319] Allow manually triggering some workflows --- .github/workflows/external-data-checker.yml | 2 ++ .github/workflows/merge.yml | 1 + .github/workflows/stale.yml | 2 ++ 3 files changed, 5 insertions(+) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 195806f..1bb03ee 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -3,6 +3,8 @@ on: schedule: - cron: '0 * * * *' + workflow_dispatch: + jobs: flathub-data-checker-global: runs-on: ubuntu-latest diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 992a712..e14ef45 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -4,6 +4,7 @@ on: issue_comment: types: - created + workflow_dispatch: jobs: merge: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 38a44ef..0788b60 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -3,6 +3,8 @@ on: schedule: - cron: "0 0 * * *" + workflow_dispatch: + jobs: stale: runs-on: ubuntu-latest From f4b01463654c6f8c04c523d2dde0b128e9366a16 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 28 Jun 2024 16:47:49 +0530 Subject: [PATCH 077/319] stale: Prevent marking issues as stale and only process labeled PRs Also increase the limit to wait for 30 days before closing stale workflow has no option on running on issues only See https://github.com/actions/stale/issues/1112 --- .github/workflows/stale.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 0788b60..97a2f8e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,6 +12,10 @@ jobs: - uses: actions/stale@v9 with: repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} - stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 14 days. Feel free to re-open it if you plan to continue working on that pull request or think it deserves attention from Flathub admins" - days-before-stale: 365 - days-before-close: 14 + stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. Feel free to re-open it if you plan to continue working on that pull request or think it deserves attention from Flathub admins" + days-before-stale: -1 + days-before-close: -1 + days-before-pr-stale: 365 + days-before-pr-close: 30 + only-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream + remove-pr-stale-when-updated: true From 783f0e65618576161f7564428b3da96da1480e80 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 28 Jun 2024 16:48:56 +0530 Subject: [PATCH 078/319] merge: Bump urllib3 to 2.2.2 Resolves https://github.com/flathub/flathub/security/dependabot/12 --- .github/actions/merge/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index c1861cd..e1a739b 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -61,7 +61,7 @@ sniffio==1.3.1 # via anyio typing-extensions==4.12.2 # via pygithub -urllib3==2.2.1 +urllib3==2.2.2 # via # pygithub # requests From 375af24b3999161237ea12eba8d6abc8f557cce8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 29 Jun 2024 13:18:03 +0530 Subject: [PATCH 079/319] Reduce the PR template --- .github/pull_request_template.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 25be108..1d4179d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,20 +2,15 @@ ### Please confirm your submission meets all the criteria - + -- [ ] Please describe your application briefly. -- [ ] I have read the [App Requirements][reqs] and [App Maintenance][maint] pages. -- [ ] My pull request follows the instructions at [App Submission][submission]. +- [ ] Please describe the application briefly. +- [ ] The domain used for the application ID is [controlled by the application developers][appid-domain] and the [application id guidelines][appid] are followed. +- [ ] I have read the and followed all the [Submission and licence requirements][reqs]. - [ ] I have [built][build] and tested the submission locally. -- [ ] I am using only the minimal set of permissions. *(If not, please explain each non-standard permission.)* -- [ ] All assets referenced in the manifest are redistributable by any party. If not, the unredistributable parts are using an extra-data source type. -- [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about submitting their software to Flathub. **Link:** -- [ ] The domain used for the application ID is controlled by the application developers either directly or through the code hosting (e.g. GitHub, GitLab, SourceForge, etc.). The [application id guidelines][app-id] are followed. -- [ ] Any additional patches or files have been submitted to the upstream projects concerned. *(If not, explain why.)* +- [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about this submission. **Link:** +[appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements#control-over-domain +[appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements -[maint]: https://docs.flathub.org/docs/for-app-authors/maintanance -[submission]: https://docs.flathub.org/docs/for-app-authors/submission [build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission -[app-id]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id From 90bdc682e62f8b13b59aa3f28eee4bd48aac7531 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 29 Jun 2024 14:53:08 +0530 Subject: [PATCH 080/319] Add a warning to not remove links --- .github/pull_request_template.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1d4179d..7b81327 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -10,6 +10,9 @@ - [ ] I have [built][build] and tested the submission locally. - [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about this submission. **Link:** + + + [appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements#control-over-domain [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements From 4f57602218c003f390cf470af8708d27ec0d7f03 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 6 Jul 2024 20:29:53 +0530 Subject: [PATCH 081/319] Update certifi and pycairo Fixes https://github.com/flathub/flathub/security/dependabot/13 --- .github/actions/merge/requirements.txt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index e1a739b..bcf48db 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.11 +# This file is autogenerated by pip-compile with Python 3.12 # by the following command: # # pip-compile requirements.in @@ -8,7 +8,7 @@ anyio==4.4.0 # via gql backoff==2.2.1 # via gql -certifi==2024.6.2 +certifi==2024.7.4 # via requests cffi==1.16.0 # via @@ -32,7 +32,7 @@ idna==3.7 # yarl multidict==6.0.5 # via yarl -pycairo==1.26.0 +pycairo==1.26.1 # via pygobject pycparser==2.22 # via cffi @@ -43,9 +43,7 @@ pygithub==2.3.0 pygobject==3.48.2 # via -r requirements.in pyjwt[crypto]==2.8.0 - # via - # pygithub - # pyjwt + # via pygithub pynacl==1.5.0 # via pygithub pyyaml==6.0.1 From 5b657a2de5b8837e351b91bea6e83f51e8000490 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 9 Jul 2024 19:23:13 +0530 Subject: [PATCH 082/319] merge: Set "Automatically delete head branches" on by default --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index b8caaf4..f611615 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -179,7 +179,7 @@ def main(): print("Creating new repo on Flathub") repo = org.create_repo(appid) time.sleep(5) - repo.edit(homepage=f"https://flathub.org/apps/details/{appid}") + repo.edit(homepage=f"https://flathub.org/apps/details/{appid}", delete_branch_on_merge=True) print("Adding flathub remote") clone.remotes.create( From ec0a36a0063c4abb169b93627d080f6eae48585e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 5 Jul 2024 17:22:25 +0530 Subject: [PATCH 083/319] Add action to archive repositories of EOL apps --- .github/scripts/archive_eol.py | 106 +++++++++++++++++++++++++++++++++ .github/workflows/archive.yml | 26 ++++++++ 2 files changed, 132 insertions(+) create mode 100644 .github/scripts/archive_eol.py create mode 100644 .github/workflows/archive.yml diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py new file mode 100644 index 0000000..6dc68e9 --- /dev/null +++ b/.github/scripts/archive_eol.py @@ -0,0 +1,106 @@ +import os +import subprocess +import time + +import github +from github.GithubException import RateLimitExceededException, UnknownObjectException + + +def ignore_ref(ref: str) -> bool: + ref_splits = ref.split("/") + + if len(ref_splits) != 4: + return True + + if ref_splits[2] not in ("x86_64", "aarch64") or ref_splits[1].endswith( + (".Debug", ".Locale", ".Sources") + ): + return True + return False + + +def get_eol_refs(arch: str, remote: str) -> set: + cmd = ( + f'flatpak remote-ls --user --arch="{arch}" --all --columns=ref,options {remote}' + ) + ret = subprocess.run(cmd, shell=True, capture_output=True, encoding="utf-8") + eol_refs: set = set() + + if ret.returncode == 0 and ret.stdout: + for line in ret.stdout.split("\n"): + if line: + split = line.split("\t") + if len(split) < 2: + continue + ref, options = split + if ignore_ref(ref): + continue + refname = ref.split("/")[1] + if any(x in options for x in ("eol=", "eol-rebase=")): + eol_refs.add(refname) + + return eol_refs + + +def main() -> None: + + token = os.environ["GITHUB_TOKEN"] + + g = github.Github(auth=github.Auth.Token(token)) + + # Exclude refs that have EOL notices but are still maintained + # in some branch + excludes = { + "com.riverbankcomputing.PyQt.BaseApp", + "org.freedesktop.LinuxAudio.BaseExtension", + "org.freedesktop.LinuxAudio.Plugins.LSP", + "org.freedesktop.LinuxAudio.Plugins.setBfree", + "org.freedesktop.LinuxAudio.Plugins.sfizz", + "org.freedesktop.LinuxAudio.Plugins.x42Plugins", + "org.freedesktop.LinuxAudio.Plugins.ZamPlugins", + "org.freedesktop.Sdk.Extension.golang", + "org.freedesktop.Sdk.Extension.mono6", + "org.freedesktop.Sdk.Extension.openjdk8", + "org.freedesktop.Sdk.Extension.php73", + "org.freedesktop.Sdk.Extension.rust-stable", + "org.freedesktop.Sdk.Extension.ziglang", + "org.gnome.Chess", + "org.gnome.GHex", + "org.gnome.Quadrapassel", + "org.gnome.Tetravex", + "org.kde.kate", + "org.kekikakademi.eFatura", + "org.mozilla.firefox.BaseApp", + "org.tabos.twofun", + "org.videolan.VLC.Plugin.bdj", + "org.videolan.VLC.Plugin.fdkaac", + } + # we need to get apps which are EOL on both supported arches + # as there are apps which are only EOL on one arch but maintained + # in another. This might miss some refs but LBYL! + stable = get_eol_refs("x86_64", "flathub") & get_eol_refs("aarch64", "flathub") + eols = list(stable - excludes) + + if not eols: + return + + earliest = datetime.datetime.now(datetime.UTC) - datetime.timedelta(weeks=60) + count = 0 + while count < len(eols): + refname = eols[count] + try: + repo = g.get_repo(f"flathub/{refname}") + if not repo.archived: + print("Archiving {}".format(repo.html_url)) + repo.edit(archived=True) + except UnknownObjectException: + pass + except RateLimitExceededException: + print("Rate limited") + time.sleep(g.rate_limiting_resettime - time.time() + 10) + continue + count += 1 + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml new file mode 100644 index 0000000..8455738 --- /dev/null +++ b/.github/workflows/archive.yml @@ -0,0 +1,26 @@ +name: Archive EOL repositories + +on: + schedule: + - cron: '0 14 * * 1' + workflow_dispatch: {} + +jobs: + archive: + name: Archive EOL repositories + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt install -y flatpak python3 python3-pip + pip3 install 'PyGithub==2.3.0' + + - name: Set up Flathub remotes + run: | + flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + + - name: Run EOL script + run: python3 .github/scripts/archive_eol.py From 3cddb151fba6552754c77d9a464769424982ca17 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 9 Jul 2024 14:03:51 +0530 Subject: [PATCH 084/319] Add a cutoff period before archiving --- .github/scripts/archive_eol.py | 9 +++++++-- .github/workflows/archive.yml | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 6dc68e9..821b21a 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -1,3 +1,4 @@ +import datetime import os import subprocess import time @@ -90,8 +91,12 @@ def main() -> None: refname = eols[count] try: repo = g.get_repo(f"flathub/{refname}") - if not repo.archived: - print("Archiving {}".format(repo.html_url)) + if not repo.archived and repo.pushed_at < earliest: + print( + "Archiving: {}. Repo is in EOL list. Last push: {}, earlier than: {}".format( + repo.html_url, repo.pushed_at.isoformat(), earliest.isoformat() + ) + ) repo.edit(archived=True) except UnknownObjectException: pass diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 8455738..89f6eb9 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -2,7 +2,7 @@ name: Archive EOL repositories on: schedule: - - cron: '0 14 * * 1' + - cron: '0 0 1 * *' workflow_dispatch: {} jobs: From 9c1343d46f008e7d143faa365eeb9e5623599762 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 10 Jul 2024 17:50:16 +0530 Subject: [PATCH 085/319] Add checkout actions This got lost during rebase --- .github/workflows/archive.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 89f6eb9..66983c7 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -12,6 +12,8 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} steps: + - uses: actions/checkout@v4 + - name: Install dependencies run: | sudo apt-get update From bd128deef997115754513c9b84e3e9d6853ac323 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 10 Jul 2024 17:54:52 +0530 Subject: [PATCH 086/319] archive_eol: Change datetime.UTC to datetime.timezone.utc This works on older Python versions and the first is an alias to the second --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 821b21a..51dba55 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -85,7 +85,7 @@ def main() -> None: if not eols: return - earliest = datetime.datetime.now(datetime.UTC) - datetime.timedelta(weeks=60) + earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(weeks=60) count = 0 while count < len(eols): refname = eols[count] From 93084c900f453a38bb440d95f3cd4204e1d7ca06 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 10 Jul 2024 17:59:29 +0530 Subject: [PATCH 087/319] archive_eol.py: Remove full stop so that links are valid --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 51dba55..adeafc4 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -93,7 +93,7 @@ def main() -> None: repo = g.get_repo(f"flathub/{refname}") if not repo.archived and repo.pushed_at < earliest: print( - "Archiving: {}. Repo is in EOL list. Last push: {}, earlier than: {}".format( + "Archiving: {} Repo is in EOL list. Last push: {}, earlier than: {}".format( repo.html_url, repo.pushed_at.isoformat(), earliest.isoformat() ) ) From e0616da4de63e4213cbef8858007d1aa6d516bbe Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 10 Jul 2024 18:22:25 +0530 Subject: [PATCH 088/319] build-merge: Give a proper name --- .github/workflows/build-merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-merge.yml b/.github/workflows/build-merge.yml index 6de14b0..480e187 100644 --- a/.github/workflows/build-merge.yml +++ b/.github/workflows/build-merge.yml @@ -1,4 +1,4 @@ -name: build-merge +name: 'Build image for merge workflow' on: push: From 2c6bf98a9663d83305c1ab633da4eed6bf830350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hubert=20Figui=C3=A8re?= Date: Wed, 10 Jul 2024 20:40:23 -0400 Subject: [PATCH 089/319] template: added explicit 'where to put the description' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Hubert Figuière --- .github/pull_request_template.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 7b81327..607efef 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,6 +5,8 @@ - [ ] Please describe the application briefly. + + - [ ] The domain used for the application ID is [controlled by the application developers][appid-domain] and the [application id guidelines][appid] are followed. - [ ] I have read the and followed all the [Submission and licence requirements][reqs]. - [ ] I have [built][build] and tested the submission locally. From 77a0556951ee9538ef6f8d81cc42c4b4834b5285 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 13 Jul 2024 21:21:51 +0530 Subject: [PATCH 090/319] stale: Run monthly --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 97a2f8e..c97038a 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: "Close stale PR" on: schedule: - - cron: "0 0 * * *" + - cron: "0 0 1 * *" workflow_dispatch: From 9f1a262fe29774b5b62f97edd6aa0d6368432d6b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 17 Jul 2024 21:05:54 +0530 Subject: [PATCH 091/319] eol: Add reason strings for exclusions and add rust-nightly --- .github/scripts/archive_eol.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index adeafc4..6412f1f 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -52,28 +52,48 @@ def main() -> None: # Exclude refs that have EOL notices but are still maintained # in some branch excludes = { + # Maintainer EOLs old branches "com.riverbankcomputing.PyQt.BaseApp", + # 19.08 branch is EOL "org.freedesktop.LinuxAudio.BaseExtension", "org.freedesktop.LinuxAudio.Plugins.LSP", "org.freedesktop.LinuxAudio.Plugins.setBfree", "org.freedesktop.LinuxAudio.Plugins.sfizz", "org.freedesktop.LinuxAudio.Plugins.x42Plugins", "org.freedesktop.LinuxAudio.Plugins.ZamPlugins", + # 1.6 branch is EOL "org.freedesktop.Sdk.Extension.golang", + # 19.08, 20.08, 21.08 are EOL "org.freedesktop.Sdk.Extension.mono6", + # 1.6, 18.08, 19.08 are EOL "org.freedesktop.Sdk.Extension.openjdk8", + # 18.08 is EOL "org.freedesktop.Sdk.Extension.php73", + # 1.6 is EOL "org.freedesktop.Sdk.Extension.rust-stable", + # EOL notice added for special reasons + "org.freedesktop.Sdk.Extension.rust-nightly", + # 19.08, 20.08 are EOL "org.freedesktop.Sdk.Extension.ziglang", + # rename is EOL but github repo is + # case-insensitive "org.gnome.Chess", "org.gnome.GHex", "org.gnome.Quadrapassel", "org.gnome.Tetravex", + # EOL-ed to hide from website "org.kde.kate", + # rename is EOL but github repo is + # case-insensitive "org.kekikakademi.eFatura", + # EOL notice added for special reasons "org.mozilla.firefox.BaseApp", + # rename is EOL but github repo is + # case-insensitive "org.tabos.twofun", + # 3-18.08 is EOL "org.videolan.VLC.Plugin.bdj", + # 3-1.6, 3-18.08 is EOL "org.videolan.VLC.Plugin.fdkaac", } # we need to get apps which are EOL on both supported arches @@ -85,7 +105,9 @@ def main() -> None: if not eols: return - earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(weeks=60) + earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( + weeks=60 + ) count = 0 while count < len(eols): refname = eols[count] From c235d646be8858dc94554965ff6a3c7755a18a43 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 17 Jul 2024 21:19:47 +0530 Subject: [PATCH 092/319] eol: Fix grammar --- .github/scripts/archive_eol.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 6412f1f..142649c 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -75,7 +75,7 @@ def main() -> None: "org.freedesktop.Sdk.Extension.rust-nightly", # 19.08, 20.08 are EOL "org.freedesktop.Sdk.Extension.ziglang", - # rename is EOL but github repo is + # renamed, previous name is EOL but github repo is # case-insensitive "org.gnome.Chess", "org.gnome.GHex", @@ -83,12 +83,12 @@ def main() -> None: "org.gnome.Tetravex", # EOL-ed to hide from website "org.kde.kate", - # rename is EOL but github repo is + # renamed, previous name is EOL but github repo is # case-insensitive "org.kekikakademi.eFatura", # EOL notice added for special reasons "org.mozilla.firefox.BaseApp", - # rename is EOL but github repo is + # renamed, previous name is EOL but github repo is # case-insensitive "org.tabos.twofun", # 3-18.08 is EOL From 31b777cece9f81e7918e2d7e3230f25de3e2f048 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 25 Jul 2024 13:11:44 +0530 Subject: [PATCH 093/319] Update appid domain link --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 607efef..96ccf20 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -15,7 +15,7 @@ -[appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements#control-over-domain +[appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission From 64aa0e9ac35a6a220f38e9dea07d97054a6e8c4b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 14 Sep 2024 08:58:47 +0530 Subject: [PATCH 094/319] Bump cryptography Resolves https://github.com/flathub/flathub/security/dependabot/14 --- .github/actions/merge/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index bcf48db..d496fdd 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile requirements.in +# pip-compile # anyio==4.4.0 # via gql @@ -17,7 +17,7 @@ cffi==1.16.0 # pynacl charset-normalizer==3.3.2 # via requests -cryptography==42.0.8 +cryptography==43.0.1 # via pyjwt deprecated==1.2.14 # via pygithub From 1a30993f2917e30860f0c6fcde81508d2fae99e0 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 09:53:06 +0530 Subject: [PATCH 095/319] gh-ls-org: Don't process untouched repos A repo is considered untouched if it has >= 10 open PRs by flathubbot and no pushes have been made to the default branch in the last 5 weeks --- .../flatpak-external-data-checker/gh-ls-org | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/actions/flatpak-external-data-checker/gh-ls-org b/.github/actions/flatpak-external-data-checker/gh-ls-org index 3c99dda..f0172c0 100755 --- a/.github/actions/flatpak-external-data-checker/gh-ls-org +++ b/.github/actions/flatpak-external-data-checker/gh-ls-org @@ -1,9 +1,11 @@ #!/usr/bin/python3 import argparse +import datetime import os import github +from github.GithubException import GithubException if __name__ == "__main__": usage = ( @@ -14,6 +16,10 @@ if __name__ == "__main__": parser.add_argument("organization", help="name of github organization") args = parser.parse_args() + earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( + weeks=5 + ) + github_token = os.environ['GITHUB_TOKEN'] g = github.Github(github_token, per_page=200) @@ -21,4 +27,24 @@ if __name__ == "__main__": for repo in org.get_repos(): if not repo.archived: + try: + default_branch = repo.default_branch + branch = repo.get_branch(default_branch) + last_commit = repo.get_commit(branch.commit.sha) + last_commit_time = last_commit.commit.committer.date.astimezone( + datetime.timezone.utc + ) + pr_count = [ + pr + for pr in repo.get_pulls(state="open") + if pr.user.login == "flathubbot" + ] + except GithubException: + pr_count = [] + last_commit_time = datetime.datetime.now( + datetime.timezone.utc + ) + datetime.timedelta(seconds=10) + pass + if len(pr_count) >= 10 and last_commit_time < earliest: + continue print(repo.html_url) From bad9b653b5bf06a3a8d23005f83fdd30f163f697 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 09:58:03 +0530 Subject: [PATCH 096/319] entrypoint: Apply shellcheck fixes --- .../flatpak-external-data-checker/entrypoint.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 25a7b6e..7971b4f 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -9,25 +9,25 @@ git config --global user.name "flathubbot" && \ git config --global user.email "sysadmin@flathub.org" mkdir flathub -cd flathub +cd flathub || exit gh-ls-org flathub | parallel "git clone --depth 1 {}" mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u ) -for repo in ${checker_apps[@]}; do +for repo in "${checker_apps[@]}"; do FEDC_OPTS=() if [[ -f $repo/flathub.json ]]; then # check if repo opted out - if ! jq -e '."disable-external-data-checker" | not' < $repo/flathub.json > /dev/null; then + if ! jq -e '."disable-external-data-checker" | not' < "$repo"/flathub.json > /dev/null; then continue fi # check if the app is EOL - if ! jq -e '."end-of-life" or ."end-of-life-rebase" | not' < $repo/flathub.json > /dev/null; then + if ! jq -e '."end-of-life" or ."end-of-life-rebase" | not' < "$repo"/flathub.json > /dev/null; then continue fi # add repo-specified f-e-d-c args - if jq -e '."require-important-update"' < $repo/flathub.json > /dev/null; then + if jq -e '."require-important-update"' < "$repo"/flathub.json > /dev/null; then FEDC_OPTS+=("--require-important-update") fi fi From b75e4b688f513ca6ed323d9f9dea1af2aa2a64d6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 09:58:21 +0530 Subject: [PATCH 097/319] gh-ls-org: Apply black formatting fixes --- .github/actions/flatpak-external-data-checker/gh-ls-org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/gh-ls-org b/.github/actions/flatpak-external-data-checker/gh-ls-org index f0172c0..aa1b879 100755 --- a/.github/actions/flatpak-external-data-checker/gh-ls-org +++ b/.github/actions/flatpak-external-data-checker/gh-ls-org @@ -20,7 +20,7 @@ if __name__ == "__main__": weeks=5 ) - github_token = os.environ['GITHUB_TOKEN'] + github_token = os.environ["GITHUB_TOKEN"] g = github.Github(github_token, per_page=200) org = g.get_organization(args.organization) From f518bfcd278c2bdaaae239661b75ab8cd9b3215e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 09:59:23 +0530 Subject: [PATCH 098/319] entrypoint: Randomise checked repos --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 7971b4f..80bebd0 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -12,7 +12,7 @@ mkdir flathub cd flathub || exit gh-ls-org flathub | parallel "git clone --depth 1 {}" -mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u ) +mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do FEDC_OPTS=() From 5d0c97ee1d1c3516ae53e3e7d4339ee44840099c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 19:36:02 +0530 Subject: [PATCH 099/319] merge: Install pygobject in dockerfile Workaround for: https://github.com/dependabot/dependabot-core/issues/10070 --- .github/actions/merge/Dockerfile | 2 +- .github/actions/merge/requirements.in | 1 - .github/actions/merge/requirements.txt | 14 +++++--------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index cfeda01..a38031e 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get update && \ ADD requirements.txt . RUN python -m venv /venv && \ - /venv/bin/python -m pip install -r requirements.txt + /venv/bin/python -m pip install -r requirements.txt PyGObject FROM python:3.12-slim ENV PATH="/venv/bin:$PATH" diff --git a/.github/actions/merge/requirements.in b/.github/actions/merge/requirements.in index b4a7ffa..cc15727 100644 --- a/.github/actions/merge/requirements.in +++ b/.github/actions/merge/requirements.in @@ -2,4 +2,3 @@ gql[requests] pygit2 PyGithub PyYAML -PyGobject diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index d496fdd..d33610a 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -2,7 +2,7 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile +# pip-compile .github/actions/merge/requirements.in # anyio==4.4.0 # via gql @@ -22,7 +22,7 @@ cryptography==43.0.1 deprecated==1.2.14 # via pygithub gql[requests]==3.5.0 - # via -r requirements.in + # via -r .github/actions/merge/requirements.in graphql-core==3.2.3 # via gql idna==3.7 @@ -32,22 +32,18 @@ idna==3.7 # yarl multidict==6.0.5 # via yarl -pycairo==1.26.1 - # via pygobject pycparser==2.22 # via cffi pygit2==1.15.0 - # via -r requirements.in + # via -r .github/actions/merge/requirements.in pygithub==2.3.0 - # via -r requirements.in -pygobject==3.48.2 - # via -r requirements.in + # via -r .github/actions/merge/requirements.in pyjwt[crypto]==2.8.0 # via pygithub pynacl==1.5.0 # via pygithub pyyaml==6.0.1 - # via -r requirements.in + # via -r .github/actions/merge/requirements.in requests==2.32.3 # via # gql From 7af494e7e7e8ddbe2fec96ff897ba2fb3e329b9e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 18 Sep 2024 21:25:53 +0530 Subject: [PATCH 100/319] Revert "gh-ls-org: Don't process untouched repos" This reverts commit 1a30993f2917e30860f0c6fcde81508d2fae99e0. This hits API limit too frequently --- .../flatpak-external-data-checker/gh-ls-org | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/.github/actions/flatpak-external-data-checker/gh-ls-org b/.github/actions/flatpak-external-data-checker/gh-ls-org index aa1b879..d23a693 100755 --- a/.github/actions/flatpak-external-data-checker/gh-ls-org +++ b/.github/actions/flatpak-external-data-checker/gh-ls-org @@ -1,11 +1,9 @@ #!/usr/bin/python3 import argparse -import datetime import os import github -from github.GithubException import GithubException if __name__ == "__main__": usage = ( @@ -16,10 +14,6 @@ if __name__ == "__main__": parser.add_argument("organization", help="name of github organization") args = parser.parse_args() - earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( - weeks=5 - ) - github_token = os.environ["GITHUB_TOKEN"] g = github.Github(github_token, per_page=200) @@ -27,24 +21,4 @@ if __name__ == "__main__": for repo in org.get_repos(): if not repo.archived: - try: - default_branch = repo.default_branch - branch = repo.get_branch(default_branch) - last_commit = repo.get_commit(branch.commit.sha) - last_commit_time = last_commit.commit.committer.date.astimezone( - datetime.timezone.utc - ) - pr_count = [ - pr - for pr in repo.get_pulls(state="open") - if pr.user.login == "flathubbot" - ] - except GithubException: - pr_count = [] - last_commit_time = datetime.datetime.now( - datetime.timezone.utc - ) + datetime.timedelta(seconds=10) - pass - if len(pr_count) >= 10 and last_commit_time < earliest: - continue print(repo.html_url) From b5e9fe9afc26f6eb214d0acc23d1ea328a9b4ffc Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 08:41:49 +0530 Subject: [PATCH 101/319] archive_eol: Set a description before archiving --- .github/scripts/archive_eol.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 142649c..65ab0a1 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -119,6 +119,8 @@ def main() -> None: repo.html_url, repo.pushed_at.isoformat(), earliest.isoformat() ) ) + desc = "This repo is archived as the app is EOL." + repo.edit(description=desc) repo.edit(archived=True) except UnknownObjectException: pass From fe7035367c003296bfcc059c68be1e718baa3785 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 08:52:18 +0530 Subject: [PATCH 102/319] archive_eol: Use last commit time on default branch instead of pushed_at pushed_at counts all branches so if x-checker is making new PRs it won't be countted even if the repo is inactive --- .github/scripts/archive_eol.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 65ab0a1..6c69e6c 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -113,15 +113,24 @@ def main() -> None: refname = eols[count] try: repo = g.get_repo(f"flathub/{refname}") - if not repo.archived and repo.pushed_at < earliest: - print( - "Archiving: {} Repo is in EOL list. Last push: {}, earlier than: {}".format( - repo.html_url, repo.pushed_at.isoformat(), earliest.isoformat() - ) + if not repo.archived: + default_branch = repo.default_branch + branch = repo.get_branch(default_branch) + last_commit = repo.get_commit(branch.commit.sha) + last_commit_time = last_commit.commit.committer.date.astimezone( + datetime.timezone.utc ) - desc = "This repo is archived as the app is EOL." - repo.edit(description=desc) - repo.edit(archived=True) + if last_commit_time < earliest: + print( + "Archiving: {} Repo is in EOL list. Last push: {}, earlier than: {}".format( + repo.html_url, + last_commit_time.isoformat(), + earliest.isoformat(), + ) + ) + desc = "This repo is archived as the app is EOL." + repo.edit(description=desc) + repo.edit(archived=True) except UnknownObjectException: pass except RateLimitExceededException: From 8eae8bfc9ec299e57f28b39967122a8793da433f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 09:02:19 +0530 Subject: [PATCH 103/319] archive_eol: Make description more descriptive --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 6c69e6c..127ead9 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -128,7 +128,7 @@ def main() -> None: earliest.isoformat(), ) ) - desc = "This repo is archived as the app is EOL." + desc = "This repo is archived by Flathub as the app is EOL. If this was done in error, please open an issue at https://github.com/flathub/flathub/issues" repo.edit(description=desc) repo.edit(archived=True) except UnknownObjectException: From a25236ac64ecbf155315d26e7b0d9fe1adc1e017 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 09:15:36 +0530 Subject: [PATCH 104/319] archive_eol: Add more LinuxAudio plugins to exceptions --- .github/scripts/archive_eol.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 127ead9..6dbd6b8 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -61,6 +61,24 @@ def main() -> None: "org.freedesktop.LinuxAudio.Plugins.sfizz", "org.freedesktop.LinuxAudio.Plugins.x42Plugins", "org.freedesktop.LinuxAudio.Plugins.ZamPlugins", + "org.freedesktop.LinuxAudio.Plugins.gmsynth", + "org.freedesktop.LinuxAudio.Plugins.CAPS", + "org.freedesktop.LinuxAudio.Plugins.CAPS", + "org.freedesktop.LinuxAudio.Plugins.VL1Emulator", + "org.freedesktop.LinuxAudio.Plugins.ZynFusion", + "org.freedesktop.LinuxAudio.Plugins.CMT", + "org.freedesktop.LinuxAudio.Plugins.DrumGizmo", + "org.freedesktop.LinuxAudio.Plugins.TAP", + "org.freedesktop.LinuxAudio.Plugins.SoSynthLV2", + "org.freedesktop.LinuxAudio.Plugins.Surge", + "org.freedesktop.LinuxAudio.Plugins.DPF-Plugins", + "org.freedesktop.LinuxAudio.Plugins.DISTRHO-Ports", + "org.freedesktop.LinuxAudio.Plugins.MDA", + "org.freedesktop.LinuxAudio.Plugins.Ninjas2", + "org.freedesktop.LinuxAudio.Plugins.reMID-lv2", + "org.freedesktop.LinuxAudio.Plugins.swh", + "org.freedesktop.LinuxAudio.Plugins.GxPlugins", + "org.freedesktop.LinuxAudio.Plugins.KapitonovPluginsPack", # 1.6 branch is EOL "org.freedesktop.Sdk.Extension.golang", # 19.08, 20.08, 21.08 are EOL From 5e109e4918bfcbe1464608b3e95d6a2395c0fa94 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 09:35:33 +0530 Subject: [PATCH 105/319] archive_eol: Handle githubexception when getting last commit time --- .github/scripts/archive_eol.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 6dbd6b8..49e7d5d 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -4,7 +4,11 @@ import subprocess import time import github -from github.GithubException import RateLimitExceededException, UnknownObjectException +from github.GithubException import ( + RateLimitExceededException, + UnknownObjectException, + GithubException, +) def ignore_ref(ref: str) -> bool: @@ -132,12 +136,18 @@ def main() -> None: try: repo = g.get_repo(f"flathub/{refname}") if not repo.archived: - default_branch = repo.default_branch - branch = repo.get_branch(default_branch) - last_commit = repo.get_commit(branch.commit.sha) - last_commit_time = last_commit.commit.committer.date.astimezone( - datetime.timezone.utc - ) + try: + default_branch = repo.default_branch + branch = repo.get_branch(default_branch) + last_commit = repo.get_commit(branch.commit.sha) + last_commit_time = last_commit.commit.committer.date.astimezone( + datetime.timezone.utc + ) + except GithubException: + last_commit_time = datetime.datetime.now( + datetime.timezone.utc + ) + datetime.timedelta(seconds=10) + pass if last_commit_time < earliest: print( "Archiving: {} Repo is in EOL list. Last push: {}, earlier than: {}".format( From c86f3cfb2a7ddc621812031050a261ba4df1f055 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 09:42:42 +0530 Subject: [PATCH 106/319] archive_eol: Handle beta refs too and remove restriction on arches --- .github/scripts/archive_eol.py | 11 ++++++----- .github/workflows/archive.yml | 1 + 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 49e7d5d..17357da 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -118,11 +118,12 @@ def main() -> None: # 3-1.6, 3-18.08 is EOL "org.videolan.VLC.Plugin.fdkaac", } - # we need to get apps which are EOL on both supported arches - # as there are apps which are only EOL on one arch but maintained - # in another. This might miss some refs but LBYL! - stable = get_eol_refs("x86_64", "flathub") & get_eol_refs("aarch64", "flathub") - eols = list(stable - excludes) + + stable = get_eol_refs("x86_64", "flathub") | get_eol_refs("aarch64", "flathub") + beta = get_eol_refs("x86_64", "flathub-beta") | get_eol_refs( + "aarch64", "flathub-beta" + ) + eols = list((stable | beta) - excludes) if not eols: return diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 66983c7..04fb1c4 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -23,6 +23,7 @@ jobs: - name: Set up Flathub remotes run: | flatpak remote-add --user --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo + flatpak remote-add --user --if-not-exists flathub-beta https://flathub.org/beta-repo/flathub-beta.flatpakrepo - name: Run EOL script run: python3 .github/scripts/archive_eol.py From 57a39a7c2b1e1a1d8e93c0675ada1cd553d7b472 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 09:54:01 +0530 Subject: [PATCH 107/319] archive_eol: Add some more excludes --- .github/scripts/archive_eol.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 17357da..f054148 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -83,6 +83,10 @@ def main() -> None: "org.freedesktop.LinuxAudio.Plugins.swh", "org.freedesktop.LinuxAudio.Plugins.GxPlugins", "org.freedesktop.LinuxAudio.Plugins.KapitonovPluginsPack", + "org.freedesktop.LinuxAudio.Plugins.ArtyFX", + "org.freedesktop.LinuxAudio.Plugins.Sorcer", + "org.freedesktop.LinuxAudio.Plugins.ADLplug", + "org.freedesktop.LinuxAudio.Plugins.Fabla", # 1.6 branch is EOL "org.freedesktop.Sdk.Extension.golang", # 19.08, 20.08, 21.08 are EOL From 9e9a8d6fcde85415e71ec0602ff1696b9a7d70f4 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 21:22:37 +0530 Subject: [PATCH 108/319] entrypoint: Prevent flatpak-external-data-checker from failing on a repo Since we are checking all repos in a loop and fedc can fail on incorrect x-checker paras or git errors when branching, exiting early means some repos won't get checked. So ignore errors for this command --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 80bebd0..da09932 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -43,5 +43,5 @@ for repo in "${checker_apps[@]}"; do fi echo "==> checking ${repo}" - /app/flatpak-external-data-checker --verbose --update "${FEDC_OPTS[@]}" "$repo/$manifest" + /app/flatpak-external-data-checker --verbose --update "${FEDC_OPTS[@]}" "$repo/$manifest" || true done From 72b6ff12b6a9642044c5175e1676c4e41f49397d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 20 Sep 2024 21:18:39 +0530 Subject: [PATCH 109/319] Add script to archive orphaned repos --- .github/scripts/archive_orphan.py | 61 +++++++++++++++++++++++++++++++ .github/workflows/archive.yml | 3 ++ 2 files changed, 64 insertions(+) create mode 100644 .github/scripts/archive_orphan.py diff --git a/.github/scripts/archive_orphan.py b/.github/scripts/archive_orphan.py new file mode 100644 index 0000000..56c58a1 --- /dev/null +++ b/.github/scripts/archive_orphan.py @@ -0,0 +1,61 @@ +import datetime +import os +import time + +import github +from github.GithubException import ( + RateLimitExceededException, + GithubException, +) + + +def main() -> None: + + token = os.environ["GITHUB_TOKEN"] + g = github.Github(auth=github.Auth.Token(token)) + + org = g.get_organization("flathub") + + excludes = {} + + earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( + weeks=60 + ) + + for repo in org.get_repos(): + if not repo.archived: + try: + default_branch = repo.default_branch + branch = repo.get_branch(default_branch) + last_commit = repo.get_commit(branch.commit.sha) + last_commit_time = last_commit.commit.committer.date.astimezone( + datetime.timezone.utc + ) + collaborators = repo.get_collaborators(affiliation="direct") + colb_count = collaborators.totalCount + except GithubException: + last_commit_time = datetime.datetime.now( + datetime.timezone.utc + ) + datetime.timedelta(seconds=10) + colb_count = 1 + pass + except RateLimitExceededException: + print("Rate limited") + time.sleep(g.rate_limiting_resettime - time.time() + 10) + continue + + if colb_count == 0 and last_commit_time < earliest: + print( + "Archiving: {} Repo has no collaborators. Last push: {}, earlier than: {}".format( + repo.html_url, + last_commit_time.isoformat(), + earliest.isoformat(), + ) + ) + desc = "This repo is archived by Flathub as it is orphaned. If this was done in error or you wish to maintain it, please open an issue at https://github.com/flathub/flathub/issues" + repo.edit(description=desc) + repo.edit(archived=True) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 04fb1c4..5a2b54a 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -27,3 +27,6 @@ jobs: - name: Run EOL script run: python3 .github/scripts/archive_eol.py + + - name: Run orphan script + run: python3 .github/scripts/archive_orphan.py From 24342ff9ad7f75efd7db5ee931904b87abe35910 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 22 Sep 2024 09:57:12 +0530 Subject: [PATCH 110/319] x-checker: Use gh to get repos --- .github/actions/flatpak-external-data-checker/Dockerfile | 2 +- .github/actions/flatpak-external-data-checker/entrypoint.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/flatpak-external-data-checker/Dockerfile b/.github/actions/flatpak-external-data-checker/Dockerfile index eb3fc6d..f16c226 100644 --- a/.github/actions/flatpak-external-data-checker/Dockerfile +++ b/.github/actions/flatpak-external-data-checker/Dockerfile @@ -1,7 +1,7 @@ FROM ghcr.io/flathub/flatpak-external-data-checker:latest RUN apt-get update && \ - apt-get install -y parallel && \ + apt-get install -y gh jq parallel && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ADD gh-ls-org /usr/local/bin/gh-ls-org diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index da09932..7ec5b41 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -11,7 +11,7 @@ git config --global user.email "sysadmin@flathub.org" mkdir flathub cd flathub || exit -gh-ls-org flathub | parallel "git clone --depth 1 {}" +gh repo list flathub --visibility public -L 8000 --json url --json isArchived --jq '.[] | select(.isArchived == false)|.url' | parallel "git clone --depth 1 {}" mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do From 6b819f6f7e2a98ef5f79145b75317b54c4f2112c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 8 Oct 2024 08:56:19 +0530 Subject: [PATCH 111/319] archive_eol: Remove rust-nightly --- .github/scripts/archive_eol.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index f054148..9a0c3a1 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -97,8 +97,6 @@ def main() -> None: "org.freedesktop.Sdk.Extension.php73", # 1.6 is EOL "org.freedesktop.Sdk.Extension.rust-stable", - # EOL notice added for special reasons - "org.freedesktop.Sdk.Extension.rust-nightly", # 19.08, 20.08 are EOL "org.freedesktop.Sdk.Extension.ziglang", # renamed, previous name is EOL but github repo is From 5d60ae55a334d00d6d1c63280a551967ccb92373 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 15 Oct 2024 18:55:28 +0530 Subject: [PATCH 112/319] ci: Set timeout minutes for some jobs that are likely to hang --- .github/workflows/archive.yml | 1 + .github/workflows/external-data-checker.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 5a2b54a..bcd3e2b 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -9,6 +9,7 @@ jobs: archive: name: Archive EOL repositories runs-on: ubuntu-latest + timeout-minutes: 120 env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} steps: diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 1bb03ee..19c673d 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -8,6 +8,7 @@ on: jobs: flathub-data-checker-global: runs-on: ubuntu-latest + timeout-minutes: 120 steps: - uses: actions/checkout@v4 From b1394321a58aef78ec11a57c60fa9e65e3543de9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 24 Oct 2024 08:53:39 +0530 Subject: [PATCH 113/319] merge: Trigger only on PRs and if actor is reviewer --- .github/actions/merge/Dockerfile | 2 +- .github/workflows/merge.yml | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index a38031e..32821f0 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -14,7 +14,7 @@ ENV PATH="/venv/bin:$PATH" RUN apt-get update && \ apt-get install -y --no-install-recommends \ - git libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ + git gh libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ apt-get clean && rm -rf /var/lib/apt/lists/* COPY --from=builder /venv /venv diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index e14ef45..d4cd311 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -9,9 +9,21 @@ on: jobs: merge: runs-on: ubuntu-latest + if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: image: ghcr.io/flathub/actions/merge:latest steps: - - run: /app/entrypoint.py + - name: Check if actor is reviewer + run: | + if gh api /orgs/${{ github.repository_owner }}/teams/reviewers/memberships/${{ github.actor }} --silent; then + echo "IS_REVIEWER=true" >> "$GITHUB_ENV" + else + echo "IS_REVIEWER=false" >> "$GITHUB_ENV" + fi + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + + - run: /app/entrypoint.py + if: env.IS_REVIEWER == 'true' env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 49c808e0bccce3088661e854a71dc1374ec6a33e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 31 Oct 2024 17:49:52 +0530 Subject: [PATCH 114/319] Disable the orphan script The initial set of repos were archived and running this causes too many API requests. We can run it again manually if needed. --- .github/workflows/archive.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index bcd3e2b..12bb309 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -30,4 +30,5 @@ jobs: run: python3 .github/scripts/archive_eol.py - name: Run orphan script + if: false run: python3 .github/scripts/archive_orphan.py From d31d9a132f41cc409df36a82abfef214190bae9b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 21:53:55 +0530 Subject: [PATCH 115/319] Add action to close PRs against master --- .github/workflows/close-master-prs.yaml | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/close-master-prs.yaml diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml new file mode 100644 index 0000000..ec9e358 --- /dev/null +++ b/.github/workflows/close-master-prs.yaml @@ -0,0 +1,30 @@ +name: Close PRs to master + +on: + pull_request: + types: [opened, reopened, synchronize] + branches: + - master + +jobs: + close: + runs-on: ubuntu-latest + steps: + - name: Check if PR author is an org member and PR does not have no-close label + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + ORG_NAME: ${{ github.repository_owner }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + run: | + has_label=$(gh pr view ${{ github.event.pull_request.number }} --json labels -q '.labels | any(.name == "master-leave-open")') + + if [[ "$has_label" != "true" ]]; then + if gh api orgs/$ORG_NAME/members/$PR_AUTHOR --silent; then + echo "User $PR_AUTHOR is a member of $ORG_NAME. Skipping" + else + echo "User $PR_AUTHOR is not a member of $ORG_NAME and no 'master-leave-open' label is found. Closing PR." + gh pr close ${{ github.event.pull_request.number }} -c "This PR is automatically closed because submission PRs must be made against the new-pr branch. If this is done in error, please comment!" + fi + else + echo "PR has 'master-leave-open' label. Skipping" + fi From c1891e430d67a36942fe5d4d63970ed2d699b6e8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 22:14:59 +0530 Subject: [PATCH 116/319] ci: Fix close-master-prs action --- .github/workflows/close-master-prs.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index ec9e358..9af3518 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -5,14 +5,15 @@ on: types: [opened, reopened, synchronize] branches: - master + workflow_dispatch: jobs: close: runs-on: ubuntu-latest steps: - - name: Check if PR author is an org member and PR does not have no-close label + - name: Check and close env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} ORG_NAME: ${{ github.repository_owner }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} run: | From 5fb56b36a2976cc70f7ee576fb30b7e80a78d03d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 22:21:28 +0530 Subject: [PATCH 117/319] ci: Use checkout action --- .github/workflows/close-master-prs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index 9af3518..270ba5c 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -11,6 +11,7 @@ jobs: close: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 - name: Check and close env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 5adfa46c165b38e657a2d86d01c52b7e34c9bb4f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:21:22 +0530 Subject: [PATCH 118/319] ci: Try to fix close workflow again --- .github/workflows/close-master-prs.yaml | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index 270ba5c..e79dba9 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -7,26 +7,30 @@ on: - master workflow_dispatch: +permissions: + pull-requests: write + jobs: close: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - name: Check and close env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - ORG_NAME: ${{ github.repository_owner }} - PR_AUTHOR: ${{ github.event.pull_request.user.login }} + COMMENT: > + This PR is automatically closed because application submission + PRs must be made against the new-pr branch. If this is done + in error, please comment or reopen! + REPO: flathub/flathub run: | - has_label=$(gh pr view ${{ github.event.pull_request.number }} --json labels -q '.labels | any(.name == "master-leave-open")') + has_label=$(gh pr --repo "$REPO" view ${{ github.event.pull_request.number }} --json labels -q '.labels | any(.name == "leave-open")') if [[ "$has_label" != "true" ]]; then - if gh api orgs/$ORG_NAME/members/$PR_AUTHOR --silent; then + if gh api orgs/${{ github.repository_owner }}/members/${{ github.event.pull_request.user.login }} --silent; then echo "User $PR_AUTHOR is a member of $ORG_NAME. Skipping" else - echo "User $PR_AUTHOR is not a member of $ORG_NAME and no 'master-leave-open' label is found. Closing PR." - gh pr close ${{ github.event.pull_request.number }} -c "This PR is automatically closed because submission PRs must be made against the new-pr branch. If this is done in error, please comment!" - fi + echo "User $PR_AUTHOR is not a member of $ORG_NAME and no 'leave-open' label is found" + gh pr --repo "$REPO" close ${{ github.event.pull_request.number }} -c "$COMMENT" else - echo "PR has 'master-leave-open' label. Skipping" + echo "PR has 'leave-open' label. Skipping" fi From 71c0ac4d56828178c1dceb8e4be192e8a6c9d0dc Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:27:39 +0530 Subject: [PATCH 119/319] ci: Fix the action again --- .github/workflows/close-master-prs.yaml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index e79dba9..e013ef4 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -23,14 +23,10 @@ jobs: in error, please comment or reopen! REPO: flathub/flathub run: | - has_label=$(gh pr --repo "$REPO" view ${{ github.event.pull_request.number }} --json labels -q '.labels | any(.name == "leave-open")') + has_label=$(gh pr --repo "$REPO" view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') if [[ "$has_label" != "true" ]]; then - if gh api orgs/${{ github.repository_owner }}/members/${{ github.event.pull_request.user.login }} --silent; then - echo "User $PR_AUTHOR is a member of $ORG_NAME. Skipping" - else - echo "User $PR_AUTHOR is not a member of $ORG_NAME and no 'leave-open' label is found" - gh pr --repo "$REPO" close ${{ github.event.pull_request.number }} -c "$COMMENT" - else - echo "PR has 'leave-open' label. Skipping" + if ! gh api orgs/${{ github.repository_owner }}/members/${{ github.event.pull_request.user.login }} --silent; then + gh pr --repo "$REPO" close "${{ github.event.pull_request.number }}" -c "$COMMENT" + fi fi From b283052b62c602a71a81c85981b81d8028fc6fc9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:36:44 +0530 Subject: [PATCH 120/319] ci: Use FLATHUBBOT_TOKEN For forks of public repos, github removes the ability to comment on a PR --- .github/workflows/close-master-prs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index e013ef4..805ac86 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -2,7 +2,7 @@ name: Close PRs to master on: pull_request: - types: [opened, reopened, synchronize] + types: [opened, reopened, synchronize, edited] branches: - master workflow_dispatch: @@ -16,7 +16,7 @@ jobs: steps: - name: Check and close env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done From b8e57130f09094942407729a1ae928403ec469c5 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:40:45 +0530 Subject: [PATCH 121/319] ci: Try to set env correctly --- .github/workflows/close-master-prs.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index 805ac86..0db2e91 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -15,13 +15,6 @@ jobs: runs-on: ubuntu-latest steps: - name: Check and close - env: - GH_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} - COMMENT: > - This PR is automatically closed because application submission - PRs must be made against the new-pr branch. If this is done - in error, please comment or reopen! - REPO: flathub/flathub run: | has_label=$(gh pr --repo "$REPO" view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') @@ -30,3 +23,10 @@ jobs: gh pr --repo "$REPO" close "${{ github.event.pull_request.number }}" -c "$COMMENT" fi fi + env: + GH_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + COMMENT: > + This PR is automatically closed because application submission + PRs must be made against the new-pr branch. If this is done + in error, please comment or reopen! + REPO: flathub/flathub From 9c68f7f2fc29d2a0ec73bf150ec738a1d61061d6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:46:01 +0530 Subject: [PATCH 122/319] Try setting GITHUB_TOKEN instead --- .github/workflows/close-master-prs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index 0db2e91..3530bbf 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -24,7 +24,7 @@ jobs: fi fi env: - GH_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done From a4ef2f73097a40fcdfb36aae4ffa5bf0eb58da47 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 1 Nov 2024 23:59:00 +0530 Subject: [PATCH 123/319] fix --- .github/workflows/close-master-prs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yaml index 3530bbf..b82658b 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yaml @@ -25,8 +25,8 @@ jobs: fi env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + REPO: bbhtt/flathub COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done in error, please comment or reopen! - REPO: flathub/flathub From d8171185d33cf8ab704c38264c3a046d7590141c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:02:10 +0530 Subject: [PATCH 124/319] ci: Fix workflow file name --- .../workflows/{close-master-prs.yaml => close-master-prs.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{close-master-prs.yaml => close-master-prs.yml} (96%) diff --git a/.github/workflows/close-master-prs.yaml b/.github/workflows/close-master-prs.yml similarity index 96% rename from .github/workflows/close-master-prs.yaml rename to .github/workflows/close-master-prs.yml index b82658b..e513b30 100644 --- a/.github/workflows/close-master-prs.yaml +++ b/.github/workflows/close-master-prs.yml @@ -25,7 +25,7 @@ jobs: fi env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} - REPO: bbhtt/flathub + REPO: flathub/flathub COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done From e44a62ba3ad4380a0cea4dd548ae2c42667da639 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:12:29 +0530 Subject: [PATCH 125/319] ci: Use pull_request_target event --- .github/workflows/close-master-prs.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index e513b30..f835706 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -1,10 +1,12 @@ name: Close PRs to master on: - pull_request: + pull_request_target: types: [opened, reopened, synchronize, edited] branches: - master + branches-ignore: + - new-pr workflow_dispatch: permissions: @@ -24,7 +26,7 @@ jobs: fi fi env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: flathub/flathub COMMENT: > This PR is automatically closed because application submission From 05b2d056a36d793e77272775c46d8f85e35dbc8e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:13:33 +0530 Subject: [PATCH 126/319] ci: Drop branches-ignore --- .github/workflows/close-master-prs.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index f835706..08a75a6 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -5,8 +5,6 @@ on: types: [opened, reopened, synchronize, edited] branches: - master - branches-ignore: - - new-pr workflow_dispatch: permissions: From ae28b43a242e94efbf9d0afedb065e20760e4857 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:26:46 +0530 Subject: [PATCH 127/319] ci: Drop membership checking This won't work with repo's access token and members can set the label when making the PR --- .github/workflows/close-master-prs.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index 08a75a6..0ec1ef0 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -17,11 +17,9 @@ jobs: - name: Check and close run: | has_label=$(gh pr --repo "$REPO" view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') - if [[ "$has_label" != "true" ]]; then - if ! gh api orgs/${{ github.repository_owner }}/members/${{ github.event.pull_request.user.login }} --silent; then + echo "leave-open label not found. Closing." gh pr --repo "$REPO" close "${{ github.event.pull_request.number }}" -c "$COMMENT" - fi fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 764b4410b12e9126109f1a76817d227d97f4c7a8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:28:35 +0530 Subject: [PATCH 128/319] ci: Add a warning --- .github/workflows/close-master-prs.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index 0ec1ef0..a03f215 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -1,5 +1,8 @@ name: Close PRs to master +# DO NOT RUN ANY CODE OR CHECKOUT OR USE ORG SECRETS HERE +# pull_request_target RUNS ON PUBLIC FORKS IN REPO'S CONTEXT + on: pull_request_target: types: [opened, reopened, synchronize, edited] From 1ebc3261aeb14ea30ee63d434a22fdfeb7c211d7 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 00:55:26 +0530 Subject: [PATCH 129/319] ci: Fix message --- .github/workflows/close-master-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index a03f215..3655344 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -30,4 +30,4 @@ jobs: COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done - in error, please comment or reopen! + in error, please comment. From c95ce4b7325ed0b9a9609ef78e7e485cec0e58b9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 01:22:57 +0530 Subject: [PATCH 130/319] ci: Add action to lock closed PRs --- .github/workflows/lock-prs.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/lock-prs.yml diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml new file mode 100644 index 0000000..0ccb6c9 --- /dev/null +++ b/.github/workflows/lock-prs.yml @@ -0,0 +1,24 @@ +name: "Lock closed PRs" + +on: + schedule: + - cron: "0 */8 * * *" + workflow_dispatch: + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - name: Install dependencies + run: sudo apt-get update && sudo apt install -y jq + + - name: Lock closed PRs + run: | + cmd=$(gh pr list --repo "$REPO" -L 100 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number') + + for num in $cmd; do + gh pr lock --repo "$REPO" --reason "resolved" "$num" + done + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + REPO: flathub/flathub From ef5769ecd3e105011f127b079daa52c9f4b19794 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 07:29:42 +0530 Subject: [PATCH 131/319] ci: Lock only if it was not locked before --- .github/workflows/lock-prs.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 0ccb6c9..8c4bdde 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -17,7 +17,9 @@ jobs: cmd=$(gh pr list --repo "$REPO" -L 100 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number') for num in $cmd; do - gh pr lock --repo "$REPO" --reason "resolved" "$num" + if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then + gh pr lock --repo "$REPO" --reason "resolved" "$num" + fi done env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From f745e4650ffbb4bf4c5efecba7bfc3f621f70b41 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 07:31:42 +0530 Subject: [PATCH 132/319] ci: jq is available already --- .github/workflows/lock-prs.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 8c4bdde..93d35d9 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -9,15 +9,13 @@ jobs: lock: runs-on: ubuntu-latest steps: - - name: Install dependencies - run: sudo apt-get update && sudo apt install -y jq - - name: Lock closed PRs run: | cmd=$(gh pr list --repo "$REPO" -L 100 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number') for num in $cmd; do if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then + echo "Locking pull request $num" gh pr lock --repo "$REPO" --reason "resolved" "$num" fi done From f2c0e44dc94d9c7560be6055b1b963490d248b92 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 08:44:00 +0530 Subject: [PATCH 133/319] stale: Use any-of-pr-labels only-lables requires having all the labels in the PR --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index c97038a..7550124 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -17,5 +17,5 @@ jobs: days-before-close: -1 days-before-pr-stale: 365 days-before-pr-close: 30 - only-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream + any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true From cc1f85e2d93fa2ee7af623e8b95d35c5a1377681 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 08:51:43 +0530 Subject: [PATCH 134/319] stale: Increase operations per run --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 7550124..5342623 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -19,3 +19,4 @@ jobs: days-before-pr-close: 30 any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true + operations-per-run: 100 From 5b590293e49fe6b257bbf18472aedfb0c94bd382 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 09:00:26 +0530 Subject: [PATCH 135/319] stale: change message --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5342623..e4e301f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,11 +12,12 @@ jobs: - uses: actions/stale@v9 with: repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} - stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. Feel free to re-open it if you plan to continue working on that pull request or think it deserves attention from Flathub admins" + stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment saying so." days-before-stale: -1 days-before-close: -1 days-before-pr-stale: 365 days-before-pr-close: 30 any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true + exempt-pr-labels: leave-open operations-per-run: 100 From 947c269bfedbacfe49ab633a3c766021448643fd Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 09:02:53 +0530 Subject: [PATCH 136/319] stale: Run twice weekly and reduce operations-per-run --- .github/workflows/stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e4e301f..e12973d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: "Close stale PR" on: schedule: - - cron: "0 0 1 * *" + - cron: "0 0 * * 1,4" workflow_dispatch: @@ -20,4 +20,4 @@ jobs: any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true exempt-pr-labels: leave-open - operations-per-run: 100 + operations-per-run: 10 From 10aac87c568ff8f118c25b5c0210051a5983f2e9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 09:42:54 +0530 Subject: [PATCH 137/319] lock-prs: Exempt locking prs marked as stale --- .github/workflows/lock-prs.yml | 6 ++++-- .github/workflows/stale.yml | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 93d35d9..46fef9b 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -15,8 +15,10 @@ jobs: for num in $cmd; do if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then - echo "Locking pull request $num" - gh pr lock --repo "$REPO" --reason "resolved" "$num" + if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^Stale$" + echo "Locking pull request $num" + gh pr lock --repo "$REPO" --reason "resolved" "$num" + fi fi done env: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e12973d..71c934b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/stale@v9 with: repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} - stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment saying so." + stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment or re-open the PR." days-before-stale: -1 days-before-close: -1 days-before-pr-stale: 365 From d163baee7120443b41c4fdb7c0b404c1a06a88af Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 09:45:42 +0530 Subject: [PATCH 138/319] lock-prs: Fix syntax error --- .github/workflows/lock-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 46fef9b..bfa581e 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -15,7 +15,7 @@ jobs: for num in $cmd; do if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then - if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^Stale$" + if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^Stale$"; then echo "Locking pull request $num" gh pr lock --repo "$REPO" --reason "resolved" "$num" fi From 27d515572e3ba9ba5b98a48b1ed31e84a8757b80 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 09:51:16 +0530 Subject: [PATCH 139/319] lock-prs: Get all updated PRs then filter to first 100 --- .github/workflows/lock-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index bfa581e..eb42a70 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Lock closed PRs run: | - cmd=$(gh pr list --repo "$REPO" -L 100 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number') + cmd=$(gh pr list --repo "$REPO" -L 100000 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number'|head -n 100) for num in $cmd; do if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then From cbd6812c9c2d71e142ebea5a13061a436466844f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 10:02:44 +0530 Subject: [PATCH 140/319] lock-prs: Use the locked field --- .github/workflows/lock-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index eb42a70..17cbe0c 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -14,7 +14,7 @@ jobs: cmd=$(gh pr list --repo "$REPO" -L 100000 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number'|head -n 100) for num in $cmd; do - if [ "$(gh api repos/$REPO/issues/$num --jq '.active_lock_reason'| wc -c)" -le 1 ]; then + if [ "$(gh api repos/$REPO/issues/$num --jq '.locked')" = "false" ]; then if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^Stale$"; then echo "Locking pull request $num" gh pr lock --repo "$REPO" --reason "resolved" "$num" From 6f288aa41d2b807a913b4be7cb319eb3f85df847 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 12:42:02 +0530 Subject: [PATCH 141/319] Add more warnings to PR template --- .github/pull_request_template.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 96ccf20..41010b1 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,19 +1,18 @@ - + + + ### Please confirm your submission meets all the criteria - - -- [ ] Please describe the application briefly. - + +- [ ] Please describe the application briefly. - [ ] The domain used for the application ID is [controlled by the application developers][appid-domain] and the [application id guidelines][appid] are followed. - [ ] I have read the and followed all the [Submission and licence requirements][reqs]. - [ ] I have [built][build] and tested the submission locally. - [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about this submission. **Link:** - - + [appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id From f31a17dbdf8ef62928d3fbcec06c4480cfc21084 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 2 Nov 2024 12:44:29 +0530 Subject: [PATCH 142/319] Fix some spaces in the template --- .github/pull_request_template.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 41010b1..1228b44 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ - + @@ -8,11 +8,11 @@ - [ ] Please describe the application briefly. - [ ] The domain used for the application ID is [controlled by the application developers][appid-domain] and the [application id guidelines][appid] are followed. -- [ ] I have read the and followed all the [Submission and licence requirements][reqs]. +- [ ] I have read and followed all the [Submission and licence requirements][reqs]. - [ ] I have [built][build] and tested the submission locally. -- [ ] I am an author/developer/upstream contributor of the project. If not, I contacted upstream developers about this submission. **Link:** +- [ ] I am an author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** - + [appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id From 6c695ce4067995cff6d6740b4f0d5909f965264b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 3 Nov 2024 09:59:38 +0530 Subject: [PATCH 143/319] Use github token and allow workflow_call --- .github/workflows/lock-prs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 17cbe0c..62ca306 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -4,6 +4,7 @@ on: schedule: - cron: "0 */8 * * *" workflow_dispatch: + workflow_call: jobs: lock: @@ -22,5 +23,5 @@ jobs: fi done env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO: flathub/flathub From 626c65dedb3509f8d0db42e224620c0172d1df57 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 3 Nov 2024 10:50:50 +0530 Subject: [PATCH 144/319] Add a helper image when closing --- .github/images/pr_image.png | Bin 0 -> 80765 bytes .github/workflows/close-master-prs.yml | 1 + 2 files changed, 1 insertion(+) create mode 100644 .github/images/pr_image.png diff --git a/.github/images/pr_image.png b/.github/images/pr_image.png new file mode 100644 index 0000000000000000000000000000000000000000..0408cabcba104340ac61bdc4f7f58dbe19742635 GIT binary patch literal 80765 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 H6h-@2QTB7HG8& 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 Date: Tue, 5 Nov 2024 08:12:39 +0530 Subject: [PATCH 145/319] x-checker: Add a concurrency key to prevent multiple runs racing against each other --- .github/workflows/external-data-checker.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 19c673d..89848ca 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -5,6 +5,10 @@ on: workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + jobs: flathub-data-checker-global: runs-on: ubuntu-latest From 80defad9386d2a1ee1b8b49c3a415928140537d1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 5 Nov 2024 08:35:39 +0530 Subject: [PATCH 146/319] stale: Bump operations until we get rid of largest batch --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 71c934b..d1b68f7 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -20,4 +20,4 @@ jobs: any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true exempt-pr-labels: leave-open - operations-per-run: 10 + operations-per-run: 100 From bd94df47abdf98bb6bff06b17a77ae1aed0d9884 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 6 Nov 2024 21:27:18 +0530 Subject: [PATCH 147/319] lock-prs: Respect leave-open label too --- .github/workflows/lock-prs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 62ca306..bcfd067 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -2,7 +2,7 @@ name: "Lock closed PRs" on: schedule: - - cron: "0 */8 * * *" + - cron: "0 */6 * * *" workflow_dispatch: workflow_call: @@ -16,7 +16,7 @@ jobs: for num in $cmd; do if [ "$(gh api repos/$REPO/issues/$num --jq '.locked')" = "false" ]; then - if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^Stale$"; then + if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^(Stale|leave-open)$"; then echo "Locking pull request $num" gh pr lock --repo "$REPO" --reason "resolved" "$num" fi From db3e106060ac8f51bbab0cea9da9d0c6355dc5d8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 7 Nov 2024 13:50:55 +0530 Subject: [PATCH 148/319] merge: Change some words --- .github/actions/merge/entrypoint.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index f611615..af0c41c 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -232,11 +232,13 @@ def main(): pass close_comment = ( - f"A repository for this submission has been created: {repo.html_url}", + f"A repository for this submission has been created: {repo.html_url} and it will be published to Flathub in 4-5 hours.", "\n", - f"You will receive an invitation to be a collaborator which will grant you write access to the repository above. The invite can be also viewed [here]({repo.html_url}/invitations).", + f"You will receive an [invite]({repo.html_url}/invitations) to be a collaborator which will grant you write access to the above repository. Please accept the invite within one week.", "\n", - "If you've never maintained an app on Flathub before, common questions are answered in the [app maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/). If you're the original developer (or an authorized party), [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) next to let users know it's coming from you.", + "Please go through the [App maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/) if you have never maintained an app on Flathub before.", + "\n", + "If you're the original developer (or an authorized party), please [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) to let users know it's coming from you.", "\n", "Please follow the [Flathub blog](https://docs.flathub.org/blog) for the latest announcements.", "\n", From 1c29aa60d56ff1b52b9d95390c7f43e562bd305a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 7 Nov 2024 13:52:56 +0530 Subject: [PATCH 149/319] merge: Format with ruff --- .github/actions/merge/entrypoint.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index af0c41c..8ee48a6 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -17,7 +17,7 @@ from gql import Client, gql from gql.transport.requests import RequestsHTTPTransport gi.require_version("Json", "1.0") -from gi.repository import Json +from gi.repository import Json # noqa: E402 def set_protected_branch(token, repo, branch): @@ -179,7 +179,10 @@ def main(): print("Creating new repo on Flathub") repo = org.create_repo(appid) time.sleep(5) - repo.edit(homepage=f"https://flathub.org/apps/details/{appid}", delete_branch_on_merge=True) + repo.edit( + homepage=f"https://flathub.org/apps/details/{appid}", + delete_branch_on_merge=True, + ) print("Adding flathub remote") clone.remotes.create( From bf42f138a07ab6982dfdfce0e46f2cf3f5b5af91 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 7 Nov 2024 14:02:10 +0530 Subject: [PATCH 150/319] Add python format and lint CI --- .github/actions/merge/entrypoint.py | 2 +- .github/scripts/archive_eol.py | 1 - .github/scripts/archive_orphan.py | 3 +-- .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++ 4 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 8ee48a6..dd4918e 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -17,7 +17,7 @@ from gql import Client, gql from gql.transport.requests import RequestsHTTPTransport gi.require_version("Json", "1.0") -from gi.repository import Json # noqa: E402 +from gi.repository import Json # noqa: E402 def set_protected_branch(token, repo, branch): diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 9a0c3a1..ba6bc30 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -48,7 +48,6 @@ def get_eol_refs(arch: str, remote: str) -> set: def main() -> None: - token = os.environ["GITHUB_TOKEN"] g = github.Github(auth=github.Auth.Token(token)) diff --git a/.github/scripts/archive_orphan.py b/.github/scripts/archive_orphan.py index 56c58a1..389fa5d 100644 --- a/.github/scripts/archive_orphan.py +++ b/.github/scripts/archive_orphan.py @@ -10,13 +10,12 @@ from github.GithubException import ( def main() -> None: - token = os.environ["GITHUB_TOKEN"] g = github.Github(auth=github.Auth.Token(token)) org = g.get_organization("flathub") - excludes = {} + # excludes = {} earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( weeks=60 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c5665cc --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: master + pull_request: + branches: master + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + + - name: Install dependencies + run: pip install --user ruff + + - name: Check format + run: find .github -name *.py -exec ruff format --check {} \; + + - name: Lint + run: find .github -name *.py -exec ruff check --output-format=github {} \; From 27589e147016dd2dcf9175248c04d32dbc7148c8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 7 Nov 2024 14:04:54 +0530 Subject: [PATCH 151/319] ci: Set python-version --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c5665cc..8160597 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,9 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 + with: + python-version: '3.13' + cache: 'pip' - name: Install dependencies run: pip install --user ruff From 8697a100510a12a5d36cdcce43f48c0ccda1e635 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 8 Nov 2024 08:32:14 +0530 Subject: [PATCH 152/319] pr: Add submission guide to template --- .github/pull_request_template.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1228b44..86ce9fd 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,8 +7,8 @@ - [ ] Please describe the application briefly. -- [ ] The domain used for the application ID is [controlled by the application developers][appid-domain] and the [application id guidelines][appid] are followed. -- [ ] I have read and followed all the [Submission and licence requirements][reqs]. +- [ ] The domain used for the application ID is [controlled by the application developer(s)][appid-domain] and the [application id guidelines][appid] are followed. +- [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2]. - [ ] I have [built][build] and tested the submission locally. - [ ] I am an author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** @@ -17,4 +17,5 @@ [appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements +[reqs2]: https://docs.flathub.org/docs/for-app-authors/submission [build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission From 3c992b88f4626704f4159c911184c859ee27e53d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 5 Dec 2024 21:26:52 +0530 Subject: [PATCH 153/319] ci: Increase stale frequencey and process in ascending order --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index d1b68f7..af7562c 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: "Close stale PR" on: schedule: - - cron: "0 0 * * 1,4" + - cron: "0 0 * * *" workflow_dispatch: @@ -21,3 +21,4 @@ jobs: remove-pr-stale-when-updated: true exempt-pr-labels: leave-open operations-per-run: 100 + ascending: true From 0713996adfcb0bbeca056be335d606c40b9b28d8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 5 Dec 2024 21:29:54 +0530 Subject: [PATCH 154/319] ci: Bump operations count to a larger value as it processes in oldest first order, it hits old issues first --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index af7562c..5d65569 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -20,5 +20,5 @@ jobs: any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream remove-pr-stale-when-updated: true exempt-pr-labels: leave-open - operations-per-run: 100 + operations-per-run: 500 ascending: true From 1f0d1dcd28a9b2ba4ddaaa76fc82228d537d70b8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 00:08:23 +0530 Subject: [PATCH 155/319] ci: Make the cmd readable --- .github/workflows/lock-prs.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index bcfd067..72a90cf 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -12,11 +12,14 @@ jobs: steps: - name: Lock closed PRs run: | - cmd=$(gh pr list --repo "$REPO" -L 100000 --state closed --json number,updatedAt|jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))] | sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}'| jq '.number'|head -n 100) + pr_list=$(gh pr list --repo "$REPO" -L 100000 --state closed --json number,updatedAt) + recent_prs=$(echo "$pr_list" | jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))]') + sorted_prs=$(echo "$recent_prs" | jq 'sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}') + cmd=$(echo "$sorted_prs" | jq '.number' | head -n 100) for num in $cmd; do - if [ "$(gh api repos/$REPO/issues/$num --jq '.locked')" = "false" ]; then - if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' $num|grep -qE "^(Stale|leave-open)$"; then + if [ "$(gh api repos/"$REPO"/issues/"$num" --jq '.locked')" = "false" ]; then + if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' "$num"|grep -qE "^(Stale|leave-open)$"; then echo "Locking pull request $num" gh pr lock --repo "$REPO" --reason "resolved" "$num" fi From 7b51a7c84b28c3000550e417735976fe92171b9c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 18:26:36 +0530 Subject: [PATCH 156/319] Add issue template for quality guidelines --- .github/ISSUE_TEMPLATE/1-quality-mod.md | 15 +++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 1 + 2 files changed, 16 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/1-quality-mod.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml diff --git a/.github/ISSUE_TEMPLATE/1-quality-mod.md b/.github/ISSUE_TEMPLATE/1-quality-mod.md new file mode 100644 index 0000000..fc1cd90 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1-quality-mod.md @@ -0,0 +1,15 @@ +--- +name: "Quality Guidelines" +about: "Feedback or support regarding Flathub Quality Guidelines" +labels: "quality-guidelines" +--- + +## **Flathub store page link** + + + +--- + +## Questions or Feedback + +--- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..0086358 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: true From c98723362c818704518ce67e4c6f53e8defc614c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 18:28:42 +0530 Subject: [PATCH 157/319] Simplify template --- .github/ISSUE_TEMPLATE/1-quality-mod.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1-quality-mod.md b/.github/ISSUE_TEMPLATE/1-quality-mod.md index fc1cd90..f8c3627 100644 --- a/.github/ISSUE_TEMPLATE/1-quality-mod.md +++ b/.github/ISSUE_TEMPLATE/1-quality-mod.md @@ -4,12 +4,9 @@ about: "Feedback or support regarding Flathub Quality Guidelines" labels: "quality-guidelines" --- -## **Flathub store page link** +### Flathub store page link ---- -## Questions or Feedback - ---- +### Questions or Feedback From 191bcdc1d31ed72adcf99f0fe0ceb5ba9bafcaed Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 18:45:35 +0530 Subject: [PATCH 158/319] Add workflow for tagging quality mod issues --- .github/workflows/tag-quality-mod-issues.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/tag-quality-mod-issues.yml diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml new file mode 100644 index 0000000..daaa2ad --- /dev/null +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -0,0 +1,18 @@ +name: Tag Quality mod team + +on: + issues: + types: [labeled] + +jobs: + tag: + if: github.event.label.name == 'quality-guidelines' + runs-on: ubuntu-latest + steps: + - name: Add comment tagging the team + uses: peter-evans/create-or-update-comment@v4 + with: + token: ${{ secrets.FLATHUBBOT_TOKEN }} + issue-number: ${{ github.event.issue.number }} + body: | + Thank you for opening this issue! cc @flathub/quality-moderation From 759292c2d74f6d40be500264420377e447ff55b8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 18:48:23 +0530 Subject: [PATCH 159/319] Allow to be run manually --- .github/workflows/tag-quality-mod-issues.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index daaa2ad..6991aa2 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -3,6 +3,7 @@ name: Tag Quality mod team on: issues: types: [labeled] + workflow_dispatch: jobs: tag: From d5212403656ee664c16dba80249a37be935c83e3 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Dec 2024 21:09:22 +0530 Subject: [PATCH 160/319] merge: Quote input arguments --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index d4cd311..88e7868 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -15,7 +15,7 @@ jobs: steps: - name: Check if actor is reviewer run: | - if gh api /orgs/${{ github.repository_owner }}/teams/reviewers/memberships/${{ github.actor }} --silent; then + if gh api /orgs/"${{ github.repository_owner }}"/teams/reviewers/memberships/"${{ github.actor }}" --silent; then echo "IS_REVIEWER=true" >> "$GITHUB_ENV" else echo "IS_REVIEWER=false" >> "$GITHUB_ENV" From c788763aa3c2de87b4c35d651eae36806e0ef31b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 08:08:37 +0530 Subject: [PATCH 161/319] Add a blank template --- .github/ISSUE_TEMPLATE/1-quality-mod.md | 5 ++++- .github/ISSUE_TEMPLATE/2-blank.md | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/2-blank.md diff --git a/.github/ISSUE_TEMPLATE/1-quality-mod.md b/.github/ISSUE_TEMPLATE/1-quality-mod.md index f8c3627..33ce62d 100644 --- a/.github/ISSUE_TEMPLATE/1-quality-mod.md +++ b/.github/ISSUE_TEMPLATE/1-quality-mod.md @@ -4,9 +4,12 @@ about: "Feedback or support regarding Flathub Quality Guidelines" labels: "quality-guidelines" --- + + + + ### Flathub store page link - ### Questions or Feedback diff --git a/.github/ISSUE_TEMPLATE/2-blank.md b/.github/ISSUE_TEMPLATE/2-blank.md new file mode 100644 index 0000000..583f728 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2-blank.md @@ -0,0 +1,4 @@ +--- +name: "Others" +about: "General support or issues" +--- From 9f08942894226b116f4f7170a40c6dd24ef0a556 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 11:11:37 +0530 Subject: [PATCH 162/319] Extend action to autolabel issues labelling does not work for outside users even through the template --- .github/ISSUE_TEMPLATE/1-quality-mod.md | 1 + .github/workflows/tag-quality-mod-issues.yml | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1-quality-mod.md b/.github/ISSUE_TEMPLATE/1-quality-mod.md index 33ce62d..bf4377b 100644 --- a/.github/ISSUE_TEMPLATE/1-quality-mod.md +++ b/.github/ISSUE_TEMPLATE/1-quality-mod.md @@ -1,6 +1,7 @@ --- name: "Quality Guidelines" about: "Feedback or support regarding Flathub Quality Guidelines" +title: "Quality guideline problems for " labels: "quality-guidelines" --- diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 6991aa2..8572250 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -1,15 +1,25 @@ -name: Tag Quality mod team +name: Label and tag quality mod team on: issues: - types: [labeled] + types: [opened, labeled] workflow_dispatch: jobs: - tag: - if: github.event.label.name == 'quality-guidelines' + label_and_tag: runs-on: ubuntu-latest + permissions: + issues: write + if: startsWith(github.event.issue.title, 'Quality guideline problems for') steps: + - name: Label + run: gh issue edit "$NUMBER" --add-label "$LABELS" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.issue.number }} + LABELS: quality-guidelines + - name: Add comment tagging the team uses: peter-evans/create-or-update-comment@v4 with: From fe007b9049a416e3d0a0006e3987bfeadec9a843 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 11:24:45 +0530 Subject: [PATCH 163/319] Drop labeled type Prevent duplicate runs --- .github/workflows/tag-quality-mod-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 8572250..6336926 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -2,7 +2,7 @@ name: Label and tag quality mod team on: issues: - types: [opened, labeled] + types: [opened] workflow_dispatch: jobs: From 1fdb0b8bd917d29a9ea1831ff0c77b8ba6f6dedf Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 11:29:24 +0530 Subject: [PATCH 164/319] Drop label from template now Uses autolabel based on title --- .github/ISSUE_TEMPLATE/1-quality-mod.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/1-quality-mod.md b/.github/ISSUE_TEMPLATE/1-quality-mod.md index bf4377b..d00a4ba 100644 --- a/.github/ISSUE_TEMPLATE/1-quality-mod.md +++ b/.github/ISSUE_TEMPLATE/1-quality-mod.md @@ -2,7 +2,6 @@ name: "Quality Guidelines" about: "Feedback or support regarding Flathub Quality Guidelines" title: "Quality guideline problems for " -labels: "quality-guidelines" --- From c7bbb9c871f3a50a26b525ac0d161dda694bf544 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 11:43:57 +0530 Subject: [PATCH 165/319] Seperate label and tag workflows --- .github/workflows/label-quality-mod-issues.yml | 18 ++++++++++++++++++ .github/workflows/tag-quality-mod-issues.yml | 18 ++++-------------- 2 files changed, 22 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/label-quality-mod-issues.yml diff --git a/.github/workflows/label-quality-mod-issues.yml b/.github/workflows/label-quality-mod-issues.yml new file mode 100644 index 0000000..27dfcdd --- /dev/null +++ b/.github/workflows/label-quality-mod-issues.yml @@ -0,0 +1,18 @@ +name: Label quality guidelines issues + +on: + issues: + types: [opened] + workflow_dispatch: + +jobs: + label: + if: startsWith(github.event.issue.title, 'Quality guideline problems for') + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Label + run: gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 6336926..8895ac8 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -1,25 +1,15 @@ -name: Label and tag quality mod team +name: Tag quality mod team on: issues: - types: [opened] + types: [labeled] workflow_dispatch: jobs: - label_and_tag: + tag: runs-on: ubuntu-latest - permissions: - issues: write - if: startsWith(github.event.issue.title, 'Quality guideline problems for') + if: github.event.label.name == 'quality-guidelines' && startsWith(github.event.issue.title, 'Quality guideline problems for') steps: - - name: Label - run: gh issue edit "$NUMBER" --add-label "$LABELS" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - NUMBER: ${{ github.event.issue.number }} - LABELS: quality-guidelines - - name: Add comment tagging the team uses: peter-evans/create-or-update-comment@v4 with: From 4262a849d4fa4094e66a9cdc87ab2d2027b44147 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 11:45:58 +0530 Subject: [PATCH 166/319] Add missing repo field --- .github/workflows/label-quality-mod-issues.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/label-quality-mod-issues.yml b/.github/workflows/label-quality-mod-issues.yml index 27dfcdd..bfcc124 100644 --- a/.github/workflows/label-quality-mod-issues.yml +++ b/.github/workflows/label-quality-mod-issues.yml @@ -16,3 +16,4 @@ jobs: run: gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} From 14bdfdb709e3a49bd149c7b1e6a2430d1e052522 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 12:09:22 +0530 Subject: [PATCH 167/319] Combine workflows --- .../workflows/label-quality-mod-issues.yml | 19 ----------- .github/workflows/tag-quality-mod-issues.yml | 32 +++++++++++++++++-- 2 files changed, 29 insertions(+), 22 deletions(-) delete mode 100644 .github/workflows/label-quality-mod-issues.yml diff --git a/.github/workflows/label-quality-mod-issues.yml b/.github/workflows/label-quality-mod-issues.yml deleted file mode 100644 index bfcc124..0000000 --- a/.github/workflows/label-quality-mod-issues.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Label quality guidelines issues - -on: - issues: - types: [opened] - workflow_dispatch: - -jobs: - label: - if: startsWith(github.event.issue.title, 'Quality guideline problems for') - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: Label - run: gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 8895ac8..4d389e5 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -1,19 +1,45 @@ -name: Tag quality mod team +name: Label and tag quality guidelines issues on: issues: - types: [labeled] + types: [opened, labeled] workflow_dispatch: jobs: + label: + if: startsWith(github.event.issue.title, 'Quality guideline problems for') + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Add quality-guidelines label + run: | + has_label=$(gh issue view "${{ github.event.issue.number }}" --json labels -q '.labels | any(.name == "quality-guidelines")') + if [[ "$has_label" != "true" ]]; then + gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + tag: runs-on: ubuntu-latest - if: github.event.label.name == 'quality-guidelines' && startsWith(github.event.issue.title, 'Quality guideline problems for') + if: github.event.label.name == 'quality-guidelines' steps: + - name: Find Comment + uses: peter-evans/find-comment@v3 + id: fc + with: + issue-number: ${{ github.event.issue.number }} + comment-author: 'flathubbot' + body-regex: '^Thank you for opening this issue! cc @flathub\/quality-moderation$' + - name: Add comment tagging the team uses: peter-evans/create-or-update-comment@v4 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} + comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.issue.number }} body: | Thank you for opening this issue! cc @flathub/quality-moderation + edit-mode: replace From 19c219af5e0a8a23320cf907ecc287180e9c360f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 12:14:35 +0530 Subject: [PATCH 168/319] Use FLATHUBBOT_TOKEN otherwise the second run to tag the team does not work --- .github/workflows/tag-quality-mod-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 4d389e5..8e840f2 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -19,7 +19,7 @@ jobs: gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" fi env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} GH_REPO: ${{ github.repository }} tag: From 198f39da1bd560a3550a6b5d9c42d58b706ea451 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 12:23:36 +0530 Subject: [PATCH 169/319] Drop permissions no point with flathubbot token --- .github/workflows/tag-quality-mod-issues.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 8e840f2..d57e3f1 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -9,8 +9,6 @@ jobs: label: if: startsWith(github.event.issue.title, 'Quality guideline problems for') runs-on: ubuntu-latest - permissions: - issues: write steps: - name: Add quality-guidelines label run: | From 8ace2bb0e294e73bd5a307e95bdc50fed0215b34 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 12:39:35 +0530 Subject: [PATCH 170/319] Remove some redundant fields from various workflows --- .github/workflows/archive.yml | 2 +- .github/workflows/close-master-prs.yml | 9 +++------ .github/workflows/lock-prs.yml | 11 +++++------ 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 12bb309..c2ee2c1 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -3,7 +3,7 @@ name: Archive EOL repositories on: schedule: - cron: '0 0 1 * *' - workflow_dispatch: {} + workflow_dispatch: jobs: archive: diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index b356c26..2a80ed1 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -1,11 +1,8 @@ name: Close PRs to master -# DO NOT RUN ANY CODE OR CHECKOUT OR USE ORG SECRETS HERE -# pull_request_target RUNS ON PUBLIC FORKS IN REPO'S CONTEXT - on: pull_request_target: - types: [opened, reopened, synchronize, edited] + types: [opened] branches: - master workflow_dispatch: @@ -19,14 +16,14 @@ jobs: steps: - name: Check and close run: | - has_label=$(gh pr --repo "$REPO" view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') + has_label=$(gh pr view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') if [[ "$has_label" != "true" ]]; then echo "leave-open label not found. Closing." gh pr --repo "$REPO" close "${{ github.event.pull_request.number }}" -c "$COMMENT" fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: flathub/flathub + GH_REPO: ${{ github.repository }} COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 72a90cf..0f189c1 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -4,7 +4,6 @@ on: schedule: - cron: "0 */6 * * *" workflow_dispatch: - workflow_call: jobs: lock: @@ -12,19 +11,19 @@ jobs: steps: - name: Lock closed PRs run: | - pr_list=$(gh pr list --repo "$REPO" -L 100000 --state closed --json number,updatedAt) + pr_list=$(gh pr list -L 100000 --state closed --json number,updatedAt) recent_prs=$(echo "$pr_list" | jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))]') sorted_prs=$(echo "$recent_prs" | jq 'sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}') cmd=$(echo "$sorted_prs" | jq '.number' | head -n 100) for num in $cmd; do - if [ "$(gh api repos/"$REPO"/issues/"$num" --jq '.locked')" = "false" ]; then - if ! gh pr view --repo "$REPO" --json labels -q '.labels[].name' "$num"|grep -qE "^(Stale|leave-open)$"; then + if [ "$(gh api repos/"$GH_REPO"/issues/"$num" --jq '.locked')" = "false" ]; then + if ! gh pr view --json labels -q '.labels[].name' "$num"|grep -qE "^(Stale|leave-open)$"; then echo "Locking pull request $num" - gh pr lock --repo "$REPO" --reason "resolved" "$num" + gh pr lock --reason "resolved" "$num" fi fi done env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - REPO: flathub/flathub + GH_REPO: ${{ github.repository }} From bea91fc322213ee7eca4a30b8456e90957b8ac6f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Dec 2024 12:47:34 +0530 Subject: [PATCH 171/319] Add vkBasalt extension to exceptions --- .github/scripts/archive_eol.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index ba6bc30..b6fc707 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -98,6 +98,8 @@ def main() -> None: "org.freedesktop.Sdk.Extension.rust-stable", # 19.08, 20.08 are EOL "org.freedesktop.Sdk.Extension.ziglang", + # master branch is EOL + "org.freedesktop.Platform.VulkanLayer.vkBasalt", # renamed, previous name is EOL but github repo is # case-insensitive "org.gnome.Chess", From eeb3a9a1626f99e117937e0cc2b59a616562b103 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:24:16 +0530 Subject: [PATCH 172/319] merge: Pin pygobject --- .github/actions/merge/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index 32821f0..d7e186b 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -7,7 +7,7 @@ RUN apt-get update && \ ADD requirements.txt . RUN python -m venv /venv && \ - /venv/bin/python -m pip install -r requirements.txt PyGObject + /venv/bin/python -m pip install -r requirements.txt PyGObject==3.50.0 FROM python:3.12-slim ENV PATH="/venv/bin:$PATH" From b8c3f7f4417d44d9218fa9c6f2b711796f4bd875 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:24:31 +0530 Subject: [PATCH 173/319] archive: Move token to step level --- .github/workflows/archive.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index c2ee2c1..65597dd 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -10,8 +10,6 @@ jobs: name: Archive EOL repositories runs-on: ubuntu-latest timeout-minutes: 120 - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} steps: - uses: actions/checkout@v4 @@ -28,7 +26,8 @@ jobs: - name: Run EOL script run: python3 .github/scripts/archive_eol.py + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} - - name: Run orphan script - if: false - run: python3 .github/scripts/archive_orphan.py +# - name: Run orphan script +# run: python3 .github/scripts/archive_orphan.py From 0d140c7670029af7c99ad2c8ed000d31ad9bb89a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:25:00 +0530 Subject: [PATCH 174/319] build-merge: Use finer permissions this drops all other permissions from GITHUB_TOKEN --- .github/workflows/build-merge.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/build-merge.yml b/.github/workflows/build-merge.yml index 480e187..299ea28 100644 --- a/.github/workflows/build-merge.yml +++ b/.github/workflows/build-merge.yml @@ -12,6 +12,9 @@ on: jobs: docker: runs-on: ubuntu-latest + permissions: + contents: read + packages: write steps: - uses: actions/checkout@v4 From 73b4e7d8c311df2449eb4678b543d3cdb3a80754 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:25:30 +0530 Subject: [PATCH 175/319] close-master-prs: Use env variables and drop permission to job level --- .github/workflows/close-master-prs.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index 2a80ed1..540f660 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -1,5 +1,8 @@ name: Close PRs to master +# WARNING: Do NOT use org level secrets or checkout any code in this +# workflow + on: pull_request_target: types: [opened] @@ -7,23 +10,23 @@ on: - master workflow_dispatch: -permissions: - pull-requests: write - jobs: close: runs-on: ubuntu-latest + permissions: + pull-requests: write steps: - name: Check and close run: | - has_label=$(gh pr view "${{ github.event.pull_request.number }}" --json labels -q '.labels | any(.name == "leave-open")') + has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "leave-open")') if [[ "$has_label" != "true" ]]; then echo "leave-open label not found. Closing." - gh pr --repo "$REPO" close "${{ github.event.pull_request.number }}" -c "$COMMENT" + gh pr close "$PR_NUM" -c "$COMMENT" fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} + PR_NUM: ${{ github.event.pull_request.number }} COMMENT: > This PR is automatically closed because application submission PRs must be made against the new-pr branch. If this is done From 9f7c5f1a7f28a244a03a59d04d9b36496f43aabc Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:26:04 +0530 Subject: [PATCH 176/319] lock-prs: Add finer permissions --- .github/workflows/lock-prs.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 0f189c1..feba59f 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -7,6 +7,8 @@ on: jobs: lock: + permissions: + pull-requests: write runs-on: ubuntu-latest steps: - name: Lock closed PRs @@ -14,9 +16,11 @@ jobs: pr_list=$(gh pr list -L 100000 --state closed --json number,updatedAt) recent_prs=$(echo "$pr_list" | jq '[.[] | select(.updatedAt >= (now - (7 * 24 * 60 * 60) | todate))]') sorted_prs=$(echo "$recent_prs" | jq 'sort_by(.updatedAt) | .[] | {number: .number, updatedAt: .updatedAt}') - cmd=$(echo "$sorted_prs" | jq '.number' | head -n 100) + list=$(echo "$sorted_prs" | jq '.number' | head -n 100) - for num in $cmd; do + unset pr_list recent_prs sorted_prs + + for num in $list; do if [ "$(gh api repos/"$GH_REPO"/issues/"$num" --jq '.locked')" = "false" ]; then if ! gh pr view --json labels -q '.labels[].name' "$num"|grep -qE "^(Stale|leave-open)$"; then echo "Locking pull request $num" From 3859e2ebf5185e4d8f924e5954f4db99d5300763 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:26:30 +0530 Subject: [PATCH 177/319] merge: Use env variables and output --- .github/workflows/merge.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 88e7868..92642f6 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -14,16 +14,19 @@ jobs: image: ghcr.io/flathub/actions/merge:latest steps: - name: Check if actor is reviewer + id: check_reviewer run: | - if gh api /orgs/"${{ github.repository_owner }}"/teams/reviewers/memberships/"${{ github.actor }}" --silent; then - echo "IS_REVIEWER=true" >> "$GITHUB_ENV" + if gh api /orgs/"$REPO_OWNER"/teams/reviewers/memberships/"$ACTOR" --silent; then + echo "is-reviewer=true" >> "$GITHUB_OUTPUT" else - echo "IS_REVIEWER=false" >> "$GITHUB_ENV" + echo "is-reviewer=false" >> "$GITHUB_OUTPUT" fi env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + REPO_OWNER: ${{ github.repository_owner }} + ACTOR: ${{ github.actor }} - run: /app/entrypoint.py - if: env.IS_REVIEWER == 'true' + if: ${{ steps.check_reviewer.outputs.is-reviewer == 'true' }} env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From ea598fbca74d637cd2fdc4b603951fdfea7f9225 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:26:51 +0530 Subject: [PATCH 178/319] stale: Use github token and add permission --- .github/workflows/stale.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5d65569..a9b2051 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -2,16 +2,17 @@ name: "Close stale PR" on: schedule: - cron: "0 0 * * *" - workflow_dispatch: jobs: stale: + permissions: + pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/stale@v9 with: - repo-token: ${{ secrets.FLATHUBBOT_TOKEN }} + repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment or re-open the PR." days-before-stale: -1 days-before-close: -1 From 86e743fbb18ad69c519d73619ac05135662daf88 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 17:27:06 +0530 Subject: [PATCH 179/319] tag-quality-mod-issues: Use env variables --- .github/workflows/tag-quality-mod-issues.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index d57e3f1..47434f8 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -12,13 +12,14 @@ jobs: steps: - name: Add quality-guidelines label run: | - has_label=$(gh issue view "${{ github.event.issue.number }}" --json labels -q '.labels | any(.name == "quality-guidelines")') + has_label=$(gh issue view "$ISSUE_NUM" --json labels -q '.labels | any(.name == "quality-guidelines")') if [[ "$has_label" != "true" ]]; then - gh issue edit "${{ github.event.issue.number }}" --add-label "quality-guidelines" + gh issue edit "$ISSUE_NUM" --add-label "quality-guidelines" fi env: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} GH_REPO: ${{ github.repository }} + ISSUE_NUM: ${{ github.event.issue.number }} tag: runs-on: ubuntu-latest From f79c5129964b948b8faa125c53ee7676bcee8076 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Dec 2024 21:17:55 +0530 Subject: [PATCH 180/319] Just print the list this action is not getting used anyways due to hitting API quotas --- .github/scripts/archive_orphan.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/scripts/archive_orphan.py b/.github/scripts/archive_orphan.py index 389fa5d..437ce88 100644 --- a/.github/scripts/archive_orphan.py +++ b/.github/scripts/archive_orphan.py @@ -51,9 +51,11 @@ def main() -> None: earliest.isoformat(), ) ) - desc = "This repo is archived by Flathub as it is orphaned. If this was done in error or you wish to maintain it, please open an issue at https://github.com/flathub/flathub/issues" - repo.edit(description=desc) - repo.edit(archived=True) + # desc = "This repo is archived by Flathub as it is orphaned. If this was done in error or you wish to maintain it, please open an issue at https://github.com/flathub/flathub/issues" + + +# repo.edit(description=desc) +# repo.edit(archived=True) if __name__ == "__main__": From 43d377f2f00d692fdc62a83aa01d7c9836394f90 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 2 Jan 2025 17:10:28 +0530 Subject: [PATCH 181/319] merge: mention 2fa --- .github/actions/merge/entrypoint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index dd4918e..4cd454c 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -237,7 +237,7 @@ def main(): close_comment = ( f"A repository for this submission has been created: {repo.html_url} and it will be published to Flathub in 4-5 hours.", "\n", - f"You will receive an [invite]({repo.html_url}/invitations) to be a collaborator which will grant you write access to the above repository. Please accept the invite within one week.", + f"You will receive an [invite]({repo.html_url}/invitations) to be a collaborator to the above repository. Please make sure to enable 2FA on GitHub and accept the invite within one week.", "\n", "Please go through the [App maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/) if you have never maintained an app on Flathub before.", "\n", From 413fc48b0d4a5317b91fbc9b5b8a116c34037f93 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 21:12:52 +0530 Subject: [PATCH 182/319] Add workflow to lock spam issues --- .github/workflows/lock-spams.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/lock-spams.yml diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml new file mode 100644 index 0000000..d87ec62 --- /dev/null +++ b/.github/workflows/lock-spams.yml @@ -0,0 +1,25 @@ +name: Close and lock spam issues + +on: + issues: + types: [labeled] + workflow_dispatch: + +jobs: + handle_spam: + if: github.event.label.name == 'spam' + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Close the issue + run: gh issue close "$ISSUE_NUM" --reason "not planned" + - name: Lock the issue + run: | + if [ "$(gh api repos/"$GH_REPO"/issues/"$ISSUE_NUM" --jq '.locked')" = "false" ]; then + gh issue lock "$ISSUE_NUM" --reason "spam" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + ISSUE_NUM: ${{ github.event.issue.number }} From 53f4f29882d1bfa6120b43ecc07a79ed1ddc0198 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 21:15:37 +0530 Subject: [PATCH 183/319] Fix indent --- .github/workflows/lock-spams.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml index d87ec62..1f0837e 100644 --- a/.github/workflows/lock-spams.yml +++ b/.github/workflows/lock-spams.yml @@ -16,9 +16,9 @@ jobs: run: gh issue close "$ISSUE_NUM" --reason "not planned" - name: Lock the issue run: | - if [ "$(gh api repos/"$GH_REPO"/issues/"$ISSUE_NUM" --jq '.locked')" = "false" ]; then - gh issue lock "$ISSUE_NUM" --reason "spam" - fi + if [ "$(gh api repos/"$GH_REPO"/issues/"$ISSUE_NUM" --jq '.locked')" = "false" ]; then + gh issue lock "$ISSUE_NUM" --reason "spam" + fi env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} From fe2f8a60a890aa6fe658d683c1a96f748884ef67 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 21:53:56 +0530 Subject: [PATCH 184/319] Add support for PRs too --- .github/workflows/lock-spams.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml index 1f0837e..da51639 100644 --- a/.github/workflows/lock-spams.yml +++ b/.github/workflows/lock-spams.yml @@ -1,13 +1,15 @@ -name: Close and lock spam issues +name: Close and lock spam issues and PRs on: issues: types: [labeled] + pull_request: + types: [labeled] workflow_dispatch: jobs: - handle_spam: - if: github.event.label.name == 'spam' + spam_issues: + if: github.event.label.name == 'spam' && github.event_name == 'issue' runs-on: ubuntu-latest permissions: issues: write @@ -23,3 +25,21 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} ISSUE_NUM: ${{ github.event.issue.number }} + + spam_prs: + if: github.event.label.name == 'spam' && github.event_name == 'pull_request' + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Close the PR + run: gh pr close "$PR_NUM" + - name: Lock the PR + run: | + if [ "$(gh api repos/"$GH_REPO"/issues/"$PR_NUM" --jq '.locked')" = "false" ]; then + gh pr lock "$PR_NUM" --reason "spam" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + PR_NUM: ${{ github.event.pull_request.number }} From b699208bc62478828b39d00e61030a4dfd31c19c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 21:57:15 +0530 Subject: [PATCH 185/319] Add pull_request_target event --- .github/workflows/lock-spams.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml index da51639..a5ac7b1 100644 --- a/.github/workflows/lock-spams.yml +++ b/.github/workflows/lock-spams.yml @@ -1,10 +1,15 @@ name: Close and lock spam issues and PRs +# WARNING: Do NOT use org level secrets or checkout any code in this +# workflow + on: issues: types: [labeled] pull_request: types: [labeled] + pull_request_target: + types: [labeled] workflow_dispatch: jobs: From 1d4df6311cc25cb5f2389a0b72a9f16b69cab750 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 22:10:15 +0530 Subject: [PATCH 186/319] change the conditionals --- .github/workflows/lock-spams.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml index a5ac7b1..6fc1884 100644 --- a/.github/workflows/lock-spams.yml +++ b/.github/workflows/lock-spams.yml @@ -8,13 +8,11 @@ on: types: [labeled] pull_request: types: [labeled] - pull_request_target: - types: [labeled] workflow_dispatch: jobs: spam_issues: - if: github.event.label.name == 'spam' && github.event_name == 'issue' + if: github.event.label.name == 'spam' && github.event.issue != null runs-on: ubuntu-latest permissions: issues: write @@ -32,7 +30,7 @@ jobs: ISSUE_NUM: ${{ github.event.issue.number }} spam_prs: - if: github.event.label.name == 'spam' && github.event_name == 'pull_request' + if: github.event.label.name == 'spam' && github.event.pull_request != null runs-on: ubuntu-latest permissions: pull-requests: write From 18bd011027de40cf3b1236177d0a849724216aec Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 29 Jan 2025 22:20:32 +0530 Subject: [PATCH 187/319] readd pull_request_target --- .github/workflows/lock-spams.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lock-spams.yml b/.github/workflows/lock-spams.yml index 6fc1884..5b629d0 100644 --- a/.github/workflows/lock-spams.yml +++ b/.github/workflows/lock-spams.yml @@ -8,6 +8,8 @@ on: types: [labeled] pull_request: types: [labeled] + pull_request_target: + types: [labeled] workflow_dispatch: jobs: From 60aecf493d406a02eb2ea8bbed360d2138c7fb8b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 12 Feb 2025 07:13:53 +0530 Subject: [PATCH 188/319] Exclude dependabot PRs from auto-close --- .github/workflows/close-master-prs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index 540f660..c610258 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -18,9 +18,9 @@ jobs: steps: - name: Check and close run: | - has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "leave-open")') + has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "leave-open" or .name == "dependencies")') if [[ "$has_label" != "true" ]]; then - echo "leave-open label not found. Closing." + echo "Not labeled 'leave-open' or 'dependencies'. Closing." gh pr close "$PR_NUM" -c "$COMMENT" fi env: From ccbbd26d579feb7ba1034ba5388d3b93cf238c3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Feb 2025 01:57:53 +0000 Subject: [PATCH 189/319] build(deps): bump cryptography in /.github/actions/merge Bumps [cryptography](https://github.com/pyca/cryptography) from 43.0.1 to 44.0.1. - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/43.0.1...44.0.1) --- updated-dependencies: - dependency-name: cryptography dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index d33610a..564bcf8 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -17,12 +17,12 @@ cffi==1.16.0 # pynacl charset-normalizer==3.3.2 # via requests -cryptography==43.0.1 +cryptography==44.0.1 # via pyjwt deprecated==1.2.14 # via pygithub gql[requests]==3.5.0 - # via -r .github/actions/merge/requirements.in + # via -r requirements.in graphql-core==3.2.3 # via gql idna==3.7 @@ -35,15 +35,15 @@ multidict==6.0.5 pycparser==2.22 # via cffi pygit2==1.15.0 - # via -r .github/actions/merge/requirements.in + # via -r requirements.in pygithub==2.3.0 - # via -r .github/actions/merge/requirements.in + # via -r requirements.in pyjwt[crypto]==2.8.0 # via pygithub pynacl==1.5.0 # via pygithub pyyaml==6.0.1 - # via -r .github/actions/merge/requirements.in + # via -r requirements.in requests==2.32.3 # via # gql From 8123c2e3c6b6116a33477ece376cb3334efd2624 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 12 Mar 2025 22:36:45 +0530 Subject: [PATCH 190/319] Add a note to mention any additional maintainers --- .github/pull_request_template.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 86ce9fd..19e8b78 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -12,6 +12,8 @@ - [ ] I have [built][build] and tested the submission locally. - [ ] I am an author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** + + [appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository From 3279259cddc6df2d5a5ef3d38a851e230a1b398c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 14 Mar 2025 00:13:50 +0530 Subject: [PATCH 191/319] tag-quality-mod-issues: Don't run on closed issues --- .github/workflows/tag-quality-mod-issues.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 47434f8..0814ef8 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -7,7 +7,7 @@ on: jobs: label: - if: startsWith(github.event.issue.title, 'Quality guideline problems for') + if: startsWith(github.event.issue.title, 'Quality guideline problems for') && github.event.issue.state != 'closed' runs-on: ubuntu-latest steps: - name: Add quality-guidelines label @@ -23,7 +23,7 @@ jobs: tag: runs-on: ubuntu-latest - if: github.event.label.name == 'quality-guidelines' + if: github.event.label.name == 'quality-guidelines' && github.event.issue.state != 'closed' steps: - name: Find Comment uses: peter-evans/find-comment@v3 From df77fbba08ea4341b8921905ef5abf18e63d7ea8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 16 Mar 2025 18:48:12 +0530 Subject: [PATCH 192/319] ci: Pin everything to commits and don't persist credentials --- .github/workflows/archive.yml | 5 ++++- .github/workflows/build-merge.yml | 14 ++++++++++---- .github/workflows/ci.yml | 10 +++++++--- .github/workflows/external-data-checker.yml | 5 ++++- .github/workflows/merge.yml | 2 +- .github/workflows/stale.yml | 3 ++- .github/workflows/tag-quality-mod-issues.yml | 6 ++++-- 7 files changed, 32 insertions(+), 13 deletions(-) diff --git a/.github/workflows/archive.yml b/.github/workflows/archive.yml index 65597dd..da1f9fd 100644 --- a/.github/workflows/archive.yml +++ b/.github/workflows/archive.yml @@ -11,7 +11,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 120 steps: - - uses: actions/checkout@v4 + # 4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false - name: Install dependencies run: | diff --git a/.github/workflows/build-merge.yml b/.github/workflows/build-merge.yml index 299ea28..be29b62 100644 --- a/.github/workflows/build-merge.yml +++ b/.github/workflows/build-merge.yml @@ -16,13 +16,18 @@ jobs: contents: read packages: write steps: - - uses: actions/checkout@v4 + # 4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + # 3.10.0 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 - name: Login to ghcr.io - uses: docker/login-action@v3 + # 3.4.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 with: registry: ghcr.io username: ${{ github.actor }} @@ -30,7 +35,8 @@ jobs: - name: Build and push id: docker_build - uses: docker/build-push-action@v5 + # 6.15.0 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 with: context: .github/actions/merge file: .github/actions/merge/Dockerfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8160597..3696ac6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,15 +12,19 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: - - uses: actions/checkout@v4 + # 4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false - - uses: actions/setup-python@v5 + # 5.4.0 + - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 with: python-version: '3.13' cache: 'pip' - name: Install dependencies - run: pip install --user ruff + run: pip install --user 'ruff==0.11.0' - name: Check format run: find .github -name *.py -exec ruff format --check {} \; diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 89848ca..ba35ca2 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -14,7 +14,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 120 steps: - - uses: actions/checkout@v4 + # 4.2.2 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + with: + persist-credentials: false - uses: ./.github/actions/flatpak-external-data-checker env: diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 92642f6..4ad013d 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: - image: ghcr.io/flathub/actions/merge:latest + image: ghcr.io/flathub/actions/merge:latest@sha256:ebeb5c952d8277b56ac96c72c66205c32d241119d086e9e7fa8848e80df39107 steps: - name: Check if actor is reviewer id: check_reviewer diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index a9b2051..373e293 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -10,7 +10,8 @@ jobs: pull-requests: write runs-on: ubuntu-latest steps: - - uses: actions/stale@v9 + # 9.1.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment or re-open the PR." diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 0814ef8..78d7f75 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -26,7 +26,8 @@ jobs: if: github.event.label.name == 'quality-guidelines' && github.event.issue.state != 'closed' steps: - name: Find Comment - uses: peter-evans/find-comment@v3 + # 3.1.0 + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e id: fc with: issue-number: ${{ github.event.issue.number }} @@ -34,7 +35,8 @@ jobs: body-regex: '^Thank you for opening this issue! cc @flathub\/quality-moderation$' - name: Add comment tagging the team - uses: peter-evans/create-or-update-comment@v4 + # 4.0.0 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} comment-id: ${{ steps.fc.outputs.comment-id }} From 394315a2affb74c22ddb4a102dffc1fc41e8da7b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 16 Mar 2025 18:51:11 +0530 Subject: [PATCH 193/319] ci: Fix x-checker action --- .github/workflows/external-data-checker.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index ba35ca2..83209d0 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -19,6 +19,6 @@ jobs: with: persist-credentials: false - - uses: ./.github/actions/flatpak-external-data-checker - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + - uses: ./.github/actions/flatpak-external-data-checker + env: + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} From 39cccaf8716d5e9ff73918a7b6bdd2bd56c8d92a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 19 Mar 2025 17:18:28 +0530 Subject: [PATCH 194/319] stale: Run on issues too only quality guideline issues for now --- .github/workflows/stale.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 373e293..176d118 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,6 +7,7 @@ on: jobs: stale: permissions: + issues: write pull-requests: write runs-on: ubuntu-latest steps: @@ -14,13 +15,20 @@ jobs: - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 with: repo-token: ${{ secrets.GITHUB_TOKEN }} - stale-pr-message: "This PR hasn't received any updates in a year and will be automatically closed in 30 days. If you still plan to work on this please comment or re-open the PR." - days-before-stale: -1 - days-before-close: -1 - days-before-pr-stale: 365 - days-before-pr-close: 30 + stale-issue-message: |- + This hasn't received any updates in 6 months and will be + automatically closed in 7 days. Please comment or reopen if + necessary. + stale-pr-message: |- + This hasn't received any updates in 6 months and will be + automatically closed in 7 days. Please comment or reopen if + necessary. + days-before-stale: 183 + days-before-close: 7 + any-of-issue-labels: quality-guidelines any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream - remove-pr-stale-when-updated: true + remove-stale-when-updated: true + exempt-issue-labels: leave-open exempt-pr-labels: leave-open operations-per-run: 500 ascending: true From 7a4b712dffc571663ca289ef7408431c1cc93bb7 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:14:17 +0530 Subject: [PATCH 195/319] merge: Use github token to check if actor is reviewer and add label --- .github/workflows/merge.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 4ad013d..5357f42 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -9,6 +9,8 @@ on: jobs: merge: runs-on: ubuntu-latest + permissions: + pull-requests: write if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: image: ghcr.io/flathub/actions/merge:latest@sha256:ebeb5c952d8277b56ac96c72c66205c32d241119d086e9e7fa8848e80df39107 @@ -16,16 +18,25 @@ jobs: - name: Check if actor is reviewer id: check_reviewer run: | - if gh api /orgs/"$REPO_OWNER"/teams/reviewers/memberships/"$ACTOR" --silent; then + if [ "$(gh api --silent repos/"$GH_REPO"/collaborators/"$ACTOR"/permission | jq -r '.user.permissions.push')" == "true" ]; then echo "is-reviewer=true" >> "$GITHUB_OUTPUT" else echo "is-reviewer=false" >> "$GITHUB_OUTPUT" fi - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} - REPO_OWNER: ${{ github.repository_owner }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} ACTOR: ${{ github.actor }} + - name: Add ready label + run: | + if ! gh pr view --json labels -q '.labels[].name' "$PR_NUMBER"|grep -qE "^ready$"; then + gh pr edit "$PR_NUMBER" --add-label "ready" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + PR_NUMBER: ${{ github.event.number }} + - run: /app/entrypoint.py if: ${{ steps.check_reviewer.outputs.is-reviewer == 'true' }} env: From f3854759dd03b98449d4d6344c4d5c9f8da764f5 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:21:51 +0530 Subject: [PATCH 196/319] merge: Add missing env key --- .github/workflows/merge.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 5357f42..358b2ca 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -23,6 +23,7 @@ jobs: else echo "is-reviewer=false" >> "$GITHUB_OUTPUT" fi + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} ACTOR: ${{ github.actor }} From 6f778b42e47fdc9e43fc97ac803dcbf14151d2b5 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:27:55 +0530 Subject: [PATCH 197/319] Drop labelling --- .github/workflows/merge.yml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 358b2ca..0e41f3b 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -28,16 +28,6 @@ jobs: GH_REPO: ${{ github.repository }} ACTOR: ${{ github.actor }} - - name: Add ready label - run: | - if ! gh pr view --json labels -q '.labels[].name' "$PR_NUMBER"|grep -qE "^ready$"; then - gh pr edit "$PR_NUMBER" --add-label "ready" - fi - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} - PR_NUMBER: ${{ github.event.number }} - - run: /app/entrypoint.py if: ${{ steps.check_reviewer.outputs.is-reviewer == 'true' }} env: From e3e35a285716bb2d049361eb1d519391a0c9bddd Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:28:36 +0530 Subject: [PATCH 198/319] merge: Install jq --- .github/actions/merge/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile index d7e186b..2049e57 100644 --- a/.github/actions/merge/Dockerfile +++ b/.github/actions/merge/Dockerfile @@ -14,7 +14,7 @@ ENV PATH="/venv/bin:$PATH" RUN apt-get update && \ apt-get install -y --no-install-recommends \ - git gh libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ + git gh jq libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ apt-get clean && rm -rf /var/lib/apt/lists/* COPY --from=builder /venv /venv From 2a72e48caf4698ec686fc59d25ddbdee8da59e40 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:30:22 +0530 Subject: [PATCH 199/319] merge: Update image --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 0e41f3b..42f36c0 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: - image: ghcr.io/flathub/actions/merge:latest@sha256:ebeb5c952d8277b56ac96c72c66205c32d241119d086e9e7fa8848e80df39107 + image: ghcr.io/flathub/actions/merge:latest@sha256:5ede625982e65dd0b495a6ace36c88cd206c25099da5f245a5f5a119f98728b8 steps: - name: Check if actor is reviewer id: check_reviewer From 19ef733e795fa663d74fcbad175b99e5d87522c3 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 24 Mar 2025 23:34:04 +0530 Subject: [PATCH 200/319] merge: Revert to old check --- .github/workflows/merge.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 42f36c0..2344b3a 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -18,14 +18,14 @@ jobs: - name: Check if actor is reviewer id: check_reviewer run: | - if [ "$(gh api --silent repos/"$GH_REPO"/collaborators/"$ACTOR"/permission | jq -r '.user.permissions.push')" == "true" ]; then + if gh api /orgs/"$REPO_OWNER"/teams/reviewers/memberships/"$ACTOR" --silent; then echo "is-reviewer=true" >> "$GITHUB_OUTPUT" else echo "is-reviewer=false" >> "$GITHUB_OUTPUT" fi env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GH_REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + REPO_OWNER: ${{ github.repository_owner }} ACTOR: ${{ github.actor }} - run: /app/entrypoint.py From a5fcb02c72c45edae29ddbcad05c051036cdf16d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 30 Mar 2025 09:00:28 +0530 Subject: [PATCH 201/319] Add light-dark images --- .github/images/pr_image.png | Bin 80765 -> 0 bytes .github/images/pr_image_dark.png | Bin 0 -> 82625 bytes .github/images/pr_image_light.png | Bin 0 -> 83935 bytes .github/workflows/close-master-prs.yml | 13 +++++++++---- 4 files changed, 9 insertions(+), 4 deletions(-) delete mode 100644 .github/images/pr_image.png create mode 100644 .github/images/pr_image_dark.png create mode 100644 .github/images/pr_image_light.png diff --git a/.github/images/pr_image.png b/.github/images/pr_image.png deleted file mode 100644 index 0408cabcba104340ac61bdc4f7f58dbe19742635..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80765 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 H6h-@2QTB7HG8& zWWuE1N21E(n!r6hutwCwM^&H^-vh=`+qEjKRXM0}UqUzEMn}-ZETF6mSEOYW99f}; z=eJ$1al@VzJD>W>D>ZU5fkj6s?6*0nsxt#X1I#@0-G__;1as}xey%PRRg)}nYj}CS zK9N=;Qa~?&0h{52Ze@@)OMmNK`|*qu7Od1MANqh>aL$KzQY;GcZF*Cs(OY6v?C)ou z!iP&1@Bd{72tv;Zr4vL*N;d`|!5VAhl?jmCy0z_{SXEuhvM z&MtOuJQ@|ZT3Oddivn3HPo;qTV1g(Eklos)MjF-Xb8XkpH3L?4{SO4dmsFto57CD^)kve@%o)Kj6*ih&Hm zS5k|3WMpI{0d{=uPlkk*;TWhVD4J)d5T(-gluWX)AEhSjJFm*QsO5Z0Y7Fe%4U=E$ zO}{0dkTkv4Ia^7S@P(u|6+N0=DZC{V3ZZ+Gx?w!0zKWd0udoEa1~Wvvrq4z_KuhNs ze6WumbUOCUmd!(VUCYR5>avLwx%8^^o1mp$M;sF3l`^4uN~OBxY2)?Nwx!9SQ=`)Yln^y_XE2>ckZVEbLY$ue z>OUMI;oa*`pWd@Za;Xwrw{RP!Vy9O6(~sESZ*|M_9REq*W!M@n@TF}Hk7BVj zGrPmZ%p60V>j&s&c1fw8?QQC9@;CqUt-sXD`5|$*d4sJddAgN#b|OpF#`7+9=iUFl zh4@6cvKl>e&2vCu^<#(_-)i)lR+=Bry#%*_HivUAo70}i8CjX3(!51Tzq!4e0xUoZ z23p{?tv&j=B^j6fEisG54r4i6KtuS5C<8)5LJWqhfXwR-rVSjgu$XU=JUTQ4$L{)x zlOy0O%!nzk5geq#_5asZm}A%;E$~ee3)sYZQVHgEz|jvMF9(zejHSg})ki4K*%(tZ z7UhAr3z=umMhY8~nh-JNTGU?_j$u0k$?mr*4i60{Rwffj`_n@>^`wONH%0Rflai9Q zwsuogk9JdZ)<=r;VBRHg91GL+PDkxLNbnmJ$Q-5{W2si!Pv;U|H2*thASks7#z!yB zHiD8@1XLSs1Lbd%&O@Y17?a%B(9ox5udm0C7Ir_Vzpe#m#>J~w&uO%Vvp~|@c{e!L zhl{l?z^Q!u>UlY!#KD)-;m1jV;Xqfh#4Q{jVixgYi}|6AWrM9Kx|M`Li~K&Fb@4Zat73l~=oa z=l(?;LqkK8$%>N~qhKNFgux7kTG*t#S{<-68GWvz5?ep&>-FP@cH&=SL9Zsx-}=)} z)K&)|mr6M%9OBnx^7Uo%EZ~4%gwrggv*E{&x2vTN7)B(ttgVqsBuCY~x(W^$WWHRd zHM}kQAyfOh|MR5!BUBY~ugDlY{;iMIB z{jxoHQa%)a!g;Fpr+O%=ba=&vnPe95 z>y8}n{%e}A@LY&+UL;8|F8G)`J%l0X;?$d(ps-%GWW(0n;oHM#lsmqN_Iio+Fhv7r zf4(AThuAZjpJvl*c(kIB$6R~x^XD2KjYQdSrO0AZA}`MHc7L~R2uqd*wxh>>B^K7NRnc-4UPU@?d9*q!x1FcjD;_ON=QgKiuX&Z-^{0|SJ_1dkuRzD`L0s%C(DRp2-aQb?f+*0V2X zxJD)%%X75n`pft@B=+((owZ2zu@ZaEQB6DIMIjc5*CQ8n;#JmCs4ybQdhkHMUH3u>zba(yq^Cbnqnt>+{&A#}99^ zEPY)m`KbEqb$N{l+Vjfa=L`jhLvAQ6G-Gx9`Jnkrmo7o=7IBS$HvM%9PO?wM*W!GZAC6!I{?J*JXSstZ0*s018T<-clHI){MU(;UBu_K0uDehS84f$=t;8X4i2`s+8Vs;;A zV4B2WR_FuO!>A%AkUa@S4ehtN1=AWF=b_i-ANRVr&l_ciJ6-M^YjRB-gxpz zorIP)$IXHy_?izCTVUKpr*Xq2lVsx)uyOQ*3 zv=AvDQ@BgYu_cNmqMFnwJd!7%PB{maAT;Cc1B0M#Xs4tEt@bUra*X>SS`5s}V5*az?K=?!g84-Nf5sr^#QBwd9WdFW}} zsvg0Cd{=d_;|gn;hE2yCGMAVMZh$k8PAE%<#TB;(ZAPW234lV%{u{CdLC8LFIbNm* zvinO>HY>DV5N@=QgPCuOA`E0v-nUqJ+sgs4Ki#W%Nw`(e;Mf@rYnFh=UuYg@rO8BF z+NRln>CmI*Hw%}F=*Lmvc0K4kMf3tWpAB>WIwB7MROo9~Ar?DMb7{ll@yz<%=|j3R z8VNKf<+Gej>J?5#2Pd|m-+4OjfQh$1LY}wnPB<;KBN0oTqn+y3M$bzjbU8X`-Ie~d z+Uyu^p*P^^_VM%Q&qiJxiggFKO(rT5+VYvsaogX;{xipTMZuEwZqQU$WzV}siH9Gq zlaost8D$tmMMT_!^0s0bJ!X$?daoze+u(07{)_0DFVSo&pCz-&EM!i;L+x2PBpWNM zsH&J*o8Mij!Ih1ICuj3lsQ^OO%lVT+)>DqniNp3>yP>(jJH~f2i0wf%Z+BmV2WGXs z1(~n~(4+MlDcf-^{(;#L+po8om+ygosmzK2a+azypWs3hESlO8*ZXjcvs&Yh?Zz0F z$ylTui*nEY{PVX~mb10*YbAAn1_XTJvN}YhjqzFjluyMQe{(e<8|DfiolS3lbNbJ_ zpH;yBMe!MirxguB8MOq>j~qjAt7?f2EeA(1#7>;~J>E+wf9qB>k74+SSm}|$Qd<;4 zHnjZtBbXZp+$H!zFSWGlJA2Q%xA^!0)={c8Cmz$vdHk)qS?K}s+=QQJLD5;_> z)#b4?Ld?pb9%R@O*W>&Kh28`u?^p1Ck-hqg^dU#4t(BEFW~JZG-d-lj!Fqy{%}p3G zyZ~|V9YwI3R#z+uRBAs}^XSG)|CTXMJ6ny!gNQ~<)(J?M4lA;E>F=~gc9zS8%E) zQYm%umzKRpUb?sR7&Jx(y(!m-S|jwfX6gY^&@FMiQTb2|%3=npmOxc? zK+s?|y7jbT{}aTuB3e5hVBH|dPR!w}P(Zi-+{DRjxEV^#0>5+LF7JCVES&cpYr{}n znC)$-Rz$I%h4i%OhsGbaD#l7}@%^6neysw-5zrd6x7?#6-FFz_0t@#qutp#uxxT&q znj0R403H4nwL(8I^ni#`MK;q3n)2KpO^DQ~!M*ZAQt}=*ceu6TU{9isMDO7$K!A|M z0(|mtnLQ_XG9Y2dDHzbPYJqTve5jJjz1l4yfeI}5W(!Ql-R874yAz*5KuDnhVtbaW zi}}#I2qVby`rxaupOi%wU=W(yx+V0Oc0C(-XZ8h47w2RI&pD&diG?1y3+W5oc zCs<_6Nt;ah8!*z{wS+%b%Qv9%2Svdrm^M}(+1%|SUSj#@g=<^`z zX9y`g+Yq2LIZ?jsGi_fS*t2~{xK=bL8NyR*w{=>P(4Bj5{gRy+g-pc!$X`Zr=-AnA z3g{jw{nmJFGG6g&2eS%AI@r93C3#!}0$yA`1FHNf*m+!4i);2KU8QS1uDuco{b60H zJoB=%6C^x@w{D5S>jXPqLXEuyMC;>)y}WsET{i=XwD>0Z#fukgj;_iO;D^(ZEN+g;-obp9 z^aqpyW)nUqF9|`^X(JRg<{dM88gYD<1I&sr@^47`3FI<)iqvFLv<44<$*H2DPmivl1!5``y^v0pgiouxW z$oD*%&euR32pIFt2P%;qIxSOjX*XaHdg@d~bvVblw0`|Z@{8_7KN3z4A0j4AV=d8m zL3NQwj z#4L(6Xz%>cu=6S1oYl`5TVV7g}-ej^QY~dt6JU>1GnqR=iWJ@GT#Q6jWDJWin zbQ}RFlUqY`_8UK5*gdbVSw9f6W0S34D9GO22lKrmZ^%WB=28HYR(UY_>sLG zG&;zglrrOa;H++T=7D;NWc`tl&y!E?2ED(C`hUsmHSkPo=;-Khhwgs7(7G{E9`jM? zcWhYLyYQl*ozH5Lz&aqgpo6&@4I81CsDM0~nQf#VAVE_3?0LaA4|KNaKvbkGP|EE4u~B7qxqSCcseEoUtuassYTR}xGSMx^V^#U{D39*dPjH8M6~m(kLp3|= zqY-LCjwwvvBXjrW+z+X)Ru{~;rttI?3;mFoytW?0^9N_J3|D)}Xbi>Tl<{ooT8s=yAyHajc85$3QXf@yj zt!9dRP2<^s}(Z>Rvf29e{l;anX)D_81Zm0}ASfK@wU zh2yeLn%kK3f`Wo}R>sL7Sg5y@JuWsD4(SaVq41uWwKYlL&~a$RL#MWBTM3=P%JHqk zlCuG%vd(sjoN{5#kCy0MIgR1?;=x+!=U8gvblCNo*`R1^&e{JWeyVu?tp#B{q8n`hM3}$){Wgnxfc`^)Q^mif;9&a29XErMd!}p z%A{H7KmZLKOxiv#Jz>dfagi3o>83G!g1r|mC_+niY_`iEuCVx&eM}Ml@_L?&Fg9jZuWlphI@G%^((#%8X{Ky~r z+){T60*xiR(-0ey;__VqL0}(b&F2b0ROQ=e9(rYYzEH;)Kw^;&gq;EyOAPBP8Dw06 z_XsB`xh}$L;Oq;bVVXDlRn;8xV9Y;|zWS?I!8_)lTe2wjsBjia%B#?p7o!)^^Pvo5 z-u}q|2SOYb6qmq%tzq``fO7XEw{lW+{Q3e$ONkJx_Im1Pkbbr> zb~0TBCw2!iZK3AsialIqeI7vB9>yfUiNU-Y#Hy6rgn`aEcRf(V%*v{6pd$eAOa-UE z+357M4eUU-Y%g|pN?R_NEloWZP7oZPxef0EIp_8}g=cZa#7cmo1a&;~gv)Snve7X{ zp5JDrju;;w{$E2)y)Vf_&2xy$Q*hv7IE%8~>B$~&Zq?}TcYEa4O!)8;56n##M;qJNRJGk zR+7m4Lym((+Vt}21pbUDyJzRE=pq8+K1)@h76=Z zVH&lI8BD`_=N}lD`YnWzwQTdrw!rDt^H3eaO6H6is_p2&gY&Jol)kt3d=->``Y`^9 zEH&WNSmPR*j!;P#W@cv)_7_@LE{ZEmOiXJVdr}1jIn^yKEmrL!yz$HCV6=ejJTtTs zo0zTXx#kd@HYmhQ>gqNR=9-b~02&C|)2|lX&L~`j2^JO>eyU#C@%6jtaFJ~`L$zV^ z3HFE9doI#mC!|zIJM3-53Yvd{reJL9p6*|feDNpMC+u`TPFKehf# zYZ4Rv;0*WW3h{4{`di^YzC}RLs=d%!;?;x}C;a^)91Jq_Ae_A|LF6>ZdRF*kCy4Ui zaQ$7|2WreqPrIK;m3?hIL#7;awcipoA>^>P28Yj8k<;xfh67p2FM_D8R=TRWR2+vq zse)@K;ziG#+2233n6ANXa6MEk8DS^&cVf5aK!)dBCxt=eZOpB_oPny;i^yh;DKffy z|K8`8FvcypQ|vNUlh<%zFO)?-K*(_~SF@iH+IE%+z*xh1jxgZUMEaRrsAYjg8GJ>j z($i#niQEAk6DTy*gD_<~2M3F(sWS`hafVyF{}<7iFLvX~>OjVKlX8dS5`&Q8E(bVE zA@ku9N$RKoBUn3)5yf9+})(u#9OM32bpgpZ9eCgwC0gVO;A_wG_ z?QTp;_v*IWIac97J-t8cV$s(z5DrRVr?T>`u^e~f_;{$G(J+4VgDK$al*T}YT05+w zt?jL8SJ{+EhpCA&`;h;ee$6`F%~USyE@FKZ%}oo}2t&q`3nJ+hXN>-np2pFbdr3hs zPJEq`k}CzZ9*9IxBC1X^>1fs>H~7jBEiJ@-Tgn4a!p4#BE4vu7^Z6 z2r@OJ<_eXD9-s>{rYR_lW#R?~24KPwQi?Pe+7mjbs~&Ch@@`IFpo(l!aHtg7PvZ#DL4q(+V4Ed5x`6Bh-%pPOV zeWYMt)+5~>i|Q{H~VfxAnaA0;CWQW+I~-=Xp&@zkpL$1MoF?{W<=m!AYuv~P4_ z(FmFgGg}ObWp=>cQE$JUvoZU2I(0YHQUd$_4hW_a*5mC=N2A+=yuFT(jt49Eyu1Wo z0h4gbfb8-$O9XEr8VPzjbL?308s1Bg0nlvJHEhrFsLM9g<9Z6(^G4TmM))FyqTm&A zx)xVxLGSHq%zu87*NX)pLZ&CO&O(CBS&hjFq2r2rn$}U7&i|%f z2f6;4sh4=2{a7^M^EpeddyyWjJSleGHxwrV{uilu`Up4n@|%1+bBm$T-rq7>pu`68Q79(8&tFrc6T@@#A!e02lln=qC&h#B?-fMe#&Io|@jz^N=4dnvdTVzES_GW6 ztWL|m1!+hOC=UN5*AWpZz_ zC>QBWR+Ot0J4FGIV}?EEtC9K=-C}g4#gr;7_9pS^OE~9W1|>c-=r3WJexK@9Vs^LI znCU5oTUvY;Sd?T+O;mAqH->8;sGCZCi9h$v>C5H5%t5z* zaAP^bB>Uje_*<7gjZXv-L9R(VBOVq13rxg^p51Qhuwq0lb;Q6!eJX>{H&7Af04KCAR9}q>GuMM#)6*+$)W>G%d+}yZPerUE; zgA0PVptQn%2tEJ%HOEjwKqzYV`VNjx%b(Y9F>v5V!ZhoB2yT!+jVa8|HBAtym{5am zAv(HXRm0R&TKg$)rO8MY*ihY9&Jr};p{hDA7BSy#Be4+R?MkzhS7{BWdGG*FM4f8) z5Op32J+`6Xm&tO%h0@~gVUsE&r4Bc>d_uz2u z0Z&b>l+NhZji7v5P<(tku)Hm@WyvU?=97?(&)Wa<*$cDll$9pu?wH04_WgVp6DJ^; zrjpE9$X&=BDH8G7agU?F@V^hDbP)L2v6fA}@D8SBP|Dzis2QG2rg@d<8rBLJX!5)$ zVC{4M8d>)r15T$hTML?n^DIgQiF&Atwv%N~v6c0)`G?|R7P^=g_4`Wsw>Q=WHWw2j zy!|ew8WwGYnjeVR*qO|#)dHAafU^v5fnehX?w1W$*x2tCBo}N`uj0z`XkH!`jtDk4$c=exE4y1498=W!6cju=x z`)~zMhdwAp(1_s?cO*#keL>@ZP|6$dkUYy$dYnR=!hFNYpeJ80$Mi?R_q53WYK}lF#JWwK`q#C4cREn#kUCw|57vw=FG)Crs-W&a=fAD(KS`G8<>*EaNPZMAEF2o8sdMqui>NeNy@AJa_{-%V9_~W!p zU1Ty|lcw?bL975^N-}VvUdEMR{@Bl+-`X+3^W6O43Q^PSIgeDy$i7^j#mt;(W7?k=Gx~j~ccS z5ImjgsrQZgp#0w_cd-r(EX>W!zDboI4vj9(wJpDJDHY*dt%WS#_VjiBt}Ib8BO{|? z8w_hlg208Ul85QbeaTFjBl-0jY*Uq^_--dhyE8M}u78S9O<>AARHDO4#8}e((_9wL z5HG)rjh%x>QR~@W+OdIyQh=W1bQ*LPq{}Z46*IB&d}xawcTrHRZuO4=wxceaY;gAN z?>k%OTPl?{4|~^@=G#vb+1E9FPWC`bM`2-sc5Zx)cf`GXQv>@67sw<(AmlDy#e-qAh73ulIf0&j z_Pypy9z)A1KtC&H!izKsQ9ghE!)2SmJ(jwTV2LH6md&iSCpwEF(dOgFdtr0A>{q1mmL4~EZZ-)v%S@-(gS+hXe9nj^#@GEdtFcp!KdQaYh+g`KZ6 zLlPKJ#bQldoOi$8PJ>cMca=##ttRKF6;vY9b_xn5nurHxcD@1N77yWjXY#gYql6r} zv#r-J-?K$S6S=7N3{tA z0g?kz_~5fh_1vG%pRKd{*o-P{XtFe9|St z(4(}0b$x;Z`LeSM)SXayO80Tfa3qWSJk?;()9X;@J$(`NX=^FLvO>rL(BQ3&mqvghMYc#y2!Liia|#$z)6Da{08}SvtMp)0b!Y?|XP6Dt zD;c-(%v(ENAW0=7c?k>+(W9w)*=qai!=lhhlmh+?eR|2r@2CAA`V}h8X+ZaR?%et9 z;m?CrUOw2 zcm>hCN>I0(#zmHLJ=hW(bSL7%)!}oQIR{k#OPHTN(;Beo&QEn5F~YW(Ka&r($e?|L zYXx>19~;A2fKzYH2rwQkiWzxfeA_@byE8xkL%$EmCGzx}Zy>r*81~PY{Qc4G+a2In z5BDlk%vme;XMC9z{(KEdl_I!)y9urby({)O1>-(x?+GszBI4@Oi`^Kn6j5#Ly#WK= z4Wok*AS&M7Kk9`E2P@+QqHt#A28dd)>mMJ_&z^MJi&G>4a2z%pM8OO%3yVn*#!)0! zd->zTU#t!f{(dj|>B*C(1Q8K5OjpjO$;OtNeFP3HrsapVvxmo*?i6EX;nSHbvc)FZ zl_qkKJP{9%)FM1WqqZA$hJybT6gfW-x^Rh z-HP$NfWQqvuj;|=!Eq9D=2vz-jRRz96aJ~v-mVLN4?^PegW{r+XJQIAJ`i{<9)Xk% zUM8^7Z+iW)`@YffzGS1mp`M;hF+j|@cFS)DG8EmFzg*r~@AZ_56NtHH9V4WN_xSPS zx9M-bn5dTafM5<3znV%YP}J{VBDB-%y3yORI8jMV>fi%9 zKZM&7wmWtH(Ek&`vvD+Dyns`B0PvWPWbEvIltR%9uVR8h-$we-#Hc$5ktTx}?tNhf zP)ATlghLuM4x3ZmMMMl|ikj&ACF4Hz?an}!x^#S*J3B)qFNy|B>D3+M_+=oN`TRA?s|q%Ppw>6wk3cBy*RlUk zO;;Y4^clyqww_iwmX?`iM$4ROTA{Tpk5>Aa<}r17Wu9rsyi%J9%W1~EmXuc@S)OPM zt<(WJO7biW>6>)6|4OvVEv${0%(tzVGjSzwhVxetN0zE`eLBA@k|*cvU0z zrSZZ}zF|e*_)~ZMxdDMgzDwA*)q)T&wWSMRcXKQqCq4QmC&}0>T0E`z?E53$=j5(DN1yI*+vKU(H8<$u^_)& zP~n|7`KpaXdmq^YS?g4D>I1fE=au0htbB$9D}U$zE8oBC98pC@CFZE$%v12nRZcpn zeq}*p9ycO{U4^seH*GStlYo#PkTiN(bghCnJ8P zHo#o)^6JZ$-9^5Ka_Yqb?t(igD{&0Trg@f1%QVud>)p6sbuVn~+Z_wI?PB+d!zPr+$>9GiuUl*oErMo5$*=d+ z#jXYz2S?6#ZsiQ?wtzP*(+rtN9r}H;R$4FDdk6Hd=@kbseeXk|i* z*P!`*aU-l#N(z~utId1TbtHb!5Mb2JaN$O|Ja*~A1sFAw&quQi>)ueW9bj%VK_X#Ccz92prTw70D`)VHI30=Efc|aQ zdeIVmU3XP_M)eu{)a}DxgnV}~gPmL#J^VFVF(H-I$S3v)9a0+PjKv5!t#Dh9@|%W0 z3Vm^h!dZ#;%+t{3)s)PPEl9!D3#djdMQ}c+NYBp>WyHW7BeHnesk@BVjS{gS)0EO3 z*?-d54P*=y1g(_bI%fP6&div-SSG7y|MID9)`QY-+k@8Dg{vtPeqLoqj=?lINLEh8 z!3MKEiHYrESE_Hoza3@%k5LY45_?mdlfGP{rlmng!34yw8Ad&1LwMIWR98n&t*rf> zUSCGrI%jX((9Dqb6~kNwas<)w57hMWZEMV8Qh+;N6$o{Vjg65!YZtTH7d z!-OjBKFeS_erg{py27O_$l=N9CBZYTEiGpa+>O#-U2SflN>dgQ zoMt*r&~x5|(UUdS%@qY=+l&jEDrmcn5UKp_;U(0}wP^UD2}4oE$dHY2wxJM*UgWW3 z>kV6Gcc9n9t+>hcUHWwMvfDb+ECROW&3zknu@12yt}F6;51|#Bj_Um+Zcum^-b2B2{Mh%*OzPtU|wXM zKHoEXH$PsoXKE5Ui;lMqp$8E>Uz z3oe;rzq?6_p#c>u5S5+{$2U`tPXtdESsQxPq(DOeOznh)=JpKW4;Xx_Q*_l65hKp6 znL3%?rFOVY;)=N!CN+%NAdcc8T&lnp8K&u)nX%9;C_ny6&w=5w^Pj10o{4|wJ-ggZ zEsE1in7hepow-K301KZ-53_Ri+uHU&Jo%yAtwQagcg-bCO#QB)MQD;Uptv1PzTvNL zVDM)QmwI&!b#U1cUZ`5Ofz!w;)(WE1ms2Yiko*;K2pMaI>CQ1G=AHUY7~Zz+(x~7j zc)&`AorM?47V_Bbb+r`oqwBhxy=z6i#J!pd$xGyE@dq{U>~1f}&JNn1VQFwC#4GCX zt;j?iIL>G&#@Zgym7JbhmVOhaz3l(jeX4DJivR7TsNo?l?EUv-i9A ziShmMjd8|d3}vv^dY*OXb7zXgYQB?0LA*2Jh^2?<{{?(e_+R;{5Do}-_Kc|v-*k0zQ~ z?KfMT--H=$(35C2nPGiIq4@Ey|9<(6&LRHS3o8$-+v&Lf`9OPUmaoizK90f~g~9XB z#V8a5;yhdbz7_b?J4$eI@y4%w)JTzufr~Gh9$?JT;Ru7{g_x|jl zh-X%vh)m`&yi{#9-xwVe)jkVr36ad!KhSb6H@~pbUs(wZ3|@g&nCJcvyMXPDvRQ6jF$fFxcz`XJuv8blb;3 z!sqd;u)I8(+dU4fj^P?DUT|lL&oUbUN`=qE>-W!RB_t*EI&!2%$2{-CIKdPyPe8TJ z56?E@CLoY-cUWV@88N5b#vFG^cemZzmYi~_S_cBAKwx1Z1Kbeb4P%dNYG+p$qR-)9 z@hEwDaJ^ptWU**J!#|7kgjEVzOZN*_3XkIx-Svw_&IWHsNA|)J$GFeQZ25mYXKKxR zHg!Dy+&tWK%0M8WL_dAeRu+ALN4VS(d{_<>2_fRM8qJchSZIh%U^V_NpU-7~&88F^ z`#J5sFM1Nkd&}!nq=;vz=!TPf)3*&yZxN6&-mp^ouC0A-YHm(ob!JMcwJ@DDX&o`> zF8jJIf0x&uDHd+C-uGgr#=J*CR&elwLFM-s+Qj4qFxtiKV`I@vOS(?`3xlDvR>Ilx za!N`fR#qimX>ppZK5ZX3tQH0`pW&};Zi<1$vc0_>O3WGlR-=~19g=JWbyQ%hEpl>l zx^2-zux>ef3Htn+jxOjKK9jDgVb@OzVV8ZKhxU;XY&aZp!^3NzZwS3Z zL&gWm+$4N9aBzMf|I9lt4uU1ye}~D}w%idgUGCX<{|j_T;O^EwMw03oxo1omF~^op z<6SuK<=U9+)de!S&CZ&HyuAGLX_vOu_3wA0IeK3V%Ps#iHy+HO*6AF0MmJBdj7X z2wKFgE#rU4Ev?%Bgdlaq%Qtm&?%g%ZtScd8ilU@(aj zp-lJB6W_ZummN9_3yVv$BYj^C+~KefGc}G3U^WMm*$e;NI$112qDosvogwg_#KbDs z3QOU(7F)feA?WE96;b%9-V5pW7)x#UcO>;{-UWlAeibIcY1oNEEpdbGtuAw%qKcmhR^{5 z|AvaXqPJ5~8 zKWTuZ*{*iOkMF*#Kj;j?g*)Av&in)Aw3?e*I{#~)`DA`>p4g+g9z;?2d11K3LT*Pp z2K6SF_iEKVBPHhBXTgEQ)=B)2U=1os`CtK|=>guYZn~VL`!mbckhvkm~w_B9=M|1X% zTg=?+I%sWeP5Eu+KM8W6hmq8QkdP40<>oRSgaEd|>T?CTv9ZyeX3$Wp)2Sl$-3cvk zq5}J3ITwu*=?gaMUhz#OQv_1Kx9c$2kT9m;0LUx=Nqop}y806~SRAb(7a1uR_qN$f zMy6pTX?l8k5K@_KMLoITxk*}MG2Pw~!PkCywCZ{d^WN;uP1WCxD{iXa3Uf23MEmy$ zu9QADYjY?K*&%a<$NAv1i;GKU&vP=Cr#>L4c_QmrVqjp1Mile2SG^J>_i6wB?sof*IcUpc30$L*OHKEc6gcJ}u0 z^C$(Q<_dD|r+d>)xF&`}t(Q;2&DeRJ_H=h*=sb?DHj8fdIcqHE`_3(A#Vz%aKils< zO|Ou@XnXdIa?Bpw`xKM;U2dFqYu2ZElg91M zDT68@_^cLNUu05v{F0K0PhicpUE8St4DY0F90rdMRR})9JL3aQ(J&%IyTwf%mv12c zf+*NtyXaxy(29yn!%^qCF^~X9!s8(R(5Y0c+&}qN1MWnyw@Nyx2JW`Sid4P0W??sl z$JxquW-uSuCz)h^e5lRG2PuM>%jOja2gh3`S##6vGhU}t+H_vb2PBAGz9JE6@h^Kz z^`h2RK{Sy&MED6acF*fm)9MN$1x>|HfP~-=51Y!3v|L^51-z0=_ya}$!Gg5{00Z3} z_cL3}S0HA~_d*vvIv5^qX}$>wT|-}>A>TXvU@-^5{u(Pw@o~*}9nCsrv?>=sT z=cGL2uflE)TGK#Og)3XxEk!@q0XyB$(C|43-XI$1EmVog%F2?t9149D7S>pe36qqP zMohO)3FiW7<<=dRZN1p?R;IDu(eCswHk@cUk;rU~CAzk~t?hC(RL9y@OCM^R)M^~30Z>gh=cCI45+UZ8p z)bw<d=DD@ zA_V$0tXl`?8V^4xX0_Ox26d9jB{QzC<1Nr^%_pxEw!Gm{Eh3UF)>xqB$P z;KM+=kS~|*4&L(eGVKdA096722%QGAdpaz9cFgeh?Rs>C;KsU&_A*G=`t6-Tn)M!p z$jD;;nB@K;g$%qk*2a5vw#D+3Wc=>O7sja>RaG&0d9=sJ$6pF3e)#$685neQh2US= zPSE>$wA^hFFQ`@p(xiGs0pJ~#k`e~W1lAmB^N9xhe`D}ZyYJ1BwUm@zFt;2&5iHW| zO<^@=F*(%r@bIv4cFs*t_o=JnI^Un~$7E0;DvF-OGG|~oND)kP-xypC=Y?e{x8duv9~BS9>Cpk~&IK8ZW_CfL9+Ef=2OxB4GK?4f#?=0J+glmFYEI1zm6N z?ZvFMnwRCL)#70x zB_vSenY2JGe_M2W@7~wf_x$+Ms0+=^%&g9Mfp4bD)Hkh^S*%og_r<>lv$I%Yd22<< z;Nat2C@3^4UHe~xI&9l;BY=O7K1;?5l3Z{92+hj87X=PlcA4z)#r}x{532(;NLq#F zx+C`w7g;j@07eQc*9Trwhkt(sc>NYp0{NeS4dS2CoBzw(zakxm{|Sp9QS?N;uX5}D zNkbn|j#Q{A{~yKXe{TQ3QK|m-#fp9s@LnayYV$kU9MH-VOsSgoPStpO@8_z@Q#Yn}fc7z`B|s&u{%gv8P~uLX zQEq01+!(C7e@%N%T*-8S{EPgN7>Y*S3%}9tQ86bQOp^RUxc7d>Y20htGfzL{x_duO zXXD3#>uFnXNNx>ovwi6NQ_9PY&$;xHBP{%+g;MwQB#+UOHk4n#=J+A<_Wm4?jNgie z*(|p{M1M&+oQC3_@#RL}6l5WF*_&8m6QcEnms?I*S=3CDMT5ig4KMF5W^bj&1(}PR zYq@#Px!@bmBk0K~>(J3vE_ud;*`QWT>+>+tj;l&zS|%nIXSpAQz0C#!(bTfpi$32P zAdy*b;+U>*eCQN%qp`?)g4dOBajmsX;-L!e0B|(3w(>$Nn&P8R3ABemSPVl6upo|d;c`j-6-RW+V83= z3Ww{PH~ZH<$sxo(iORHB#ra&@&)28RH<9JcL83jk)Bx4Go~U%Qv${su zTo|0iLe)1kX+)tv6h*4%i`qsyq;hs@+A?%Lun=ExfChh3_-S_V8>RBf zU@_?hy;SlH1|{dphJd>f$pd7`TB8;#%DGwAu-r;FFiZnQQcA;)$!gg8Mn?(Det1p< z>mz|)97aR=Ds{Rd-PLV$L|$IruysVe8{)9EvD?*z_t6nDjPg1sf}(SANN~QVr0{Q>nif5Hz6HPLxXm#@mVUZq zO(}{^hz%)-ZSbE_OmuXFjYJFi2COV^3yJvoSLVu=8{AAHU8JzN(!Y4|f;Lvt?P5Db zJ{!PrlgUzzLP2XWF?NOAp>*ll8bvdDZpY)Njn4aRLyKvMn9OVYBBcs)au{s}vV4Bv znh;q*q_)1kVDEc#?Ed@8Uu$nV=%^zEuh@_=_dx0)`|-nHURCw)eX~24`v%)1ZE$-> z&U^^FSjZ_$hl2w+<9F?%!FCk0gyd(7N%qG!WgBM4#Kp1PT2uBy`qq+4;|cj&cQf&M zoVWX?Y;kRzY$>?8gXVc_ST_$`n@%=%;U4>~q!e4EaZ@NzI%3eXyoulDyy#_Ffl;mg zRx&#ZHJW;iy@0iD3t5VL(m9dE4zv9sN{k5RgP!e_|vFgO}aXc`kQp!fu z=}9knExY#}_Qn&AkL|)q`9lK&XnG}rNO)%sPvH$5v!#aO8V?dm8#iK=k_BAbmju`x z(>Su5;4(!cvLAfDsj8}DVUx*7O0xU`+eEv%qRZC#es0=rb9w zZijX2{YO_{wd@Qg z1Af)=XTECPy>_L?w#w&UY>4FKI>#p`Q{|Qnk=V<{I3YPJo#WLe800#F8w1V63=9k# zix+TkX&#pX+}zyPo@DMTbgwC2PgUM@JH#FEyRjI~JYR5k#|Ds?dNoIO(F=fx?-7C? zI^G^hHT!kO_nuAnJN;*U!)l>p1>pPTTrK11AIymsuG7*(LXe2YVp$odw$;~s6SdAU zNpxm8J8SQTB)~`esk93^FAQRWCNI8lL&uFj$>{EOa*ll$-5tB)-?!TnC1GO+3Gg88f-A_*5qOf@_Yut5wuhN4D?N zY!7$8+23GaVtB^XoiYD(y`~{SxWRgNZn)>!@I^`c!{jzQXn72gW%bClq~N)Z?{%5H z`lB{UsLacRyq}`QmUV3$C8pBT#@;7lEPM4P2l00 zQw9BMBs+RV_ID-%VrP=lQA?M{jRhu?WkoE z+ha^wRqxYEFAWFH_V)H9BqUgVt<0zS2|Y&*-1MkdcAl;jQ5k;Dw52Qm|()LpmiCavpOWM~RNu4F+j~?M+Hd zOpFaTPeFo8v1x-NOvu*ueQSxDw47~Z?+I_2H?y|(!a%A!CvUCwYWtP_<@MEjd&r#8 z`m`!p^UZmtDIO;O^S?;d{X4UUUR4{kSK}F(yh@US6Pet9Ec^W@5eb(CSfc>T>5% zrpMKE?&Z}Dt2snVGdz6Mx$OGtNjDcOKNH4gx+h>+)Wq+0u0Q;fqDZYd zIP~;+!;kHmpsl>WNx_Z&iZSu_$DQv1eNk3brhCADLI}`EqmzYLw!AG20W&H-sh?Aa z8KLdZA8qfVfByvv%|61V$rv%Y+*`#gFZ+UxNAgj-#Hu+> z%^tQg{0*V#7REWn%eAz*X+6x1{4+689<~7Lr_Tu-#l8EnK%{xBhlG*OK{hV5RV=LE z4^L24Rju&c-9Xw!)!iyvzP&z?1!(S_?l9Itvo}2X-HldXsbk-`rEen6Gq55FYZrSr z(06-#douuTc%0z}uM11CCamdS5{KX_K!0PfB0DA&wWfkQ)no;+@vpiVzOPkoWR%0ls zr%1NM+Bt95`8Wi`Pv`wR7V>jF+Xg z`{nXmr=@iyem$w<-w!i$_k@YJUxRUEp}er}W0b@?6i0Dy{mJ_ja8HmCGwAw07-ouQ zD2`Y`>?(#HM2}M=X!{$!Ye4Cq%6gZEwfvBI;GB3N0>Wts$h}5K!hg2#S1xe$&B&IM#Q6Q8%}o$<6+DG{~DOXsdO!RTb_KO7%m!k0Or zX06_mi}N;x{;HNW$UcAV&>cYgw&+aflDMFBMv)`jp>C7cj8opW|F|Yvc5t|} zx0r1oHRN+t9@m!YZH8)kW;1Gg8$lo-wBleGeo-{oy~#8uqI-*=KWebwy0fuTRD! z@Muy+_4K4~>iZ7~Z-3sqAzVIp1z9$g%4oil%MSyTugHpPRB|ykzkAo&a&j7iw};iA z|Jw^-PmcK;X0B4#v?GwIpvmvH5Om>l6Qp*7M`gNP=a}%R?HB&vkOd{{#i%M9h&NA> zcH)&B@Aml`nM^BGVev{a>7$`g&z0bp$RzPK?@hRda7PojIb>PwPkXQ-+}0~44#qB8V+=p7vR+c~4BVuiq+w(>tW2uSs-nE>P|zeLAt|q^p`he% z9`WqxV76Tw7K)0F0;RL=@Dc@yfWyzJUxgqIl^NV90}aPyR_5ZF7!ZJIBFHIeXaYu~ za3HAye(~|Oy?jJcl_kFlRRY7p9@)wtKV0M$qNF$EdA+MhwVpdL$&E8)X>!;x!iZ=!H;O`$Em_m`J- zs+lQL%lOP#UfZuh%t+?)3I&`JD6P#KMy>Lw3FyV(AbtXxiO2T3a{3{Y`CCQ0x;=df9+ z#e0Ojl9G*4zmp%1yCsXYQqXr%Q8>N*g%4EjZEb%@c-?;38xQ@Ajg?UR`cy>3PgO%> ztWj2{#%ke{hX={kl`AN2Q<~;90Wp>hQ)o zD?1z9t|J5C=G4~8&`=~IwRx(>G34NE&%*0rUnM%_clXXtL*QYEW`oPOmEW&lQ?^Td z{@gai{NcgP;37Z&_{k~pyPpPP5ddE#e*f+fPQoLu|FP-*Y%;WQZ;!E^St|<+#@w7H zxb)Nz-Es_Y=+0hhC%E}^y;(VL?74Z=y^BC%58H*>Zm%GM$}b5|YI1TCl%jy<``h2Y zIycPr%CU;n1Fr_%9+`WllU zFgrVY#N!;cC}w7c24;D0s>ZLN0HD43x`&+_q2Vfyo8fPFot>Igf`SqJjn4X}rrBv| zuB_!#CdmZ#FTH=9Y!0n#9E8`_V#3A6#Z|$EBcE*!vDc%Up(;4e=2{Eltl)CFu5eLx zb!j%(q)z=JXmEyxIa%-B)myj1C-d2c=KVzh^(wc=791U2?;yR7lmWIwikF&Nf&=<) z&f;XY`LBEA#3YGX0)-=!g17aM@w2=_x@|3E`Z#1zcL%NZaCsjvf|hG?d57cnM7;kx zb%-=}eBez^*wadLb88)A*z*&=I=b)oXT`~Lm(xU%_L^E+NiHD~FSOo9!7M&z)QE-3 zvmS=GMdEV}fyZ+$!8kHMiR*pMq~G_t3ue4#4w^e0j4=|`+nktwwK(o8MJvN2gbSaSU-IT;oW9R~HJ^TvYIm=6%GK!|S4#zL^riGe79jc(+u8WshBCO0 z@Dg&pvMSyLBugdHhVq7LOr0VP%_@@7o4fP5EeN$wihvlE!+65NjgKytwkBdhb@vyF zM+0h|-%nxRE~0IZk?oj@#1wu?Lb}errfT{PEd`WjnE>pI4YVp4M5pQC&?wTQd4`l11!4;fz(8bOan0zX(nC-C|$gcj)I-H@VR&zB~sY%4~>)hpQ z{?S*yG>hNIdN$l9xun)(&;AXWkr2_w$w$V| ztf-*b|H}e!fLvjG@+J zs+_v z1{&FszyB^8s)=HMIVLtdF}^iPmsenRiz@qGrIhG)e|_J#Hlp-T0MD~$&&JJY;KpTS zLJ7DN)0cEXjsP;Ls_HL+uI|yILidQ&(|tiWV`JkF&}9NrLyu4DMxy@r$wHj^y))gS zX|>teRLo7cX2nfPiYmK2O!@};r{uT14tt*lCJF&_I^(?6mLJ^%7~ADhkyUE}HAk|V z$i%3R@g-Ve2i}$P@=@qse%5=pKrP&rrm~Xkv9t_Zw_Uk>|NXnL%SJsuHy}j=Fv(2L zd46zDPdoPg@>ehJ9vzLc--Osa_+lDZS_+GZaBDUA+g^|NB8?p#o~|8cAe_}SHq>Xz z=kJ95_$(vSy*m?c`ly2YMlyo%bk?UVC-<#7*0H#?ADssm6o|uS)pZT^k&%%LS?=9a zTf;N-3=HTy)lI)ifK3Rvb^v|Za8l@4Tv$->_x;g30s}`!EhGPBX6qO0>#C{?w9fw% zkj<*q=jQpjJci#rggR(>3hj1leb9Z?;UCd9*8eQF?+G!nc@&PL!X!Um)8F1+D;r6| zt)2JpDTE%J74%JaH>3xejmd`iE}ry+lYlbI0K{Ge1%(b~b7lJ*Qr7M1O8fv!(zVg9 zXVTiATeEwSmisc*WerIXP{ z*lj^!VSZ6j=Zrd3X7Mv4$4i>-k}mR$y1YOTLfadhY54gcsa!xKV%eXeX)g#!oB67@ zE6%&Qy5r&y_4Svwlq~iD8oN(&uo^1eDhS5ccCBoghlg-`8>q+Z^&W4-x^^LHyi%$c z2PFJ5cLi$eO==t^LRsW@-MSj4qIfTzn2MtWwq|lbQu5tyzJ?~c zq*jv;*xZ?R8CKVrvQy<1J)g~~An6F;j>*#QtUh^qw|Fq0vpRjjRFr%RHy<5)!VIgA z%!wo@PSM`EXWnkoB}G&@k92ZL@bcCeItL{JA)i`(0b4|H(V?H-#*f&c=rMV_A!|uUypN5I zb#Zee_9(Xq%z@yk`aN;lpOSH@TMno^W|@zN0#mG%j0^@t++6^GbsvRi-@#_w_`2ER zj4Vlc9gVInoy*MDojbcVMG7a5mxLpJeQrHCeb+GnmW7XDbq;QOn9KkG#-T~?ur)L^ zW~wZE0LGP5%Oeobe>yqIaf$r2V%d4M^%eaWg4<&G{9&^&=CuO(`8kD$9ceYIwc9H7 zVxdi{EgljggF}aQ(c@tgwj%W_(iX4#=Y%|=xv5vkf)A&Z*vry7_8;=uNKD+CwPPiz zf>2TMUcLkzzcGNtho{FYD_#EN=p|piz&zj!N>l9TJ-}u@E&X=Tuh?urJf%znMH*Un z<4&|2`jr^$rDb5N%?sNlDtLBBAqv3Zj@hd1Xw1#{SJ%=P^#^z9#agM#!Ms4!xFJ(* zYvFHHt8{yzq@)x|#Q*Zar;Ql#effEXXy*I8+?-B%C#RP>9@p<5$7<>j`#A~UFTkQl zMW;vuG)&&~fWhy6p|^J#bh<0(18dP5G4T{SnE~Oi0IAQ!)CL1xu3%>&B)y=z*s6%5 zdaz`iK(I9_sH^)?8n~nc&L@BD%~fcRAgdDc8<9XDkSa@P>Rd9(oqEn&>Dh5ym#{8_ zOv_&OoDwmq(ME_OBcQoB2{e?t4@gBi(9>!pp|*uzh`bz>)Tc9wC$}C-^3S~QI4l() zvxj%`85LPMqWH4=Fm)jjE569Zf!`HxkU>>{H=_idNTbev#canLG>e{lWLijcfbu>z z;9~|uQg2NjWX5Qw01eMkU&7F^u(Ss-%ke6LKboxx1bp#__k;K~@78UPU)M(CH-}V` zqjzR*k^%x6zO=;|yV@>wL?(I0tbqNjB(hH)YO1Z^xH?0Sq?}V#mBB`t*k;R&-FU!# zcb-HSEr*7f*zVw)-`DVchX)BkwADwUvDJ1xH^9;SJ00GsH|2t^N^#D3y1~cR=7cfp zB;wk)rJFfD*|C}Uq?@I$9Ut&D@2+gClwMp$cpxD^koogYT2|tr;Ys!z#a5Oy^sq^0 z)Qx1gOV8&gb4o+uI4|WDh7@Lp9j&sG9b1R!6qUy{Z;r;ZR|!7mG!Ly$JOe1=b68Cx zT-H>CG|EwRtE6TH^h8ZBC8c;fPFS#EIWvj=Y>HxT zVRMz&e7hxQd0&1u-5>z|f$#wO!MG4><2+Z^cEYS0csJkM3@?d_)lS4lMt%#(rSU^V zM0#K&LI;k5%gbxq%VBs)Ne9mCkix=0N9^qCF=&R-V?~8PYwhgmvOViFyvxHe#)rDy zuqy#1V)f<&I+CjnIaO?Gs;H|PAp#OcPF~*6qN2~EW22{Ip8b7&fB(J{SQ!}WA6o)? z7kNc#n0i6e`Fi>}8?lNCr@Df{W_(f-Kts!0&z+q+@;QJ|s;WvLgIK_?pHt3PA|)-c zv6<$z2C5dITs^5f5~@AG4`|?PZaO6ohi~%qq+?>5bVhn)#UNS@qZtauE32!aCD54Y z6w7yE@~!+dNd*P;O-<;z7_RO&1ffnQsOIM8K(9XYc6W8nRHW~PK+Hz@$B2$kjsXt2 z&UZ}Ty=8HP5fm2Yn1tQ1(a_{BoB@Lm^x?s1rKHBk=R=I-3!oiCon@dcNB|Sn)i)B8 zF3Y#hNrz+ury-~l)y~tpfYWj~cPPv>lqk%9RV?Cg-8gM&byrN>#H87SsKGgLOxy5l z)~Z%+C`k2CQ4S&<-@&nyZsrupY#do;>*y4t)V7%j3oC>(pz(lfHHgYW!Dfz^>Nv z@*+b$vUS**iw#fVv0rWvlcSTCXe_AcTjH0=`0~pl0BmjpO9}hxH~a?W$&r!T)^BoZ zYh{~9a-p%Coq8~0Wp8&YzL|nxx3OK2Stf~XM{sIVIpa9w@)*m`EW})$Na%^#&jqx^ z0iN%}nfFyG(s~j~m8lZvO2`Y7F$o?W!OPixm>>(X(=u?4*`$)oEH*3C{=A`M{*}U~ zScPU@JYHQ=p4sj!o<@SV32!mu+1YG$qC88u_mE%LYWc}_FptZJ=;OD8fhFEyO^%pO zd4H`v(A?VNI0FGMWu-UvToiTwb3!Oxe^Y4e%(J}rb)rzQiu~E<)HieLci-Khu_1w0mutfx5ZW$MT5YouL8JPXDH|ttcsu0c;v)RpFp9}&{%*$$lP1=~Vll+nI z?UxbwfJ2&cb!M3|TGf6y=^vyW3hL;7oAoF1Cnxbm&bU>Q!?x4!+nGEb$1UApoNxu3 zGas){`PEYW0+l9cV?gR58xa%;1hw54^%?m@S3(9FL0|itGW$P$BZb-;qXY()()Mgl zLy0_)$;{&A_kN~|<~xE_A}IDZW4v2%P8PG@)r&X21(0O`5~Zox69o+|2UuN@NGTji z1zdarlzLSM-;zkYv(*TLMH~pD1_0WoV`Q+nU;-Cc@r{R zTwH94Mp}qhh`>j$Yhd8}G2_vYk)d3up@~`kUZrnuq}?&hgcDr zNlT;K+LoVgLnHG365F3Ki;0cZdVA{|ln_Y~`IP9*ZxKzRBa4XvcLF#qlfq@M&Use> z7?70}eQ;jJ-g2LgK{SkTcE#Sb_bNre703Gl4hfwwI8$93P+6Wg#9mX9($d+|vrgAC zIl~;5+r#Aw(I+O*7Jkc_8sKv$tB%IiURYS$+!gq-wz&zAxv*;O!PNAufuZ5Vk}DTa z0U=PTArK}Y(6d-vqR6E2WO(1r)w5Qa7BWCZaAmW3z4izYkkEgd*B*dk1A8XtEx6yK zBkytvzFRi=N18Vru;T*j!=LG{glL-Z+Vl-;5DBEPaYU|Qg@0qIRBlvBj6-as! z;uX*zws@ImYs_wT-{gK*QKHA=46u-F{(QgjhFz;fT>*B-u8>0 z3A(-I!$U*#MZ%nbK9)5vU%p)1obY}pE_@+lKU0X?6AoA#$RRc*5IMliecii6CE<1$ zUW=Kb=P^vrks#cV7?q6jHVq4u2uB*%P>L9(j0muUY91y&> z!&912>g?GTSmLCz0s@DvgF}{<`#k=8V`JctAhJ_f=XP9q3Q)r5B-^9|cwRCxhusAP zLGStaknV*v*;FnWaDv5jF@w^Kh6Yf0vR`bFX%9318mx1hK6ip#O6|oh4tGB!RrV&=fkBBaKLF3 z?3+mms?HHWgJF=)L3PzZQe2tv7O>KyF<2$~!Q+7Cq)nO+c$~Yxc29bmzc=eR7m+j{ zk{>x2rQG%Mof(7-o$)N{MXW9@DqO^LA3c1`_yVeX^x~YDo#T%rw~pqNGj&MYP+L~2 zlT)*zWDnGYW2Tx^(lT4juD2HIzPmr!6hIOG@!1`d zq1rjq&~0m^hk#QrYUI>`w1o8eJ>6SNx={X)Y8!?#kXtlhRscfv3i$exlpch1I`J_r zWfelc!L4zYwomWO} z+0=}^OzpU(#@d0<{e5)wrJuYX>}S9krcPbSYe7ONWVIZGw)V+-Z9*2=yFiszcN;6g zCk)k?sm+^91XH=&FJ_+ly+_Wc70({DBnL$%w#ESx}{rG5Ope zo!NKd6_72_UQ;yra$9TPzHV$h$yO?2Yp{L!=Z7(;JO3otmA^%+Gs8MdcUW6G6z&1OTsM}%bJdg!+1N7F1?g@ql9bRC+y#$uY z1U^TiJ7kRCfNDUvxmej;bZf=naC#(UZ-HnTO3L{S82%o;OOe9JgzwF&1i}<(!dG{9 zdvIkRQVI&pqM~u88{Kog-d_XizpU)*++`3~W8D{ZbxAw<*GZg~a1Q1y`!n?^N4V7Q zU3b`&8FfU>5T1p?=2~8WSdr>-4I3XHw>j8TJKt+KdefP_XHmgYiGqr1IJl!Ey8Gyc z0@OdN)7(>l$!HmAb@xjfIH$k~t1mzR-m7;uFgBJllSJ!}XUeEr+whvEV`N;jbHKac zFN1S;M+UAf)r;BE>jv|^R8yc3Sn6Jf&bqFZ)8vht0F!}u^BJ-^tCC8XY1qx_z;-kU z{C1l~_26s}a5MecR-ic}z2U@luFif#Q|Wxcbdc)JjOO=!E$hvrCoLki0pbI&V)MhB#(}+aE!E z$5Xf_)e~Q{jLY=ytbMjGJchN1k&%&e2J6rPNPe`D)f*5C3H?FeFlMwO4(S3XUMrxV zEVO|n(yNdgnG!3ZJQ*gZCmnQRnZ#)~OUmkc6bq$gX5Jj_I?;T0Bpgxh5*iW0J{`xV zVqmGDm7{;P6U%UWzB}|-69d~DI2NON(@%7_8QD+)DH1Z={{W=LGWnZyy3aI#eT4(w zBLYiDs(m9*KfhvDKnn+{+KTzgYFd;4-X10On4^ZwlCHl&^0eUQG;>;i^3M0sr^LF3 z&4y^&Y3ULae&J!v(j46M28hC=-*Ds1s zKZrz!w=&&L)dGoAWGgfxP@Q||Yl5OAm1Oo2`DHOl^Vaz#hOZ?y!$CUj@*BCudFkOF z&@Gz_?^4HWs>ljimB}BL);K(O!fyP|-*X-Xv*4!2L#zy2Vc2?%5_@ z_^oNqD8eXcgJxf1vu#Ve-LG;5%`Q@})-B(~yBeX#VH^O5G%`pYu5!E*Gk1E0PNSxU zY@a-xIsZhz9C7_){RQDF-Z|3VRH3lTQ+O1ExhoU;d1m19XF&zu3P;QD)(BRadmmqK z%m%^w_(U`GX?%{KUTeD>hF=tXfzXVaaK2D|#+g}nJSKc?S|0E1@iQIuVKjx69T=Qn zpI>YyB{${QJpWP2m7+@`x0k0G$)pJ#du1rg#^H#C zpHAzRivNCXESb;sJE+EfHPQ|~8a<8Xyl7xeR}J+cql~~m-ZkG54QsL7NLnG!Q`lr0 zsN2U_a4j^n{_b5xlj;S^ILDBnheyW@DIiy)Q_4Qh?Ev?y>v}b(YQvfoV3Y>6k~LBR zFabxq&|s}MFR8lFOA`WEr@P)<11k33k!+;L??F} zUtC>YeoTmb5A4jqMxR7-MSYKEHFzOK(fQy! z%7J?H5Tuqcvf6)b6A}ByD2#`Q*?E2@3+PfEqBl(A+|IYWsL~5kLTp?qvQ;_bxlo0z(uV^ zYT!s^RDB5br;xdaCE>bycboIm{3Nf-&|yM$qvv*SA6+jZ+)Wt8eI6#A+i70BQJO4?#`q}O4R~3x9<84yafIf#wK(U zs1ophKJa{gdP1*@vtXW~eP)cSjez*{&xe?o{!t|QfqKDuJij1gt%4XNo9~RjC&If5 z4y{sFp76VuR$mCf)XXjas})2)-~9K8nS6-)??*iRhL`yMUypbQM0$hz-;a3s|MTJo z3THBcaTHl=YZB5FB9{L=F#(05L>vfRh_0?*jk2_kIPk2r;d9Ih6jHc&xUnaT5Q&Q8 zzTbNE_4n=Y{wVzYbZ)%BA43>iL{~iWseWW?SnprQmpY}pdZ!6xnVCuU_9Y}kbALD8 zR@9EXLTw1F*{7qYf6dHU+v4mgVr6gpyETBpb5859Qeo8?nvRa?hqcl`$3pOTWIKqd zSXWFBHByAiB=pQH>0h%Qm=s^bi83*m#F(5R@ejFvP_>v$3_??X=E z$klnc*&M(VDn?#Cr^c14JXVcLkn*c4`PUOT0*MgW%|5wG^cp%l7hlAGa&dE4_?f1& z*x1ZCNV0!bqeKhyLzJ?UL9vxmpu-zLIn^_7+?d;49T{H!cL&jn!KqwXYgoT_=>o1p zc(@Gb=`Z^`K20^Ug&$TW5OmUDtdDc=nkMKMEO0tm|9Jh+3;%QRTp1X@k}bnLmS5^r zzI^kSb!wSBZ#D8bH8)LuVEy*0&x^@>5lj@HfW74#AlbW1r*?)H`>)>Lo=AK@_-;dk z{L&v$iP!sac>JjL=;^7%a>b0JgvR`^9{2>z*hw`>wl|miRCQ#N`ad6@ycWq^P1kX`} zbL8$mkTU-1Y2m_GGCcrC`w>hD{dnku4XVsoK8dF$7O8JRNUT9y;QW zs*TCJh2!M542^Tf*kHH)rkFcM<%w;-r8Uneq3k$=8wf5*a# z5xb!5OyCQrl;a=2kYeYa@ijP3$Cl;h9kLr{lpa6~@1%4RQ=0o#J<1*~?BhpT24+fT zW)(6kzq;q@Vg5}`ntgr!CU`jV`*!j@MB37uJ1OH9GVv;RAMNAgXB{J?`uwqKCf2X% z&%^>71VbKYAALJccKGbVrkG{Fw&^uSe2m8Z`N@S?DO5q;!&4&&}Dzf*eBlqjk0^al6K= z{p;PguM1n}=jQ0>V&gxd*j7tQO4-=km$GQ>OojDK*3ZP~Sg=#m_(aQ_p759%8wZqH zPuT7<#mAsi>~#Mh%)M1ulx@^D3@V_As34-Gii&hdr-UH=0MgwJ(#@a!`^R0Q}eRuwy|M+&k+2Bx^x$k?fSl3$TI@h_BgTjjCaO;DX<>*6Q}SD1Y#5vrDN5MunT^TjKruR&AIT0LUf2W zrD6uGPz73M{M7Gn^*>j#|MG1v_TQ^$md0=hId4v3o*$!_FshCxFMwQ!@glW1*L+@5 z>JK9??{y641C-#s)t)B-X5(dhj+4lsg^$$6tcJ}~*g>@*`T+CW~&v2QRhCou*&)J(NQA zlFGZd(1kOqS+Y+gm)PQwbA0>#RPWbo+Qwi~qf-_yW%G)JgXkbO&KMSWs$w9ulh@diS(yTmH=sqEZ^!0A-F0eWn#u{ig7D`YdU zUgQ+7+Zi#F9GR^}`(0fQchJ4SwChYLJ{?aIcm9zi2f@0!4GZ4VWWxE`@zzvb2>hb8 z=B@L9>-g*(<+)sRaQ{{99A{2Oed9^)k z@z>WWlzV0R_hvJEMg}Ug48(y3^D%HtLRa?z-~el*&YwSjc2PU=Je>CbU`lSQc9Jcl zH2}H+*8(j04qGp81*Hlgm4t;a31(~iwirHo{P=zK`A8cqc%^e*kTqZ*xA9~h|2}vC zDRK^*3H>AYL#;Yf0+JE$+w7T>7eg2?{`%{dym;`}=x9l0<#EC*R-;AJi8!fBQC{p3 zgJs$=U?H;$GdvkFo;`auRlZSG{lihNss6W7+dxL}w1R>Py2hDsypLhYTC^jY!vG{! zxVX7;9NdotCY19psalfv-mQ&^<*Q*68?Pr!D>6>@>-H8=j=qVKbw?d z;uBmqZw)DUpIiS5Ph7Ag%FEy&o*$#6q=eb5N0g_)CPX&X;9!0H^t3JKUXa+IIt>=D zF|JFOFQf6B;yu)Gz6q1PG4c_kKs@@hwWqFJyxcnrq&a{d=bB z!@hj|Zo5hIl+YdGh|O9Y$~-7c9~&DRx?dWX)=Tl|SlELSv5QDfPTrhAOyacb%v_v} zT=K&w*Pj?fOguQQza~Xr=Res{WQFL-GrBHtTzwOBDA$uThQr4AXgjR1(ew1sb^#e9 zl^{^L+?&d|v)C~|?N6D-V(qOYn5jGav%}+Tj}t>0ggb86ZRi8kw%`~f))+$BG}}v= zR8jE`G^{pvkkv!jt)Kn7H;h&V=O<{!gi?)YTW~I2(w~ zhuA)EnIae$7InOgrsAA?GF0S%$E;;^cFd<@YipZ%WXovTeq>lzj3*kLI3SMVM3E)@W#cd$Py=DzNn+Epvm%n_xOCw;kC(?v&D-o$RSAue(G9cDjagl{ zACDB<$erx3Me#V|Zd9C5Y;A4zTN9>Fh`{nnHPBbhH)haX7d~liV|wm9;o)|${!&zw z%cin$lPA6-BVVsh>>L&q{MuJIQTMbYcg%hAUWO6KOt@IpdcdVagfU|{ZKkt|iF?3` z3Y_dJ^6`zqne_pbzcvr?><{|z*G9LtrI>D!-D$77eBydEuL5YqO;mhp(XatKUh-bKdB94;27n zH{u}_v;Czz0GcOR3^KMS2!@2wA#{%oLVk3csuh^tu0Ad6BtTA7?{}B0$US=Wh|6y7 z*$#1qn6`GmU3Z}cv3BJ1n5Qz)pJQU$W*Vf99LLKt%5nzxTw(FJUw^y#Gj3n* zIt;3w;IADm&C03f8Pf2(?|+x0+#z20`c*+TPM|}>hG{MzDVQpkAOM4gt)ilWmKFR& zMCS@qJdkq{m$_;QXQ3Sb-eU=gMfAMu>+45y+lv(%(90lJ<(<|>>R{IT%d!&^C_7@< zXU}d57@~@-&~~V%2BYTm4e`BOH7ArFH8W47mO&W=)&r*QpZ8m$30$>OOx5k2lZ;d} zEj((bY$QiB0WUG=RX0gMXT%|E^vY6y2KB>-59!s)z8N$H+n>6yjazRRM}ZIy^*$w+ zw{j{K6;DK39*7&Nv?1x#rsx_ju!s@~L|3V@HmkNT=2yi3Qq8F*cPl2NacDZmUB|O<4-G zW+ZnTlO+@norYN#z+=BJ^QMMozvwluH%I>pTN{cKevrCXdRFnk49FqZ{ZgNxF$)ADe%b3Xx0b z+$N%n;xnQZOZrHi5PR*#&O(RFPRAfDTNZ=Hzy{C+;?6g*g#`bjM}OdC{8L-|7G_R9 zvHKRq1TJ&L)@7WV$|t3%GBK@VuGi7CEEYo1@JrrVW1*7SgadpnzJt?D^T8aXJ=A74 zfe+sE?D6}Proc2$Ukgwy>Ml@Iyj!)yD440<@LR9$YGv0a%k4P{7ZjVKQ*MrK7nfbMblH8jZT_v^#6rOXpA33kj?F~*oU}p~kJvfq7l2$t- zI_1n{kkr|TU|NL1cmyItjaJ&Pk0|m?Hnhte*FFg+VzdtyfZNjC+WLrzDWN^E-NL>n zJ9Kx~VZvpHVShug=4OU+FDxV}x{Uzb>(_^iZ3Gp6%FdQ9n%E=xla_~*aIRgu=5ai1 zVrXK5eqX%D%KbJTAM6`*4H4SYxlJZ-G@63P5R;XT!Dd}kLLR%_)Y38gx2meD+T)cx zJ$;X>t7M~Ke|&!-aC~SWaB^zj79v?VUJcdkGQu90Y^p0i=WVktw8y{fJld%^Z;UZC zGGbXcKVfJa*j<&^;;%3TUjWDiJ4YruU@zp?3N=!DM?GXqmZtqF=HQUmT_BVrxP7}b zLWfcBXq$-du&eG078W>SSI}Rl)FPsPvBG{T&T_0IP0|j3YA#KY?_|{;ozVOK{lQbY zXw#@cuE+0#$$6O1wxZ~Da^Jb`ED#JNe>6I$x+z$H(5AAvl+=6e>Q&u=9prG}NdvLA z?!h`g9;Gd3PUSwOlyC+|;rJlRj*qcFM@I)6pRBph>?W(;%wsRj{P4UyRtk?zp*xaT zNn(?2?bPvx;)aG{j&*e!TMHUCzn#|9pGwC{!@-&0wf#jYC!mSK^V`vm&TLw0d?MK8 zKnni!M&!^fi4!oB)j;ToygLqzTS4)cOpJV99l+hI38W+M01~w6F*?kuGYK7P&lK1#KU_6 zoZ*uL$_L<#XN?wh|B|P|kU~+!$(pbiNrFgLn@Z*b28K9x3&fv}j;u~55^iV4C><{? zaY;$s1g~QnAt9jx({3_vZGQJ3gUehlo43T0y7LfO$|^?m4Q2IK%=duD63$4kLdc0W z;1V)Y2J@|yucYKsmg;#Kp$$SdQ*fgYaIeXSoxGp|Nou;sO)&sL)%7 zHVhXyo5x^})}z zJ|6=D7U7Q%*cpP9GE{o25rRLGlDd~2pg1j_F^)Gh)+4yi|7LHcyEFJVS8v=XtT$>q zm}H{n;fWqEKlp8gQa;{WvxstrW8>nWyXkaqu!w+}9?w94cgcL4BX&=Fmj zY+?wOP7F5yH)H%DWiWTtraG>Ae{FVk_%RfRaXTC`7mp8g=bcXfdKOH^FKK7T8pC1r zQ=|#so4Y0cOH^$*gN6jMS-0U+7?7&EKtK;%K_lWEDlwm*5wVVlcZ(?M?7k1u<&CNjO{)wumE*l1;5MW!0~kBXRwronvzJi3p;LTSP=J;buX? zBzkNl3=B^S)wB8?T_Jd@2N7B@8~BvLd72?8eNdniCFd5_^x%Vd4N302o8}mIoSsj- z(Tf_$q81Q%J2b=vUj*fF(TQv`5jT8nX0}Ym=kftJ2$c2^#eH;wf`S>I!*2WDE2!z0 zU=K6Z%EO@sySqXy-#ll$pPyQ@z<68iT?tBA@w5pSJcUD$b zdcm$u!QV>ou)5XsvY(7k93v)~CLqNyV8b68Z+U|)_?!?S_4;+6V^CT_LHqW`yFbDtzLAuD?|j~s zEXH?V!ND>3^FAkp37DLf+DP|}O6296W5`jP%3AO`bM+e}`S|$$`aU%qa*i}V$<8j) zdGtB@tND?$3~FU>p#>4iV}dQW zMys}z7EAk8L_|PrEE%ZSpzfG>rk`$qd3VWv7;9-L_p*o|UTyE}#@3ZENi6i3s~5b7 zFYbSv%5P`X1~r`Lh%y??ZOzNeqrVscQ*`$$oT4BaX#aTSbN@CVElJ`b-KC1uFi%_# zT%YnykgTR%FQ71}rL}cotkf_ban3Cj;Oji;8PcDDxbi#Q1b`&7iOkaZ4Is#=&stqY z!;Tah^XtuSaTF;EzEJmX9u}R-=o+v9L8H5cS>?PcPRow% zy>&jyKG-ZST@Ts{>gz?@sdGrAPg=pd^Y(HrbMZ>_*Fg_j!sM08XTVa}6 z46#y`|F>`9(HgAIYmzU0u>}RINi={O&LI_BMZf>nr1*?fbdSo%!q6?>-x5YDXsRHs_6DD8IsT-d*-VcngB|2JFi; zyP$J8XATGRkzj48U(>Q{YsZuEnR=d8?;dL%RYhy0@uC{+AcO_g>jm38*S7(zbh(;S z!4qPV;2NECe(SZ>FR|-!8nx?cx40^RV3SNb zwZ&~!B8jhAo!2wK`FLL8nn+|}1otyE(U=sxem!7wYrjaktu>QPCpD~C@%qE}B`ITl z&Xo|>b?2)v8MjB8MGaKEw1*|_rJQs8*2!vgdU3H0Jf8Vr0q3s8V6Q=bp~dB+gSwQ6 zh=?b82TKMac8oM12hYzacis4Hsfbw1)all;-tBW3G+(N6~ieSgQR#P@O7`=F$*Fm8Q=j5iU;FMN2 z8iBEIoRyAe4Ldx%vR-C!kEw#W$+)856JN@bn80C0Qitc#rAt|5C(70=QyUvMBdcS% zd3k%mwW9Ev%gqQLB{LYG#oke68?eQBt=5P{Midk{?06s$pKvp5So;3r~Ul<90wly9gGaNF%Z6AvLz5Pze811Awat%EpfVcpo?xGwgZmI&AP zQfSM20F?Ie2eS6F)~{opo3cfdJ_1!~Wo5q>!#_=<{`n@M^t~v%3l43Cbqn_|pR!Cs zMzSY$Jy&z)3(L#eQfqamLT-@WIyJd6Qd8-k1p*MMcR^LRu*{`CL?{S11k6711<237J zTtnuSfq~N2D3_Rd8=#!Pvo$xLmXB7{n!0DoLC$PO`HiBpZ5BukEPs8Hd9lXnr0p`r zau1J;->IHYM-lVI#zdvr9fEhYZ_aS&DB0dTkcnnX)G9B6*^gS9T_C>3H8dI;6XCC& zlM2XlxW6O7p=C~MpCTfNpFDX2CH{#;iiE_(;(B@yA@lIy!2@rQEH86JDfebGtmLip z9|Sf|P9^{pJ2OB3a`z)47`^?q(WY@K@g9gg0E0#&xBF*C>p!~y)&l`i7LuU3MdG1T zrTl_|JA_Zs%AjZ=VBa5&R>~&GiOK@A@#wo9G4@l!??B)?YBAx27*MIqUfYu9?(Q$! zpK$Z??a@Hr+=uCK*OxC}!VTT_SA|SXO|xbT!@|SlK`9=*2>FbDJTjNm6w;xWZ{NO^ zj%WJL#LT_?iMKR}3=fPzA3w(%iZ@TW)M_g7T#VNY<^^zhIyF@+>2KmPjlD?Jk)2KsTb z)C+%@ASv)D*glLCW6Kd2_AWb+aoc@!U%xM-8v69`@USaeix*6X1wALY3viIlgZuS_ znfbGj5BAL3tX5roCOOxe&sClq-#t&9z!3IUxY}prrh;*k9_6qCnx@`T*TdKk93e-J zn^O;A3h(oo-U6TsWdFlwW(WXBN@r+`prxTnG|C8v`%SH`YR+cGa{;oSC)%CO{0D=lAT=)s=@_k<-sfD^532oRXc%m8z z#>6SpqQ6rze;0&o%2U1yA~-lo6SK3_v%*8E5RBe;8444&28^Jxjxr0|=k z`xo^&tX1_aUeOrH(f~kk9N-t9CqmB4>?5#>c1lY@?+1b`=1O-JPkAI9*pJ!RzTu?G zJgJ#X0BB8p;RXrU=Xieit~?{DpE7Z+>*MasBthYxn$oL5B#xYkiHY~{u=Dcr>FbKw z>OCv1MmfeNvPhxb26*oJ%p|$_`Kdb9X#Zw*Y3Y@n9j=p;QjSav1P->dw;(QmHQN{j zFdzr`b!1$dNb^K=uL#Ywm@+K#NJ{z;3U=x_xBZotbft_}Wt&nPErisj!+AuITTZOV zjAgF|(BFV1O8PWck4lb@JI zEgxfx@7A1h*7=ufvrQ}(13OC&Jb=^~jwT>3byaz~H-?bn;MzO?+NjpiHkt$qtL4z| zFDL7j{^jDq0FLUU*~ausNJ&wHwAE@XnN+b1FE4u#347UUa!Y4(93CmhH$kt9pw(4N zkVEDLOK>@o&_M@rc0*2Z?{P1PK;Nd?$TqUr92mXsy3#^@kJFkS5?K0Y$CFtLIcg__ z&|+kEIW_(fKa~%$jvE%Z+MCmLhX!?i76hC%Jt-HnzQo4%i{6wj$IB)b;}eTI^fQw= z47#HO9iXk7@3v>2!6a`xiKqk2LBH;b%JdV6m4x3qkr38jW|jhA2<5tc)`_nE88+-6o*gp;Op`#7p}`yO*} zgcIv{L{Y~_*6twB0)G5>%1Zr{2ueOGvdvot@l#GwFF?_dA@4n%7Bm zdm87Wp{*?df-{qjkpy#1ZB>o^@q<80!C%QA<4mOlFkS;=bkXgS5(Qtq#`H_%d8mhD??myIbKR9ow@;o`R zTP6UgwqFLL!tqE` zWhKTYg2l1bP}@Tf-^~Y|DV&AjQ*pS+mX$$L^!JOzjHXTBUzAKBwEP$%_ux6*^*Cjz z^dJ^zSiRGrWN&zqpz$#%0789sXdt4xfO6mg{gOlLVa}z!W7>oM8!;T)_3cpw=EGlS zyZa*o1S;L1L+%HXr6&3Yt~)Y2qbsB{RqHb|t$-`vn%Y1f?JORxAara&vL4RC){0Vl zNTNQ0yfW7HbFGwqGjnrVBr>|g{^FPzHfQMJp-a5i!m#;d4=wERF>^F)Y;QzxrHHYZ z&>%^wvk+1=(r#jIaS0S2kwndJW?-y$iBDI_@Z3?y??R(ex@3q zfPryblaR$#h?qFFFK%iSTN!{Waf3X##7|h5M5Pq_G<0RC&_j5OGl*k=lbnWnml&9`Iw zd_MQrKmU4mIKNn!sk(JJLpdkg(^m?5`}n3v-R(_5t#JtML`V@6I?g=-{cZ&{)=B% z;!2Jnbk)8-hVxdKI zbGzYwEcZ8U7l}YLi=uw->9sNqa5QuIIL@~G@RQWtD&s*3K0UGS){I|wn*E?3zL2KD z#@WG{AAX|P#aT{4G~wVt(D|x-lyXLjJ5pPv5@JLAL6G=wX_rF%eN~_UQggCpDOci!(_W~V z-Ev4#_^4p(T1*Z!vA*mw9=bj8s}}6zld#M`_&G_12t`;?2`wfm6Y8cuMSXPz(it1> zwc3f!_^&+#1tc<_zBKhR9TT;fD#R*~nSwv}Gg3QdPWR7ivO5>#u&&L7kelf1a}g36 zL{&Mq-OZQ>-cN+e9W)!uGDGTbHr9B;%fIjDAVs|dTt;BPsdKA^AbXH?Vf~BOGk=<~ z5j}odKfAaQlIl;rzpqrCjQcSCAI4q(u|;8DuAj5;2al#^`IyrJ65%2ge>fQl@T(9jDj zXf2$=2Op@K5@BXmapd<=s9}t5^zYMheaL~>mo6PrV0+^~O?+Ed>!T~SErM$JmFtrm1Tc3R?e7%!D5$e8s0yj~LZI$4VIBxVsG*vazM%=HXv-^uzw30GwA!l`sMXFFSl?;97o)P*+;ZV|tPjni_%n{?DTe zYhM5QJ!38<*`dmmLfFDYJZ8tew7jcLt1*R8cx*&lw)H`Jas}+azrU#P2L#^ojJiaT zEHZh>-jeZ|_0nIk$NfT6dUyWPWUXEx;y@Ex{~njEkVn_bq+Z{XIi+I>y7+0NX!vg}UAlv1C zNx10u{{QDlm%lB9viXbys`NOUMI-T;oRMBrw^_G9Nf5;N#$rGLxAP{Y3lI2HM-|EL zE-T`1+cEy3=~&E3e6lK#%=JLYX0d16AtN4Yc*PewV?q+D5&tt(CHQj;**EA{=NGt& z9e%z+V44Leu6SNp$BnZrOMeq39z3bC5nUTCHreGrQ0Bepl@rKrGJXGRcypSH%k!Ac z1o@Q1lnfdjjR_j#0o5SLNL}5Wwp6zC2JyFl=Xgx?vCyFR>e;HT^>QGiN`O1HGb>rx zJ-R^Uw#aM~3`s1ZP*Qn^-!BLphyerNZXiy$eCy7=X8wbTrkR&Ix@=KMQOKc*_?d(* zABPjjw*)z4D$x>kL~}0gF8AIb$7RqcymUvomw=Fz!|d6=!_G-4(WQlRet#x5n?$B zI9-v&ZG7^FD70I&WlNt`#ZdQIw+2J%enHY!Z{jchewUm34er00o=|_1IDc>rBL`E! z<>q$n1d>84KDZ)lv1Qb}oIMcQ&XDjAL?-)wJe(xznkZ$U`na z?%OA0W`Xl!m#DF)yX&rpPQ02J&|LK)e`7W;yqX!wV^z*W5`-NjcG){W^f?9y$lVJX z_^6oF()_*FXSpkp3V1b-AJ^}UmN|wyf^3TO1ovlra$ZQPd<+ROnDx5>(7@lR47B2) zzdvtEiV?c9#!933(k%i4w2C~W6~9CAcN{Mjx9yB*Aq(jZF+V(Vv8G^hNdAb5Q<|J4 zAoSTtpsIN8NG<|%BYs=Ln4P8?>_6duBS3@?Cc)#@&-Vl5SN)rk3kW0 z&IM$VWUEmpHj4?eATg2GeR@u7V`jrS0M-Hsouam5{Opco=aVP7=KVJ@AWY+d28HCF zC)4ZeV#>-KD1?T%lheKuWrEcBKpG*x`)+-2TPUz7ye>TXp|%?^fL=sR+!btWXj&#A z$6P^3$B)j0ExTa$NR6-K>>gYY%88`*+Cn22r`4h0me++75-9jutmwhb{L(^&uZ>;we9@b0~#UK=THf*gKepaX}^ zh_taWHq@e|_nSj6NFdw<1Ga%r&eObQ&;*(|kAp}#f0mR)W@!|?S&$AinnX{@hYwfB z`1zorgnm=-S}c$2*Uq@|H-nqgkOxI?U@^s7cj$!oIZ?#c+1{ihniA7qI2WF)z+#Ys znwlCCd+5OiR#Sn+Wc+%ub5qkGF@!;I!^0hmaXX6_&Jqs`5$KqczTHE4ofF_cgV9&X2}TN77c-HTnR4bg$#Bj?rMnJS8&csE17 zk3xL%ob_w@df9cTeK=d_`;TpzgwM@YNuq1` zXlT|m^(GeY&Ks*mzeRHGrEQ0~(`Y3lcU<=;G7D@X^O=tq2kE~B(|U*>Chix^j+GB& zsYzoKK53GAW4lyq+FQpGxn+H?KiNQT*iYEVp{L#&YK(?tNxk zQI1%K^7Lt;GZXMJtGX&TFo7RtAVG_^?U3ycXE?bVr`*ZDo|Ag9OXcw zwvLaikOzWl77UQ#)}2Xif$mv=K6G{^OAv}p+B0Ec`6mAyS-(WyUB>=}*Xj3C0CH=4 zdm-L^<7Gy7o<#(Ack*jmSKU>vA0d<`P5b1rf(bsgx(~RyqhNEV0rUv45MH?j7nt=z zqjD;-iH`7&n4vtQ=R&o$W6qOj$&XV%e{;ACU=VajZDDF&g!WLEYla&d^0Gri38!!0 zKK*Tn1sp&f)Yj}JoaRS0GAb@VRF+@D6|F<(To_4gyl&vt{ zX9Z|%0!N2b+FtWSUaChvO2mT?Mf|(j=mQf5vO$~bGZ59DySCoB%XIv1M&Dj)7~+vU zi$Pf+eoL$N{)BUq6Ij7hNWtRV^I}JbwSk~=@t{Z3buPPZ_LZ%jEem~Vp?B`wL8ETa zSWU)5lT2RT-`2q{*{DsKy-~n&NQ=#^=e;8|pn#r9Q2ib5A}J*~Tx3P3rlxjye9UUw zW7rwbuVFAa4$`IsgaoF&MR8ArQvZ5pN<`6_FltF{PYU%p@Y%NN3w+>t0aZGDIRrVi zIV}R67lstDXJ%&rbjecm+}+zV8v3obI#w9^?(`Bc57&4druNszkCsyl=L}7H%N$8T z$KjQxW$csA=vH*~-&>r4i*((O@{@!%p{kgVCJ<5J~!Gd`hyh&wa z!N@JBB=cQqVXOzs9pR395J_m~iIzDPxi3G zHz>tSeYzkTFd`Bp?kx8SpZIG&W6ZlaSHqkR;raAGYaGrQNFBGI-{8Fee5ywfS(A~# z*@#Oeu@U(`=&bNHVE0$Q4zAMhM=3DpW=fYx3&H01aCx+B|Gd%7?fr-3qX!O$C7&N!A zpa8VYs_OmQ_gwax78S;=p&HsBpTP5!t8@`bNb2tQmB606v#nzud?lc-geD}&Sz6Mc zdktJ(9o)UobfD_*>pMNa)&W%r(5VxBQUMePfH6Ktu~LNnn^H*qm#!6!!mhs#EVFO} z4Y-|E9FJN!9WA{f)Rchcn%(M>JjlXI@VJL7Qp+j0=*1@`QBhD(ggeTLiibu;NkAGC z95^VbsHmt!k*W9xlMh$8J~u(eKLM5G&@gr1c>b7I3JL`C^YbvEpQEDQ>W~M&blA03 zFSZU6)~jNMdYqZ1r5DoDfgSTowCoxjHctUB2a+T8pK=etxyHgr4u{Ql4d5`#n42ud0n1oe;w9i2=JdmUte(Z&e) zM39&s)~3m&|Hq9yTtw3|KU_p&c=(@$7PCjR6D=1qZgjU1Vnh^WbFn*%tz~0lx$N%F zc%%$CAM5iUUuPH%Bobp=CgNgu6idvGrm@Gfz4G9VJ~NyySqsCi=?q#@7C-)?`F-=v zcfMRak*Ly?C<&V%@XzAT^jwTOB8eV${WUc)wr*BWf4d^+WOrAae-qIBrGHqmiA~_#l zY%TGt+w`xDj?w-7Euj>J=U#uVw4DZAyQ0F$2`g%-(w+FGz%KK(Yg?-)D5kauX9NNf z&1R;*Hz4Wm&b!Mq+C=t%i3z!~0eCL(<^RgK$exfe$tMWU3yN8{cA_|Lnv|1U4?_>}Uc6j1c*cku+bG)&T0A*~{P)}BU3M+fprCidD% zVh?xM$4PYr1tH-F9|Q5`{-ft33cb1L8nG3;dU40Gn zTSUZ{2oq0wHg$%5`~^z36$Q#YH+~R7Rvv|B*LoLK)tNtyOiX6ijnChHFUmvb%=Cob zDxI}=D{$pwDJ7fqPA`*{c7-)iNpSoN9?02YkKiwiBAi> zkE;IQw!2vnz1ZE`OA7~t*4Gb;nul^`Ni?Ir5^5RGY2=>eM=O0X=KZ2D&T%KgQb*6^ zd^9=3>$68v(F$Ma0I;}z{5iu~xT5)_OcN#gBeBm7EiiN^!o!19#G~JARHaq-S5?ev zLzi;4s}Wq~uRc})I+{XLaOnqpeCQzNb$LY=(u%F`O;EasXJ$5@mK#28gwIIp zr%Nxx>=YH_2>t;Z#!jJD^gf(0)0{nHxbym7J2$E@PQ?cJxpAfjTFArlKLy(KHiw+@ zzP-cDaVtU33$}Y+0iR;&uipp7;xSn-=QIB#exW+P6vw?auYYEw6>4nF{=-Q{{;rC; z1=-K*; zrpbUGL?+MkjKw_g*;*La6)xRO=04X^^PB8XE0?1K#hugOAi=}tkJr{tPF0zV&V%kE zg2h&|mimtfsb!48K0@I2z8JSUv$)~-NX;1w@9I?$l)00o9FUY`5H?Rv{)(qu^*=5E z`87N|!#YZYs&?zt^0JyyX*4wLm za8$z{UU*~3#%G?tq$)Hc8TbZiQ?;-5O0&#~1$#-gVA`?3x4Y!??v?bb-_gVa1vC({ zP_b-nEK^W83aWH>HvpT~1#Jx{XE3P-4CL2YE6o(k`Rgbhv zdImXGXGp(*`xlnSeyyPRGowl8d#X_DWQDVbdVIQb0W;TKhnv2Yse+an|~bX{hPl>9{~w~V~|i0yeu zEDxe_WNF9o&N^L9TH5nOr2q8udg6D^!jw|huc(JI|rOhquJyj3)8=j1ckWsGn}dEX-L8of(lUw zq{YnxbAJ4ICq}Fu>gwv+on(^Jb{zQe z9yjg%c|%)U`@JuF1CR=S{CNZ}KIYrE7;F{;fgc94m{5P)ds#`=kSwQ*NS62S--GVj z%lw6oj~{-OO_s&_w6{w~b69;UFE7_}FETePlok@gynQ3Bma9g^ zpE6s}YYiIEmN_g-!ZX`CI;KE5#Cvutb()3fHc5TqOTf55$5Ai@SFT*?LcBm^c;b<9 zeeehRNwlXj`gk}MbUz?h>JO_%oO)tnn&A%7n7_V5^i~zaU?cZOZfc~&58J0KMy#Rr ztb~eeJ7+1f(JavtKWM}ZHimB93G#jPtmleo{kyQ>Z6ftN90u zWGrr!`xD}#^#yD`>vy$=b+RXZ=gHLDI3Y{v+SeFv zFopY|M(UB^)sd1frxhO17{NO$ivi3{y{PzQqx>MAqazm6&0CU^l3b1}kEQN1VYgn2 zpd@BQcaGzAB zmHq(l&bXG=vgWcvi+h~sTQODDpnB+azAO&+t?5O$VS9s131E(c;^5@^P8vPyqe~!c z4oQA6mX{&&%TzD@nk24x?Z!2|_Q+g7MuJmQ^PM`(D@I%=clnj)-H>I;$ska8`~~W< z(UmSB3kH%fWQn}OIV+3CUN@m2#H{Q0!_fEyX=rh^yxeqknBtxLY-1xw%)58@fahP} zKCgrZpQ1;7B+6@iKSuq$NVc%WvjQ~{^12Z#;h2`GlpULQ6y_zJYn~T*I zFW?3^Hybxk*!PJl!hKj+t~jiFbZmrIv0^rZ^aPu}uA%4C^DQ9T-*ePPt z!6RuS3@T;4j^<6E+@L;rks6drvEZqG$i_kYQntwZ%o!B}I*`c~6sHvbwfQWxZ{Mw#8}p={rpKqNtCSu^v}z?2QV%oU856GotguCv9w^ z^mIY4_YWXyl7>cxep?PJC`Ldj7`&WS>5v1W>y!3UgQnQyRtn4}Je_B#Z)MnGLt%PZ|oZ@_IzgxCK>@B;MGhSaEYgMLzBn- zl|juvz!KAIRd5610g=lVUZW_<mkv)=A-D z?ELF4P?r9Am0rVL`tQ%8(yuV%(D(oQb&cjbw66N+#qto#;h&*{pHGv$|L2PJ@7LX4 zL?k4L%aF#D^Jo6|*=BO3-bOz-b2X~gvvC|2k?|=-Nweb=%KzPJE;xN{sre}1#OA21 zoT4kP`BhVE4*|8wVmW`o|6XKzZZ$A0jtIKypR#sJGkWJ~@|2%&&1N21M0Up{wdnuhX zN!Q2!u5{WRW%%)buKVGe{0r*;KBO=Fe>qHd{`WSKpD*$JH?X$}75<;SiSy^eLU#Yz zSqUk*#S^US*2iUOy+6MI>;|QPnha~{y`viyBBHPFkn=cI=#6d=(?4L~k2}ANJ?7i` z-!!kw;V!Lz2XY8VMM(jiHD2ae2dv}1C*uVs3GTrKySo{|~coo_}V=_!&hNV)H1Oja*8=MiY!a@H2xdV zQWh)+=MP|Sf!+5Qx|(zAcw)WK)typWGatGXvChO(JX4>TqVj}lOJ7NSW!S!X-EUBrDym!1$r*T(fxT7ee{m)n| zx???f72yn8pFsQvK%JD_a$cW|$Ziuevz9~=|D~Rk>ll;mao3@E>F}a&|5Nd#tAFan zF13Q9qS|KNO$V>J+dpMv{J@RLpK#ysJD~b^VQ+tzf8p$}sWwq&TZfGS9=ywb>EbqT zX7j5GPY-Y?XP|@VO&lyjL_Ndi?My+M&EK zO{<(^R7AveVc6tob@JjV9UZF7^S?dGXIhZGiT_I@hXNB56Cf@E0)k7YoWDrDxJxdZ z4rY^M08NifMh5Evz(?PMNa=Q+^VhQHCAm!W^n~Q)Z{NRvAEPf#8_Aw-&4!WESSdEPJyZtj+aOPk|3pwLJYU+x;y**fOsLR5rX&)oQ z$bmZXkpddPz8Z&ZQXxipa|YG@bRM4hYw0s6R2#~s>SIpMhLV*2jp8?Q{nM=)mcYbo z&mJ$&;nB%Z&MMdZ^5555rukleIh)=lOD+GYc7#cF7$-gRXF0*6_W-P5#Ky(Z#X7%v z^J{YtJ^w&vOdw|X1LK>s*!~bWi~wv^9d1jFjg8x^{Yi{}K`|A&KueL4c);VL4j1mrhJ!IZ+V>OCXxlMi#1@ zxNi|P0AXmUFO87&-8*>p8sNE*lE&Z;j$4+u!Xk!+mZ+9*EFB{d2mU_=DL1fVzmiTg zCHmlO?QiKVZ_lH9W7%v>(3(_^OOAriy|s3F#K&p-Xtc=2#QhEP%Z7%M(lUk7?l0gQ zP5x&5_qo2{1Zfkhe zG}l(T1&ogC^73-U{z^t{bMsW`N5Z4t=g7^`nT85M_x&3ivwPJSah2`|z!dzHP%X$^ zTH4>UA6GnSyh3X82Fkj?4t%buc@c~1n=XDLWvv?e?_@RmH0y4tR`>P2{BQa`jJ3f6 zgo58X5`Uk{O#6djzf@UF$8 zrf#W6|7?r7s=edBWiGD1AD}&3F{VjCFr!v%Oa!iWala1GBXJDyKgWAzM$-{}Igts` z2HA^Zgs(yEXwg@9*Nrpshoj3Ql{jl29zlzoI93l_Mh7$~r2ca@#s-5aWQ>sOT5P66 zpF2Yw01yA|(v2)0pB(AWNYCZDT}lbL>)uowgww`ELmDCV@BDl!hP7uPb>GNA%9%;U zeRLJN=L?JjeALsPw;ka6|qoc}zPbqnIo1n6!@_NZpO^4i|YAZPr}{#J@} zf){iZeY0yy+lJ5x49Fmzr9gbOS?qXn^ojsOj{gkLab;jOUrxYqp*(-M!i=g`qgdD2 zSS+FH41~)G7w+CA`|!zdZ6ypuu|wDS-M1!2FXnnur1;L-?b&RmYl#y)|9lL@!^R^M z1p(~Hy-sOxRc>*evP2heqI-}4U7 z;#;00hK&CX1CGQ0IDhLF3kwTSMb%ZXEYg>u69WD`2AlcZpXP1@=y*TXgf$5YyiLt4 zvmbcLq`bTYtVY~0b&ZT<@)sDmZV}lkO?qL*p{Ec;r3{B{0$|gjDRE>HlJ#R_WGbA_ z?HwIvW63oChq<>7sFx$;>F)0C z&i$^f_x=2y=X>XydEY<2nU9%!=9azL`?}8SjJ1yASjWP95(O3r5tqAuHjBWE$jLHI zAqM7LI6zuZAFNF@#61wPO?hWNi?3X6-Bf9+Vddcg9jxz)cw7xs{o08&>DU?~8Odq8 zGpB3=j;AVX@vg*DQrcrUQZq|)SAKyd?$UTM86+JhOCMMrPcR^pb3y@gJ|?X*9C#!3 zfyo+uK=OYcd**0?=7@mS4#<&_xr^F3Aqu2hGSbquWrgW*=l2boFahEA4i3ik#BA&; zlO%!#m&wb=#KEyB_;F6o(cb>ljFruuuX=Ogg9Iz`JxQ5(y1L?EaP#wdZxX-@GQgF5 zwBf{J)AsIxfVz_+KdIq!UPKDu3yeCSG9;?IA64VJakPZB=6MbbDgrO@zq!w4Slm)?E|veGoa z<9RL=n-!u)@mPnr0}ANsfkA*clDS2C z=XVr?KzfKaB{@g3MD7DdOU64enhX!w% z;5!h>8E!k-RyzOA;{6QG-|!2|tyL;kzO$27slAn6JYzCdpa{8cA5Y>5 zfvwN&t!H@BfdMAlweB>hV}<5u@*(m^)=pQTsy;98NuH+6ZImV`5p8X)8yjmoQuhYg z{uvQF`D3P-rHkozURHowfiL!kL)9S*?E) zKyqhdKD+%SsmTjme?zQ^mLxwSlqHT2_s7c)Q%s!9yRLmMHmsb_W&Ll-b|8E{?49nx zg}BO1cUat)W)nU8%$44$GC-UsZn%vlR2&W8Uo=f3v^B5myw% z0&RMr7UIv>n~}A)w@;r9vw--gwlC4kOEz-n6F{@^Huk5CHahpOwM^V1DWY(z{d|eJ zrx%fI3Lk?ikHj2Ce33k+w9N00GM$yczbE;|BOZISl>uWHPi-RUprA*;JFB;!l9L~P z+uPG1_WhEi%wvoK*Y;e%D&zgh0I7vF@{OQYs7v*=xOI)?mfgJnpYVit3bHXMHHude z!Gnt4F9CdizG8z&E9uFUkW9AIW#m(i{`M(6ytJ0EIizto5B??Y^C4$ z1M;dih;A&Uy)&fNhHf68Y9wl+{(Sz~Hh$YJ;Bh~Xyy{4L@>F!LD&8e4Vt8mMFf!V3 zh57HzNKkR`C^EF-!1IMn6NO&?&p!A~fZ37i4t6Qq|K~}&wB(4beZE1%4VlmfHLrIb*3NY4I`gQJNVeJ2XNvO+%btSV;NgLCwQ`I3{N% zW1aK@bDz##B)V*n_Lf^4L$3|?kvy@x@zNzvov$$`X}Rk_TG-$a<#ua z(P=PCvFS$x^l*|u4)C{A?|=ZT^OHjkO9B+wDD(L^hx#MX7!-D6Zc&pno0 z(a^_BgZLd!UMCwV!)qocCX6aP%g2l1EY?q;Et-1kKxX4CRR4Y4k6^1O=C1daOGhSI zknI`Jk>ah1Dm709IDpLI=mCg|U@U%P-NeHm_4@7l)H!eS z0mN&G3Y!yccAI?HFbIK*c68q@)a#!~&#p!$_m0!k6`Yzkpk)K@$SqRdFcLMjdTOe? zx#CH1iYVU*!ysh+&@om@?CnR%{=^^QfT-M70*S)ADl`+N`Q^GO83XwmKg)nl%3NVieI==yWv>VPRHe+(cI6H(m#Ljxcl z{GK2V^P#B>gXkHrnH!t_U{A%A5Mgnlq^e4zpGVFI6=U3EbS4X;-DcP;e?cZPm{!;PW*HI%CXEh`GQSDibe zn!!JWrXW?dnjZ>{>jno0Z4Az418^z~iNF}imw+cp_!NMi9GLfFex#B^8{;ryniFTo zkZKP?_oO6AXk_Bb)UX*MAHm}?$@mXDn=d`BloCX7@b))V%j;410>)nN1Rp2Njh870|z zWXh;&G%x{5)VJ?+H@V>Oyx1MLrhA*?Qk1EfZ?yiN|9p)Fx+DigMn-Pui+~QGnb(nU zvo)3v1_^z%Gzgk1brtB!a9ge+p(I4aIY00-{rf|ZCjEe=$ZWT#1JJKJ;Qyd}4V?b; z3AdyAyn_c>Nd%UfEOv9xfLH?cR_3-tZ<6FO%(J8ACbH%3OrlALT@3J^nqh0o&&inr z+q;^Pkq9t&VzldfbWdfXyar-lr;B+!D>sjxas`G9UR&n6OP6WgKA>#2M>GW7bpC0b ztzs}<7A(bo{#~~>dAE_sxGPzK0rZ?;>7^As3%8U%)kN0Z*7j4p*a%s<=1a=r(d>M| z0$R_r{eA^ogSlrwfWQ+2heM~|W3U9Mz*4cTH#vNN!v4z9F_Ui3!x-CxcTfxbJ{|#T z!JP#nV`S0n4F+ZP?Lf+-<5L!^HvC3E66oJU61KJ1+o<2x)@HLfZXM2KNO*p-_kfDq zLluvqY9X*U+_+k@=~Xm7o7uxk`-6JG2B7BbETWV6{_$^Y(B_B$_vhP0$ZqfqxuB|z zqPK_g5?>-ILY2~7GRTM_XNL)b>H?8?ow)A@7;+?E(w)$xgnMQS6|2R@sxb~{rldqn zpUd`FwjE3F-)pHV4xv+#*o@%|N3?S|Y;}tROS4*b2+mos*Jd+944>(I5kwv9;0=DT zDYaaao@B^iO4aEi92f{7DA0j80xV8pSV2PKmcaQD#c-%XG3*R(odT!6!0y!6)jj7o zbL)ua$v11b0iCQax%l|p1VTk)HH04bWM_Lj9)iG^PmINPXKUR7Wl`7G76$_%*x71f z2w)G&aX2;u{WQ8DR7hI6yF*jnT9NjM?rdjgB+2CGmpQOVMSh40C&yPNjix+OT^=%;v7cBun4w4Kkf=GKWVqYi0_~LLM>8`@#ZrcIUai}W-p0Xf z#ipdV`vBq1`*aF40m@{&(4jdwQ3)2rJLlF7<`hEzY5^v@p%{*)2@6Eurn8N0Vf@hm zT;9eZX}3lkV^N6tqTFYC@CgZGAr5QMBy5){>Dt3g2FAf!3GXMfy zV9=jdix240yrAq|P-N37<+#9yGdr%xf*jJz+xO#o1e-$t;XIz|ZBo)#P;ZAgYq|v` z#Q3recWsD>h#LLKkY+1Sg&lYSigDO-Mu!I-8K^9NC**Dfy~#n}zk`5) zt~dEr!)TKy6mb)dg0Zj%?3jTuF&&UL4CmRhXf*m)F7W+{SH|>_)(ap>?I_RJk~@lm z)`0b?GRZUrl2TID3)RCx0mMuf#c(bH8$_pC8VF!%Ed_<`QoLtQezEp>nI-rcO;1hz z0&PAl4-$8GcifXSg=&7wl|Ckwatb=%u`wmR{H$)Z4AVyD3J3q#|T(&jL9{b<>lvAR=5@9$;ZU>WxNZ58=YkW+#814 zSJjzM8xzKVE?7ZT^Y>JZQkg}wjnR=8Ht%*l4y&0dYMjw{nZkK}nwcYr3O;`Ph##Q2 z__4R-dC-kP;>XsK0O^9mT+;JI_Sfth-SD8u?ma<@SALa{iB{U}bDA$m1RrALs2`iD zoQ_UHuyG#@p}Jw$-S^|j(kq6wh-3zxtIqF%fdy=i+g7CnU!YK11Lgw=7eEVI-v|y7 z98SE7EqtDUhu%QkheetQq5&$&$UD}@hq-5bmx(z|rXo(w{yz5fi{15NUt%_IAZ-Z( z5|fjA!E5Tqx{{Jo78lWaOZ9sE+GGzr&09-@n`vLMJ}ml^Af1gqxnA4uMk7ib}V zl%r57TezaPZ)ML8a&mJY^C%cimZzOCly!s!H+BC0{XsM_v0~nNL=$?D1mz>o6IQ*x z-}rw^Kvwat6l#x!hm70dS0n4ZX;pbtp)TOGeseUl)D;hjDN?)y;E9w5+> z8bnPSg>*@_^aNDr;q>(Mt(&*NObit+7YZwojteveid6;#&Zno7-~=15c(?(|Pm`@F zp*Xs)`&ie1bxy`o$J({Ll>q_?;ycP+GYpRxhZ;skDg#+1M-hhxKuwz-@BR%|KSAn} zRC!FL+7YgCc4)8`FQQap@(Fg2T9(`XTNXgTkbt-+9LpN zVP<-|26Qdpw4^!jjSCKYAiW;E5kG>9Jw4qAhj=PF4s_azWn^JV2u`L(`|;!YWOb}o zd&HY^D?{+O5d!>_$9nB!ZLidB`&g;q@PG&eno*plpFtJ?xe%-tU=(*ydhQI`Bi-DA z(o#Pu(B0b{9XwivS}HYI25;ZJGX>Ev2o`AQnhFXE>Kpp|kM`lBbjOos%-UN%N!bGZ zz*@=6SDsf==cy~FTbiQ1Islq1__N&6%6@N+`ljAEq04Z%fSj4}g8SW*wFv%MGH9_r zYn)x#xOO<%)ZLBk0w%6oryJvL29ri-K7;$$80t&jfljv(QIwMd;JfSG3zjw%fJz?G z(bbQSR|=m4lY*;-s?rLFHUXaF%CePbynh2WKi4`wwqcORcgSE~#v|V+TV5=PTrj z)(eIa6R~VJAKk?8%Rm*-$`3mWPCpThn^qP`m*zDnHy97TGjoPeD;%3(xY^WcF*IJ3L6M66T0DWLWQ0!G9k@*x>-3z1oJxAQL) z6bOFnH0nHi3-uK~iwGZ``7l61)>X2}de*JgTt<$jwH>KEI2&yo#yI^G6SwPX-H~pT z#S?Zn;n0N6Q^#8g0Y?x$Wi-U9={hJ&xSYppgL!9~Ruat?uh ztA;3s>W>H27Y+V7j3dxB&MbAft}YdOuNgEJo% zPcAsj!1pWX$FQX<%x-Q)j^G=;#M( zuA__8g8UHhFMDXqV{1G>2gWf9h760hk(nvLC-y#CU0=o$RP5K;tlZqy7+GdxS+v5+ zi2uHfT`E$5rp(sMfAjCn{P|+q|AzS0yZxW4Jks778DSP#9V9&w`Ezac9}U*m;M`%d zBmg81c3sqrIVQvqWC)iM%MwoepMcK7cM zlxG>8d%S(8XudLsjubnYO)?Jg3^1@+Vq+1~>gyA77=n>Ee|WMK^rF%H4W53du z=^0$emfHOM?%ZNz*+amRJT8^-q^O)<>$5Uz1j-xmC*kf828kh|BQGk2^QNSqa|o_Gu-E{4ad}PGO=d{6xMnx!Vn4`@=hNUMO z!*S<&$rB3=nS29e;|ekAc%LQkBK;#-Wn=5xMn6+ht|MMW+YB{%LT%w#Pa#wg?=21I zzd!vu0kOZKg+f6dYBUcHaM2dB52MR1fNm&!eViz6^(x00qi#Rr<5Q z+S=iw0jj+lux+PM@+T2UPqO0iEM`z>Xtl?*4@`ZS!NEZf@S1AnGB+_bE#0sLWdfaY zk#9YP`1R4sNTkdK8ce2FbiRWV$wu@FAaxmv)iF-zrwTeOc5V3VSFU1*e*IN5^j1Fm zU0q6dg5P30@L^|*0{Lv5VL#_SLK=3gHhl?X7pPt@pM3xv3-T%0hp#?-NV(nThK?di z$|(r4ArK6sAYo43X{d40#T=^~M)fT%H$chrk75WK zKV;=eK^If|3CB&ogSAm{X)|Wzv2n2*%fxcJNfuA5QEWUJ1BdNHUh>aFC7kyd-U)+` zl+lqr<)68g)DO<&N$oa1Vt!c&+vlPeoKaD$NX6SrT3XWOfoOm-Ak1huvDAMA&R^fe z%haJwo(LYG@~dM9obPAsJbAfI?gMmeFkBH1hk2mY-XlmMVfRO+eig-76v^St4@HW| zKp8Zgd+Q2CbVYfQh6>^CrCd_H#}A=k3-al^VCx4hFkWa_TVGSv5Q~N4L9i%l1iNy` zULaDmnQiCDjt~OjO${K@P+Y3sxmk@vLeie|OK`#Yl)jVqoD~`xBb;DLr)D21~ErAGS9yaa%8pZdN5I zhCYGHHkD$dKbujh<-h=&t@()nth8Cx{7Fg<>cyfHF8c#I_-d1jiXtE$mb%k998ct< z-0oHwrkh^s_5Zq#0Mw6Jnpa^7vJwy8C2dt-q@_r8t;Zd2Iq}BM`p`hl-OvSYLXB0xzKl_|}g$ z0hLS*JdJ%nTYw+&7kE67aNHu{4Fjg-y^T$dZEMJlb&spppdhJXqSBt=ct`^R&^)7Y z?vN*njW4q+YC%AxyE=dM*MekZ7{4XW>!Qv`_ou_fF_Gmwvt-UuKn7piTSdB2qsYt4 z<7!=J*X#3wkuI~?kkHdx!H9K+>>RMahY&r2L^Yp}_4~p4C~}ZvCY?dv83;gI5WrvM zn-%8cRnQ{_>52#5+gD&xfqoxK%Rz#t)i#vd7RwO;cF{zmz$EwP+gpPeA98Svawh}{ z*q{O6>h}fO^>GFb* zP;lIC|N8ao_c=I1zkaHc99cMeUqHZIhi?E+jlw_#j6{mfWmF91kdR z;C2WN=eKk`v2Unr4x%2$CVT;n*|+otkz8Hm%Ipn9>tU(GFtdg-n4zhy4$%7&b9n>U zAb))c0BAz(+4+S9Gmv^A4FLg1G167~JK4EFvh&<4AOU6~a`w6)Zz~>9eS`6PkiWnB z_%UZGl&rbEId#Y8`~)LxD_J|7+X3h$6(%)HF2eriY-Yd50FZeK_>GLFL13vF29leiaP}(sDaW@P8cS8?10g z3&14yHIL?oL_J4;5mQ*CDDnv1=WLr(W!Q@Lzw2QxP*KkQ)x#)+pcfd-Kc}t+QC$>n z*Z573TLhmWegQZHOrlXfXc=L;D3n{V8jgI264KeVVwvC&d3lv8+y7nCH(1hmu`{6$ z#l2~qDq33Z+4?-(m$qiUKL$prMeclPWaJJ3L9>h$e{;cd?=rx1Zy%wIwAN>RoU-@IlyxfAz zm#$j%uOM3%3xd`Nc1N#RXC+|rQAv1?-;@_ofQfs8q#^^U(d4(_)=*>&K**shJka0+ zGwbgoq1oeen0rLXs`J}pU*9yxI!-Yl<|DBbM@(@}PTZu+CxhVvY>vamqhmBABcAg6 z`q?G!-a>mU`D`V)D9ivqLJ=#gdy4E=l@G_hs(k`daktKTa%OH$LVlp3{QTL|D_(pS zUuTz>eeGwS^CR{&I->bnL8W8!^CbtUwcI~RpX?F206DM7jyAnCS0A=5Wx~rBJye%l z%o_ty(NxRM00b*DmbUEgZGixR!UHK^mWn9atGx57uTaJ;%3Hul^4PYU9GMB(br1`S zh=6I;f)7J=ef#)%#Go>IF-?GiE!R3y2Kg4Wu8rZJp?G*6HHVKgY`vz&Vq+{Ebj#DT ztF2A3PAxePL`rOO*BByO9w^9xw#9g8!J8H!9tb*E$lXyN&D=4 zKZH-7q&xEP>^d-5DNqyqGD^+iJd~^(vDAX?=d@144#=Ul!H15C(n_HziR!9 zxA({PmU)z+k>PCKGdiv@89b~9{pgn3v&|+Vwvm*=!8Xty#fNN)$pw}E2ir_ zWfH{vZXC)@WJU9!>h%0X2ThndoMMftAVEV`(}MuRm!%1en!^BzMgb)G+I_G&=!NZO z#_1Rz2$WU?>ud(#e4HvV(F)lreB4$mR|JnP&Qa!+Rm$uW+xHDd-xrn6ZedgScGf|F z0f!pF=F2~sl0-su02cIRs5m%@JX`nE9U2-Twu@X~Hi!v&7~b134(8Zch}@bF=_ zfKY4AeaT}yG1>jg2wH(01{#_lKYv~^-_5gSJit6C;V`Ogv({$W9Uq1VSu-%O;jtJ( zcj7*~+=S1jMVt-aVM(pv^?O`ROTOq@Zplx4*Z7rvFRg`81esapyf;T2fki*vmf2B} z;i`Nd4SoI?l(NGZBHdr1Nr2gX8gK9!?LztpKnRMB{mIi44WJs_tny*2;KZaP2%3bE zhO_LB+~MKjyzFKl-9s5(-l&717zP$|~{g;r; z_qjIBcg%Ko!g#bX%dM0v!`CAE(``?dlaa)9(fTMCF;QzBocC*MZSZMcrNlaaYgxwU zmzLZjBY8%Pj27O$Cq(fhEbS^c7Fg-e?gVUjxRTb_(f$zf0%NT7Kt8u!6Mo{;lG*3#zC_HkjQ;%^UW>;bqAA=WI14)BLf0c6Sg z#aX<^eKJTL7(hKc3#-{gr?%4!&eQ1()pMY2;|0;bUnHwq`$|8eSGxNuz(Ej%Ak`ZX zo*~V9I9;(@oObr10a*}KU!7u-fHlnh#U1@XT3W~xmI2M4KHbbseHWxsX&)3D+N6!R z;9#gcnlT)F^e47LL|XClBXwLw6yHnga_dR_DGjtA0UH3iqnYkJ%8O_+keWqDjSCKOQg$4qI2BB5Te48a*m{6ZG8|rnwVN93e|~m@D3ung=~t9 zTnmHQz#&&jBhTM!Of4pJwCi_+do13Q`xLXBC=e^>*@Agp#YlHvFf}NBHAX}7&M4p| zAE)=vC?FP8w4K|2V)kd#n8S?NX;B4noA$(@ zsvPGv*NM-uYIZ;xJXDFaBs^g8vpNp%*Hs!ra!c$LGYk z`0gnx_Ph@dDfzQ^{DGTXpcUBK5w%Y5z)h&EeFhtJsU5%x|0&Jl2Em!&KM)_(+DQB> zD~G@SKdfQc_cr@}K2(Huzun55E zZUH*S2+xB2ki@l8<6K$>Z#yp6+~ik(CKJRBpg4s-_93Y+%k%;GOO+`m9bnTpI~!tp zf{Pmt;2ZL%H0VWqK>^gDu&fNE2mCi|j`<&KE>4b!0UnCk$w!aWmrUV+1J2B?N$9=s zPJM}ej944DRFXSH{MsI@{CNZazW0wfa&r6+agZ{MXXeY7aXI^Jju;x5Prtw$VAt=6 zFmKfQ;5y{@0sGSD8_&|*?u6PqJI7fo38E%OZ6;%pVQqZrTzvkNb@g8@fceUV`NZO1 zC&M3sI(>Q)Z4yiz#rJvV)aCHRuRn;vw-aNN(2}!!aPcyNweSIWw3MtWq?bLCTY05* zjfyG>A0PiKrE$k!a}^sJFf)TB0V(Yg6B7e$K-ThGjNUBuE09QgLTH}$O`O9s*}7ky{XUT;Q$F*(n{t)X<6{MF@c`n5lfvZeoo7H+ zEiLy(y6-y8HI+^VMn)?3KfUuq^iCYDc4H%3Od9_pDHRJvG*n&6TQdE&(1W4^~fvPHjzhrjD@NUN37CxyS$ zy8kd+{d~4{e&}#;yhzMz5;ye33U-lqrS0> zs3IaFm{+cB)%X&CTT1tEe=q_LqpZeyMuQ_0n2JYE8;57PR`e)INl9(tr+lR2yd{>a z_hKDS9z$?o|8pH#$S_`M_d&YVt*`Gcdj=wCZtfw}%GLd5($M`djDlgZQ_pmExSsg* zCeO87gr8Hx35LPM%4qV1&Tq z;IpgW1?z#cTrFG?4~(WNIsLu;y%MW+nskLM!G!Lqz9f3bQ>^--p)jx3>9c%W3aDEd zVP-ebX-LVPO;Jw9+^j&LdSa1I9pxqjSP;9VNJzW>+bdr5SX$P|$`g}xt`-`+9W<^! zU07aS-8}_;5@J_sgp+&cL_d4`982KCV4mhT%~%3~7&uRRldX-FMvBD~x*1Q?vkP`B zD=UG>`jzNtuVQm?Rm<^!pipmq@GkVtWdKj2rcz~|37d5`urv{b8c8x;d(i8=&2@O3 zUme!apU$+mb$}WdnM^&H)ws34)_H8YQG5k0`f3~^t_FDc==g zG|0I61|0ab!+-TA>yAzkBr*$p@2YSo z3Abj3HeQ-rUDJ?Z!lpO0&3&wG}6BVT$yrGyR&}AdzbQTM|A!;CA1=lQSWPtlz zyKAb3PPNE)?&m|8+TkGeyG6`;-SPaa5$Ygyk)AJb&U^-MkQWj^a|_w*?Cfq4vW8vV zT?~RMYiQc2@Z*PxwKYSaxUN#Qm0!VVF=`1hsaUlArz+^Tu%^h>1(SDpczC3SEbtBv za$z9X>-vEqGqVNSA~enB=ii~!L64)NWTdn5FA-<^tadVcUjI<+JyygA+#O=odUDQ#Wu(cQJfQE|N& zH=w==%2Qy;-0>Xn7j){v_?0S2R4Xj<>{-dD_n8ZQ%{U{PP}B4rN8ulYAE~`AQ)7ffi_w^PHwN!DX)=aKTdB zT`Cm9!m=TUUZ^x^ZjM)t<$wD56N-7&c~;+OS4%wG2I=^_yd!P6Y2EcDQ4T4F^|Sm> z+Sj>>yu^z)Kq(UAzUxfR!GTxpXwPZ$L4ZO$0A$EjBTh3YU`PHsRThvfQ$XEN^alD! zy0Sl*Y^ZfyjZRFqW_UkT2x~LE@B3XtQmsOLeSyI&<qFg>d2Q{eY3c^ zNQ#5gZrmF3VKjp)DAqovbka#uOzT>WkoNG-VUl#PoEP;MR?~kirnh6`q*ISf8gKDO za0S7NKoNeTJOeohQqh6}w!a`pY=*{k-WiC)BuNRUgLk0E=pGzg3|>Y)QUS_^$k5QH zqD;l(sRS&*XN6K_XQrlJKfEqa2#3g6nPrggo&{L^7>*S6cI4~z;lmLGTQtl%d_n@K z{7S`uuG1h^10f$HD|63tnS}1!goMJ@ourR~Ur4mKy%;|$$brJx+c=KyDwU^tr@t;= z=eNI?P09x*R|%k}fe(yp|j1z{z`vc8=ZhxC>V1YW!-=; zei9=PAQM>xm2E#>KVoEOPZDzV2q+*CmgV?o2cLQTVf-ihV77Alin>?RmMX6YsNNcS zTYVb+GMUnqi5&U(jK(XPOLrGJiSSc;m0o%EaD$gI+NDeQ+y?kx$#^4AW_%ntv@yxr zqn?ATVzc6$T|qWtDlt8dPDe;jEw zk`-Nbi;&sZTHC?xMdAz`u_GuG!@pRD3JVtZ5tWj!Ua{BI2o>beazATwOw!Ww#b>*w zL7}msH9p_<3B|Czx}6B2zO?nNFI6$L+M@xwyjT zj;M?kby=bg5@mFZQrZ3n6&?&Lnr+NPTxcw465o_EROB^ui zfo8|G#<66!w)2tBy3mv$SfvtSNR=v|eyn#8Iv*48=@Tk!(p1MP+6dfCu+z0T+^O%Y z2eZUv@K%BLU51h=c_upRk2=Nr!-}Ph_4+bCZ5CxxGAKQ>*T#!d=FTx|*tzj2{I(Qz zst_DWGpVfmiJ_bhORsa!I|ZF~@vH-kfcyF>yyLt)ADUZW5XV9zOo{QS_91e=%` zEafr@c#Mdh&vHFdey5~8Aw_XKIY@Nm(OzgfmgmW2Z7Sdmm~Ul}qF|6}hvqbCbcmCX z5bj>1`pHMRyi&Et209;qyKUp-0{@be^BOEbm)AxJE?;(pHsA6_$FNu${fRsc^B0az z*JmZB2+YjQEJK)>nSbP`)5gT8gn@AUqEq0FK-^|_-bz>egfj@) zFeL0vf|qw1DaWByAUY1U>4g#_06Xa`KdwJ$c?V4%Q&lH-K4G=NaFXE{&|tZ{nxojA zoPb?a6l@g<(y7-mGNU|?6T~q!)ZUOmD~aNbaqxJ1NXL3tP%$B~qQu^UcHhY_ARxQT z#Ur2?i~jvc?#FHQ=;iFH18zJ9l@HZW@IJ5n7VPA}z7I+Xd)G$75jhq|T@Szk&_7u_ zKo2LbJlqcFvdHCV-HnZL9i9Cx4MH+J1*0Zu^G#K`dDY3DK%l`uq5bJ>K??vr%8+E< z*4Nn3R}WvnlpKSO{#aw3@W-a1YO&GyQg<(rfV03xNN)IqtBu8~n9n_{45j1K%lcQe zw6)FQTR}~Wf7oUNC+h8-YKN?5*dlou1?A>=vZFqKZh$RPd+bPCM}6E)l88h0Ex$Vf zA>kchS%F-8QTeL((qf5?*}M1bAKOaML41oNXY>S?(40Df>UB(f)-bU5HlI0qQ%keV z|I{nl{mN2WJT9$5;Px!RcaOq0x_^?i+=8LGPjyf^VOGbr;HK8UB!%- zKa-TCWM&R@aXGiK-M_!prVD1Uq~*5~FG|I8l@PyK+=oS}bWr@LoT2*3xmR{T%kSUUvq>jx_P3mV?vrVcr!nrj9;TID z7ykb2l0|>lw1}t8g*%=_(*EA|w3!WO<>_8GdKbiw+o#^RSQ505WM^x24md$+7YB4( zJG-g;9865#9iQHSJwkUV=Ru|2p^&N+nd;;^Zr~)?q0&55e&A;Fl_mLAZ-RKIy8e(H z>tKiSvzIR^paovfZkEI$S(#K6XU8X(^QQ}^r>6sh!GD17TS=!bUda{D(@Xv+X9bzTy-qpd?F7XRmS0%o6Zf z-C8DC{yA~8k1xxgggfp{Iv1!CzB*&@BF=X4@doi2 zotfo_sAYQ4KUSpeWQ_%qc2Tgq0wZZ)7IymAhAWO2BHK>(WKfW=$Pf`>lJZ{vwNYsg z)0F|A@dJv8Cx*s$c6HuN@ni}99bxd`1){WVExTGQRo0B2J!G$dl~}R(+6N%7fize} zs(3HXZ24ojf^II-W+M`Mq@e+Hw>|Xe-K;!b{*t|E1;MxN>bmvY0uxlw0sqjIAsRT( z4S{WBgokH#x*LOqg~e#hOBR~56txN(!O@G! zy2E;Yz|;HoOm(u%Vh7643A$L%>7G2$|H6*$=yY1ZmT=*7KKr-tS0bJ;JQqT6bd1 ze<@67W1{k=V75x->y=fI#x@{hLKg~8EEdfbSvZF379@!vV1KZncMH(Q@y4@ypIQMQ@odH3W{h2Rjig{IiMJm)L@VK3-C;X~(A zWuy4alZ1D}nc198{7>7hY4cqXSsNQArKL!{x%AaBm>l4`T+`m}*VcB+pN!{VNV8<~ z!sRwF(~G~S&$No59mvT0jq{WJWRa#4xz zbGjI#qLooV41T4Qi|c6!6DxBq%n*ib(y)k#Jo6_18(2NKw>s8CIuP!+fAlJ zqw7Ybqy}Rp*s&^=oVRZas;H2HNA^#t$tpO4rWZC;er`rV6%PN&)a7+;7MA=wyLM_V zcfq$Q&5--FeNYt~j5}xNVF$=IJ~n#G1*r|IfsQ+DskL<$k?P=W4GrT=*R=C-XE4OQUk z4mzF`=#Ii-xB3Zbq$F*xS8`DCd?|`EV(qXFVWsloGMjj1y+pD?r zIAt3smsx$t$Sp9rrI9^U-=0w= z<3B*baJwlvV6A6^EwZCxbW;e+%JxaS1g(K{hMhz#!3KTk3fQ|+QEIzkd8LClo zz?}4X5Ow~C3kUF7I^I6rv>c>O%3lpEurfg!AB84M_P%0)K@z&^uX2=vG#7&+OE2kE zahMW|pIwK`6^g$|Pe)t>*&XPtZ^IH^XLWRR1fT^S^M*PYnLvkt@97E}CKhJo4u+t z`;%yrH7Z?yW2#Qt^W0|If0Fjav=I5!=@A|0v6MVet+EcXP1VLL49ZnMWC5R(G?eA{MWvip7a99;PbTQ!#< z+!%CanSs^^^MTs7J9~RSM4J4;l0f)WJv$HWA_db`lvl!%;QG88Tw)FA(ZLo$t| z`VWY{)p=CKQv^qv4b)T(0m!hly2|qL_iI?CLlwF*rE`wE3zB++7l&8Ppb*pll|M0$ zovfly2bjww54=LbCn5+6j&?W2&@jvM8DLGnh0By?ZDUiy{*1%u%;w@OLFel$fO$8I z1MbmB%+9PSsiAVCcR;|ofB(X=;88 z3KFrg!H0{jZ&YcTn24z!K)iEU@IHH^e15Rr8}5M6T6wXD3-XoRq9UY8{m~I8IR&|n znzlIX@PIQuqp|-7T@QqU7d|fD*zRo!M#Q&PQuK ziL}2iyINdzHJ?BJwbGw}20|ik1_LNeX@Zgs=tW8)l}SazES+4cY8hxt9VAEVj8qm6 z5EQKF4x|NN2EVTRkCqJN@Dlqnkb(?4R=4I({?1_9H%A*o9W0#^zgk+n;nex@nx>$p zlr3HU+qdKEhhYsRcL=_~Nf6e@4DGfrI|~TJ*k4>#v0K&@7Jl-huQvg}l)2PC=$Yx^ zhyO}g_)QkC3;*>(E|j>9tV1eRQ<)PUHpNim}x72cq*q zD9UWO(0W)__O6VoQ~2&;hv}}?g`b_Yx)XvjTOzh&zBRPebXE-g@iH=m>PXqViG|hF zkwv+^y*)2~;SIftoEbk!cc5{(|QD^G|d?C_ehbrmFDHimSI+~L! zpFXuNE$KKoIOOE(H^V2RdU=)jf}tK1ppH-#315E`*pZcm@>8MK=Z^iUJW_(a`Z$d( z*Z%O8Y?=~m1I_Jn*g2D`+Ews3uvcb&MH_$$Um!@nkoPJM6;44UG*)Szth7sOtbO@1 zxGP9}!`6G2hTZQuUCEDo?AQ2FMrDQ~UEg<A>76K`=1a}7-pjfnu@X2brq&7PrDIZBz4zVE3oxZ)1K!|gpoIDO3ucC8a>)z^8; z)NY?Gs;cI>X=RA_1R$I=e~5l^L3qgmF$1|I*TL!OZci%%-f2kYL%`1x;>ye+d~x_OVDoP37a>Ga@DzLq5PC_2(Vx9dqizK@+~I&;M2fk7q&6CFF0LF0pt zSEe65z)zqb1ET#CI4A>xu2ix$^-aI?+O?k2d|C*TX690ZQg(NAbTpspy`b6NHiZT9 zH9A@Zj+LQ87K9K78(T1FjYo>~o8s*g)^9uz6~ZEXcxg&dP|$tuT@DWL9GEcEG6>&x zcjc)iT7Og>COMm2Tr9?Nmwrw}olK6(O`XhseEGSopkd(8`k&+pP6w+3E&x=(O|=B4 ztdJb7j21IMTVm&niHzuj0*pJ|P|!pi9mQ#O#0Z+3MKK2u&737fBOczmgN=uGQ?UG? zV{NoJ06ebZUOyU|E{|3UPOJTFjsoofK-1fut07LFKz(qS1>SKRbgya;e5lJL4WT`ZIrZ}64-NH8!!wWOOT-a4X$d92Fva7V^;@)dqZS1LDagpS3EPlAp{Y2b4LeopZX&l<3MnH{rb{k zZ76l9TXC}-_(Fa8>{>7%P_dbQ3Y^UI=U=!bT@w{D?3y(P=MS9V}>XjuC?by8701>VW@eTqgLt#^$OZfqSNc-x z09&|zeMnW!Rt^swtmDc<@sh5JH9LmEF?i|H0S>Y3fe;Pxd!Cm3Z?}cN2VTh`A>8~| z3$WA@er3txxeJmpO(A_KcsQ5tr2*~^e4s-@fmpc{cD!yKn$7KBWzTWI8U3^4OZ&aO z{bsP}8dz6U@+*Du+T=bu2aS~rJ@oV7wpx=A{B@znWwsOa>XHRac{?QOekZP%5|#Te z`xWyF$?|yh$jDow{zD@oxkQ_Yzt`}WSQPf6dHC-i{CQK_*DFi^?cFKDCvwUt|I%qQ zZ&-`-vscLBP|E#5UfWtw@t-&Ierq{Ffi^Jx!T;e{kPq<2|J~OyKXXel!OSE{2RsL^ z_U~2phg?|_b-%%Fo|oox|L^ZoE&;Os=S|!7U#YVG^Il=u2k2eM_Obu`>W%w zC~hE1^uMpcyW{{f`oH+&p6r!Nyz6vCtUq7znd=Q?$n`(P{`==%>R{p1oY{Bx4vvwm z33W7azGpFo@K8Gp8PGqbAW3&HxxMJ>YO*;H-8e8XA6NuOpkTD!!b7St z!T8tDKKvsB*cL58oCSuNxN`5erI&HSl{{VvSNzal!UUVEjg1|2(%l}f3XbL}f@a-Y zTTA}&@!0ZyL^7RYGv9W&`X1)Mj1zhk0*D>@5F*o=s9GCjb zvpWi0&M!dOhvrg;hSfEmjdpgG`%)W4w1|N7{fq zw-#))_NpR#DB-q-$VyDZWEFNH>TGNO#9kQ9vnCIz^;Qq+28o-Q6MG-G@83{~qrmuL8h=N!)7 zYp*ru{8e~OO@8z8Sb-O8+dm2|MOw|i0fk4z_w-Zg?1Ah-jR=#8mn||z8>_HhS-kk`gMs*^fi-z&^#@p4 z6q?gRb$DB@vxZkYB&q+s662)E0+Nxno|+7>)ik&yk zhBL*bsKtBkZ!exhBp5gOJ#X9O=DvI99l|U87pM8VFsFoJ*vp4YDfGF%Pxcvo=#wYf zMqA!HP&K~_&n>X1FWw-8arxYSCoQPnu^+W+7Tn}=zvIZb0?vq2fO$bDq zE>rS3)LV^H4Ha4hy{Qyx4m*~ze6tqW^_k56+wXb0Nz%QCF_|hVQQm)V`o7htBWVR< z5Yi(IjR4e1W8jLGjjgF@c=jq^Gmq1J!`Nt{F+eyD}C%=>(>&&ox$*=v>-;n z)BlZ^Psj0C`CBl%6H|30W>9;Gwp!B#KV*8t;dca~(rGPLL-8qXZqM0KNn;fR!?e3+ zZ=K;&&=(k9V6`eeQ#K}F{U~R#>mTdy6wek#*CdjpmO0oo6|Kzo6bz)S+?j z*LVKoiIkG%YJPS6 zXgPqbRQVF^xeI2-S_UIu>3|`&Z5FR`*CeEye>BY>0`ky&w_@rh zDX9&NUTH*qRMn}7EWocw+b>`Seh%JX`oRZTngv~LRm9|e!NCedA&Sa{4om%8eZy92 z4y;X?l}UH|Ul`Mog?fbIy(_EZE@{o2eBXz@6(DCDgfHDLM#YHl*{`9!-snO)8TcTt>_4FfJ>hAZ;9+c2oR8TSF8@Jrzd64>hGxgOew+EkNYjocDc-6oGRIme_R&DF|c`j+h z0SdwEFxx_#WrjfVFAOxwUw&}ZbTc;2uB+c%Jz6`nUhPBu)8WW5b_d3xH6=JC`SJV? zt1Zc`(Iq#?nvy;dz?BaIzsvPCuW>JoaO0bdl)835;*Gs=l$!eC61VwRXi`+->Zhe7 zCG~69C!ymP?qrsfqGe(Eq(CdSJ}FKu$nk6U7Fgt^$PO2dK;9XQM4_d1+1|!@yyoKM zH0=7*2-8@g+s`jAO6{$VHro+CAuWKEFwo3>iH!|_u)Xz9G@$lbe8>*|S%@?X+Gco8 z_5Y+Q1jSl8z|HRM2U}g%4({h;LE~EsE%*`)vz5azAH@Q~0-UUMqx?<{E#)vbotzJ@ zc^Gv{=r?;>drV!0b~@_2y)<4P*#u^<>O8079HyLJ7x6RJSFVdF2ZsE)gGE81**#c* zGbU7FGBOZ_g%YleJK?pfjBHIfcLoMZH>~2v>>XF$o>ctOwzaj5-1_qPb{q>hUUC%V zf{So0UpJ_>sM834e|-M(>+@cx-9Jg=MvYvwrG=`U=|+sM1&#H4nKnsD3hEHpdN4a| zdmFeWb%|QsFb8XtkT(VgJuvwRarGcnQc}&< ztQ+Dqb2c2}@b?dh1R4dgd;_>C_v9j;NtUQky%$k<*;51YxraLoTM`QZly0__t%2pn8wfT4 zf=8-C-aXPi(}J7*sc*oZ1oomjFcJae1*2WGnp-q2sX&Pe3b}FtZb5y9I6hp^O9NH$ z9UZ9X9l9G=S{NUym)p}p;r^$r#14|p`VD3@bk>*|Y9QbAvVfiU{QNx7Rtr>%ECoT) z_Wgu{nE2zHH#8fXr(4xlSy2YZe2!z3Q_dL0rFG-A z)#LF3@YOyg=jE$6iup zWeW76a4r~bN3fdj?acH&sPC8cJ1+ld|Fx+?nUZw-9 zOVY~r_QCgfr{i3_fy{NC>RPp~urS2cq_U$1)+Z@=T|+w7t&wk0d3Z=pd~%%U=s9^W zaxX}sT2lyGtQW((E82nne;PUyk+HHN-zu|wbUl1pnpRQv?f^A|wP(0D!qQpj-d^j+ zhuGYSYA;^LW%acFBCA1U4H7eIO8{lBKU;Su5nmXwLqiz0aKpYOCL-BH7+sdtp`E26 z6MB^e{$(yUwilD%p2Ch!0JLUZLD%^fW)qYUlE-yTL7^Nh3t^Jq9+IYXfI(AV7DB~+ zxDaKBM=lg|f_;?$Tq%PS#lh7lUycvX8^q}3(+`%bR6_nKDaOI&R4Fl^PRUuPz3_SL zxIQ%p2g8M|8ywUyjs#Ms&HB2&NKH-TNv~S@9_9#MtIb~paLhy9pYL$OnQZ9pyaS=- zbA_r(IkK|7)!sO@_tC}lH?F{r-vu6cTqh^oDWFK5TOECBnk&feDc}=GL35k_V~uza z+iIk7{?<@|ReQmJIx=7v0+Y9N6^$VdGH%P3afry~W&3O~Tx8JyGpX(PbM_v3W_49= zVlWSpIqA6VT66J4AfK)HRm=%^ByM%MZ5TJ}_ZXdv0Ho4r5~ETB#~B zp9IIrhbp|tLgI%!?M)&E9?#7?XRz_Rz_TFMkjrAM<&SZ^A?#Qbf{y+f{WHGAWPZYO+=l9KKR zbtKwX@%snc;ysUp{YaQ>xmXCQJdXCWemS)zre^PjhbBM`y$_}DCS;&PU!|fGW7-UT zx|ly%;)#{MKG3BYBec}lA-kY6(*>vP;$k6N10-NL9dR9QF9mrpV4poc0UGVaU&(k& zABrj3zS4+B@*MDL>y+I%dJ8JRw+aUJ8^0`>lQV zJ~ZU9cV?B5aGLdg3zK9lb#n!hRP9`zkWuGvmt&Sa{y_3D9}A)@N!M$l3f3Lz zd41KPsJTy1|B;wcv!i=hi+`mhk{v+nWSIpp(NN4#Wps6R-JHaxUSD-v12#QTLsf#s z%*1QRmWCiKY!IY-EAO?f6 zw{|pI^kasE=sU5`4YH-`q?xN)AglRpSv0vHG1H$iUON^RmIu9_Fb)UTuZ8=CfrpQ0{UB4L zMeE0FE{h?o4nX&yxC=rSiKE5P1ei3^iU-_bX3ps`WPzfnt||0*r(X|V#bPq`1O~g= zgqaT)ikY=aVM|H22JB{KV~^f|odq^BP=%60fK058j--slt%L}>`N!FMRdSY=OzlE@ zF}u~AKx+g_Hpy`29~;E66eey{LurJS!$n)oIaP`2uxs@MxNdvQcLTAG1uyQWWEzm$bXcG#2_uV>@r?aqa zA^e2-U|Lck^P4)OBhJ8vEZ9OF?5KeS!K?8?3k(~r7>j%DrIq8)ZS9-Is?thrpFM-5 zO2?$_EGq;o$bjTBH7NPT#>UYI%;GY2^Dg4}q4?YSUvc=8@8Kqj`F}-?R|3wRCZT5+ z-x5^^Y?b|`oGNEzvTbe#ZYY40zMOh@8Iio$*=@0{WV}t^Ix#fdw>YpZEiSd){3A*H zP}_GckP?@YE3@Uy)alQ)%DC1R{ITu>YM5Nq;mjSZE)BY47G$_A)N@Yot$79f+l5ae z<{1=P4rUoDkCzEy@|-2R1>`C7p&xO~!bc(PLI=JGu^Xcs5K$-0{Ic%nG1KF|Y~4nZ zJfYd{Nb2?GZwJVHcGKxK!8ehlUeDm9Je?+9J)P*DQbLyUk&6i{(CfEmzT)BT0htPk)Go#oBmqz`66ft;*)CTF;R zKcnBG9>`pr?e|SHu|Vf2S%&X>{}kwY&<0PMM(NAT&0)-Q10M*1qufU8a3fopJ`xnV zX=!PQYyu2gJ96}dSB?qML0^L75F=Iah0`u`B`VO&$_fDZ45t2`6B}Lq{m3k3#5YJh zNii7cfS{9ySa~l;Qoq9;NlDpBklI4G6dokB|Jvz_LqvRR?8&b!!}%Zj-;H0cZ+&|T z`3u*sU;hn~UYJ>GX>QpU4iDWW()o!m}TC z=&O8XrED)72nsD3hx(gp0AAay2L;b>Kj!Q9s}z3W4-q3qqD=yzaPb18whh|5h`nxk zK&+=%SFeUxqQYRjh~)Tu%h9d|Nl_xyhm@4ECvN?=u))XjJHGVEVFtd<@@Sq9(A+2H z=Tl`9QB|JDl`k#;R|$}YJcNKM(3BVhn&>2-l=}dYeF+V%6W%jTAG50O1`~11KHL_aGm7kVQPTHv5t(y0N3lfZW9*euMGoqu{A~j3uQItPtQ$K-wbd7GMVv;7y$)7Ef6E$JW9$ZK;>a9j z`h%J9cvuei;jnW+9VcuJ3%u;ORe5q~29z;r$eKhzb&Fw?xWU7PVJT1?Z zuTSA1ro%v!`xG44h71ul#Hkm0zHzg#JO>|*J9q9_&omJMi`5~U@O3|C?G)+#z!{Hy zu59h2`OHwr?oM|=cgFBDIq3$M9Q(y{z=2d@WtJj?awOqbge;lxp2q`F(lS!KJX>)Ya(=-cA6`%kCPXDB~we<)52fX+uQ)G?@ zKMOU??d>@PuW;tN8Xnq@F+Wq9LRpnp3kP+aDXyeC-ZjLLkj8o>A4$#fqxAH*a`35l z7n+WI{Oi=w!Gj#)J(Sx<_T3kWWZrr?|PXBmKM+yxc88ZD?!10V$@4PfdHko0W;J4}PshUQYo8>ly$bo^0}_+! z&d%J12A2y*ye=ctx|(2|H4Db|{-pfG?Utj?Cjs0|`4}jD21@Mi143U7&dnO}9)Ay8 z-^rS03Kn-z0A3rava_|7kdWxm^-CIzPePPAD-NII!o2CZ)!Z28W@cF7Bop(ekc36u z`HCYVBH~q*)y~dNZmM3qnOcr%w_o6gPRS~PCX<&hYqhMZ0?K@_fnd>bQ8d6mfQAu| zfq?;dJPz4=(j?5_H~Q^lq@(F0DZ5cese@UFt1G;pKv#`@^%7!E42;uP!q{M%08E`_EScS$X}(EL zj(EO8dny4NJTMP!V0Y^3?vjvbIK^`SGto6ht^6en@SEAM^psxkrL&ex?=`*t<@1l9 zKfC0bfj`N1`z?c7c1R7e@IWlT)9d4D1;p;jBC8#nkbdc%)jd_c-!eXGf>B9wT~ zx*P-!fD(60E-7p~a3&Wz5EjP?zewF2Yn3;!gD`M2F3ak-u+!`XUehRf>h_E=h(qdg za9kk3<*<E_4X_)ot^dF(YS5W%QD{~Xbce>Z3Jn#xfK zx25{{*B=j{D{!F(kp&jUQ`4qY<@DPHll}qz9|gXqDbpia-$2|)s-mluydprj{%ApU zka}ef6f>PwBmxYrn1=yAI_JP)e*$Gy+4x8D3y;I*9jwQDrZL3I>+0k;hMZ;;+Jb}+ z&VvdQ+2Md_lb>IN1}RPKu^rAz#_y^N44$X4d2inAJG&vL7L=Tf4#Gwk1kF)kBDFd4 zrx92plPl9TV5jN~`;}PW%>=^QOk8|3Pu-}cigJNhsI*>FU=c7zak@QU2PrP;uu&@v z)~9yV^k!-z*%9?d`J?swz>2G^a5EDoA;D$TzUbj`a(lewc(wjELJx+!<73!bV}1qqiat!+VI&LH)z^89Dt#y)=jC)iAQZ-2*%1bxB3cW(ukXk& z^PL2q86a7t5N2SIHhvxcdrlQdSwJyf*xoR`9=#}U<0srCx)c2{n$)JI(Y#fiu&XWTJeW*kuh*NV_sIIKq!TcLZfLN{=VuX!1 zC_^bl4*ao2$YV0BOwzjDwV?Klib`i^k&4bkPJmW;)hfiPrGG z3sGQa6m4K;*8J13IiJ%Ihf9``8Bj<#Ky5aro)Wjj%b!+yfS9?P^mT%^?iB$eGT4?v zCn4YwM*9?+MSXJY92~Vje|=>MzIF{5p9It-h^e5-z}GWS?DZ|6nBW@B?Nt<$C|syY z#KXn?k)QAWLR^VyKNd*~S=oDhwhG!YQaQifgN{OZUgqyecXCBWy41i(O zXD~4UU5!NZ*>j2Tsk$C3oL~;p6ryVAe0`N!ddX%LEm%=L@Y8}E03-m4l9asVH0mR^^Kv9;Iq>s zRdsph(^+)kv+^V{QLRdsd$DBRQMU5a`oOS^IM_hr-sB;Gy9L9|{q4MV-v=G`_vzU_ zukJ-r!1A5PZLyC3kVeNW7x@;jJ|v~LwKYpdHXf!eKm`6hq5I`Lt*9vcUw*-7&7ont z%^o_K!1@4<3+y}dZLNV$xI8A*IsGfa3pt8`=ZcGq3uc`(4>^>heW2suihmow#_cum z(-7xgfhp@ss2V~r1_(wbg6B;rgIbs?zmyrMCjeK0rT#nLq?^Zno&ccIM;MG{Z+hr% z!qx$auJgpL8(==5uBByQZtf4jUU1Rr;NDrt<2XUN?NO>Z>nU^hV#6+{L(lD7+v&2bGn~vuh>9=A-o=*-cH|{=teC! zVJU*gw%b`+rXlhg@Nr=n-I*ojsK!U0!)e67;#0i+p zL(rbajAE85L;DSY*g)_#0rxX^7*Wo-baTTx<1??_!wX7$9hvYna<9TvOSJev6 zrpTo@Y6@lL;xcOLNrOUuel$ZvC%$Ay#zjRCFSz%_(ia4#Y~UkHK|%3AIh7!>a{n!> zo~Pt;jn5!oSka`;{@%=R2b5n(m;knH^iTJ}pA;voIzY(50F}ZCnc{14Ss6i(OIj#< zx>|;d+CXXb)UQ`5gppQqD^}yz^!8+=qaxG%dv7o(M6|8l|6@v}abVGT8?xNndaSDI z=4vl<9Tx=eql2Kt`O0>~W_Nio-(ond+qivmt}6-Vmtv%0m($)b#T%d>sHEQ@fdr^O z%PshJb7TVe5t>=|WD;p)5*56^Bl8B90Ph(FMYXqA@Gk2E!5JCUPjoyJsHix&Pyg|0 z73Ru!jF;`7^=rr!-7lPZn);>$YzPO7&CH>;g(bxgW(4%~Ib;&6g>PX==*$2vo`C4J zzfL>{Y_{EdhunIwa&%&sqXz`!8l~>Mb0^0SH1i)Q-IG@>ba8f`fK1$@U|MHq7k!A$ zhAxT?FMDM$&qp;&i;#>;E<#MSWOHVx@IP~MeKNc)I~(Vy_;~6s_hg;}JbT{9`)9)- zGDEcc({SyU!_B7JjcL-II+7SZyNhmaZdaGbbHdRdXPPBlcm3fKO_idAL4^V`dpa~3 zHFf)^YAK?D5sdscm^!l@+ zxk*pzNO&Ap{f99pEfKt5S|Q?1d}y&8+;b=V6cYF66N7l%|6IyG+EW5IyNh@fsob3h zOKb`mgFie4X~hEnbcHe?gL-{YpG}^Xq`Mh^cat2jFnX(G-1fr*eHHwBYxKyuH(R;K zAK+vkZ%+pS4JbO1iYim1C~&4ZjBckr%M}BE&C`=w?NWu)ax#ex{(ZH%2IzrO5B{}^ zJt{B`Flgc)XR+&hc$Qh`n^Bf#@#?U+l%_lw+%!9NC$s8LJ&}tOlFb0|F^osS0)av% z8r$r+_Hq+@lGfhp_R_fC!SPh>26LWE_dOT}y&rya?wz+!o=Y<^xIum}F1>KZo{v(v zC9>wnWX*=4!$;WYjNEp5{`s6nvgn`f?A+Vn^^9RRZdXiKrt?n1S@wDVUf;qZ3-`m; z?&de`65DslT)}qmfJ_eQug{_mk&M3!9 z2{<_NLcT#e1nlxGE=WRWZ#UbL0NHBDMYshz0`Aq`%taI5%vC4RhbLR|aR1x&qPguB znuz#3_GzGLxX%}lXXvSh@i^c@dj1O3=}FT82IyhsN6PR0LfiCEw_VY_Y5fGJTgJNl zt!3YxqTgm>xD2pvZIJdHa|ANG-gtg||FGhl{m`A;Ou7k^PO1VP$xWdGPcU|Zx8Hht z96qRs!bl_Z2Z+HcdoMXcF83BV@*3{lz>22>Y;8T0jo>txvxwN52E2?c5 zX}?4K4+7xvaHCrgfyf`GgKmV{3ccCi|G4}w!SK)jvJ-=S{+FFd^}p=I|Cbj#8@o{Q z*F)Cbb|pJE_kA7?jv&*QHwg&|g=}q`mP{|vY+n8k57IfMH%$o?!u+!ioIjHWv8g9| zO6+viL@x!)OZ;V|BEM@b|4RRRoJhzXx^U%2gS{I>0uJOkF{@?kLbj85&fHMH0h$dI zgT_H+{m=4W$%7P=vIb4%MCkEXWlzpl`ji4Z!_W?|}SCE1aKw*_#l9mu(U zfO8}TCB^<>Mvgkny9d;=Gru3053oQD8zj23h!}RS8MmGP1!|gj)WQ39@2g3cv3xfk zJbRsk4(x3fzIX2;v%EZ?)516R{t{^t$F-rIt`laRQpf{C&48wf!=%TTs5!hUA?%t+ zIm3T$$W*KmNT6Y1-sE`20s=4B;jtVol2|!(SZg%!g=v0`Q}2oT%*R+dr?uxAfNbx~ z#O$m$s0gsAc>zOdxc1h|tJAc=d@TP17>gJ`7&km}{F`z%_|q^=G3koW=qTQp-X)qI z7o9WzS}s!#qm>@f<1k-cg_dQ#T}Y{tS+|@AMrgg#WU$P2$)th zSTI2v%uE@$D>a2NW`t+M<^z;`x_AdVy2x1)P|U9)SxbgZ49(EjFAwG+_Sr)PX6Vm% zrGJj-rF4_JYm4}zgh{99|GC_!^d4vQvOyq7GHQf~t8IC9*Rn;VwuH&3sNFu=Y-!XyI|Z+6)-k0sSo$0cvsBq@r$jYiwkfxnU83K_jO zNgFdt2u>X~Z~W`&+Q_kiT@Mm3z|!R6EkMk!)p&Qp45lYk`SkdUB;oz*Ac_e?LY!D_ zj-5R*2gcdn@2q>ezla5p8%OOzq|77JXL1?6MkQ56;Ut}VtCQ3>8`SiSwMXFT9{)zK zoteL#(fZV3k+b&nII>@k_MhMJAhdk%gJCt0jafpr|Lv$lquYJo;1SK{<~-1-bIHU*5m2jO}9ILzw+1xc<&Oaq_=S^pEXK<5MOx6P%T_`i;ftp$iT=Q z<8?P^O2tJ>5_yg5zh83~e)~V^S7kq|m!&gYXySi7N%mYG!WNSo6a)rE#>5RdzqR{a zH!5mZGpa|fNdW__IYaQ1h11@ydOThu&p1(a&hvhU1rw8UmL_NamaG+o$KsOmZ3l#H zFkQZU)o7?Etya)A#Mr@^d`^%7_OiUW_Bj(uF3W+}0Df+H9xj9~#bIKQ5Qqqb@@%q1jhYjuJ z%Y#*1w#~ylYZ}Pz1tb_3O&>4>2OT)ShAE0aA2heO z2Z4KS<;LNkyQ0HW7S3O)#7h#4b9A90qig;L=Xt71^sN0F7N97AVj}&1bfJ0U_5~qU z*5F!!s~u@r*H7P|Fy8yopX_mDmVbR?i0D)7nz>WoT_KKtg^0ek;TkQE+bnJz6_rdh zUnsOqbS6?E52~r9!>8bxz91~@Y3EoE))NzKroGv%tql?&)8(C-Ou+4>*GqW&Sq$1w zIN99gW2bDNJqvWzx!~j7m8*1r7PIc9Cl$xl>d{+SjRa{)mUfJudsXFMNo=LKsY`zR*(vt&4 zinW8CsND%)N_$*ya|#%7#H{b!g*6C#9xx66Zob9m_^^hB8%F(>Vq%EW1`Euezvovs zdly$OtK$$ql&H4Up&;yeJib&ZGHEFZ?9Ru;68g$g>w9A`<&`yLiA<$7Ib72347~n#S&wovxlt6~EXrN1K^N zmB6DzHjs@%Pm0GheXy}QQV|VJ5ss&)yRaPy)?;r!{Wu?+*W#^fRD=tM0+Vi~zsF3| z#eQ12_1+PjZiR|fE#Ad)F&rO+F~?s%e7QHdu+n+~g-Vu<$8;TEx$)q2Ml`u_Yjldc zF&whXymlai7Juc;lWl3)Bp60XWMRJVHZCOc`}aVJ83_@+YR@nx{b-aR$JMjYvfCSa zF5}X1Zl&ZOw!P`*p*#0bLAIhWTCm}_e%))<*O6*7U7q%j?Ycqj&ZF=k;9#>ppLirt zULL{g#$|c5+gYqHiW$qhFFFLacAr0QI;OT24A zFS2h-1%0@^pajgVfUH;@?~~<~6=;@NQyFo2*Sf2Y0iFqm2bowOA!8m!n7z&7 zDczk%Uxc<-d;O?J%OI|jP|Ook^4I}Oy}4w*q^Y(nOVpVEtYClt= z>dH`y-jCOiKTJqWW@;_CS>y52mwL9XZmccPgjt)p9g-9}lP$Cm7!*=!7siX2VH6U> z=dk!vB117vz4+C&J?fFUGW*Bn;M>#%lM9esN$dc#uFR3qFD5o`bb2RGzh>X^&>p^H z6AWh}Pn(&W3X%S*eDQ!3M&7U->ELGk^V)DOdwQ4&pLP~e@yggrBQh`1IF=-XBjqi9j;@#x=WGEeeorlqZ819NgUdP=j3|wGOa=*h$`vy^_gE=M}zAV zjOByli6fglOvtpP6Ec6nQKFS3QQU6okK`5OX?&r-wZ+u9C`LJ29zhQ*E!*C2&0WU5 z)L_e$WSnzzij0CR9oMhI^Mo%;GrwaPQ#ao!BiUbOFfxz}Od5XioiWE$tgZTbg#m5! z$tQyldJq3-wXfPk51yqk`)%EMyt637mLTdAnMQ|&xU!p--jXMBb2Fz`y+cPQX(g1o zzHW_${NLeN1qG$NE7&4I4|y#rJ6s;V5a8JL_rm9{mwKLfkKs7GyO*;a_te*4#K!i) z&G4Rm`R4uh3K0>}Q)sV3+uOU|K7|d7eY78pAuLDB*um+k@~q-q=+@3o5^S2_ z+u{wzQwj+p7aWZY3|lh;!DilHDwJLUDies(ut`-o2awfRUJ=-|)Labz63S-S%;vDD zoUWD=7@W%rF-Rj-C}GjkZNXn4?uEN8ligblp9f!~!uYYXvvc8WE_hpl)_i`(hLwe- ze=#DK4IU`S|ukv6nLzqvAOX9#*mv9@*ciEw6SYNs}NGnb9)G83?Iy1^&v2 zBr^YbTO~ZEt6N-FW(Qn~hjZ85gU5E$=mK(G`lJH==nlshyNCs%ez+n?0q<(m&m9gGy~ z*T}fVnigmtGigu!KEMITeUk3{@qdU)H^y(DDRp0ju{;m_ipcC(-pUH3$_<-_&BdFa zT?*hlX#HYeBiy~T{O6s*5KE15eH#enZ641WmTLdYL7qCkazWp)5Jb z$8H`kq_}gLt9#oooVyKAV5+Qbu2Y+I_QtZVTjVH1N$V#zxF|mGEfMUYHJTfZM&IvW z+9+I2>^E$9L9CLlS~ofxYn389{bj6T#}y6JV!u8{t*-Bqgqj5=H7y!>Fk~P&IofGf z{lw(KTs3zfOl@n@a1uwjkTW@V#tHTW)lBv3m=Zgnz|aF9v58vy=d|nz)tSE%dJnf5 zJ9Be$Z;tM&Sa0w;+vLsDo!BAgcn%45klS+uBB3-3%p*?%h9rdn>I2d&E!f4%hOP zT!rVlxIZ{TrsaxP{?dd)rGFWI;;V)7SyqZHZ9mF3p!xH6uOR-FS^4{qmZU}x89#B zE0ZmHa9#BE6(R=uicj>anG%0+D)MwwsQNj{5NWnll4953@UZdHP+4+kN0ONufPNuZ zGBsiWsoEuM(U?O9EeDTLHXxaG!wrWn;h}cEFHnZpA4FI5Z#H{uBNJ9Ez-t0sUD;mz zkqAqP)>Fz-HF){*9k5!#0+R<4L!nkS<>9+Nv1VmWO4P;Zuh?0C5oS-oJi)42-BV-z zb3jT(ECwJGg77O<9(Z@B$aQ8oSy?9Ip;|w1Z@8ULt2m7l=GU9;!x5zIHiIk*NYDKS zCN@Yy`^I!Vcr%1gAHv)Z6&dRhTAuwD2B%VlVHI+;0IFg?5f{(1u0HFj_wyZ;fC^Qf zC%9)yuhEK6*=)ZGbS3>$xYT)fa8}9t`n{}m&y zRNCGZKG~<0hnVA$BpkljtFdz8kj#GH!y^*nT)y0s`~K+7Ss7>%z+QNRhn!ikU9W8z zqzo`GqSHyn1+Cwc?|2tZ%%;V}JT@-C%SxQqs0e}i2n)yA&CPhp`P-U!ccunAY(c(B zNq0>N37K@tUs-F(L<_;QCU0DQd;r~zKa}LtBZGM@vFzvxKB##rZwf|{j-%wSNlQZk zS<{!Lg*S$(DcxDd99h9>9~hm%0C1Mk&QO6&6w4c0@j$G!m4(^adNnaK9TRfY|fu=4QVLZ2X&oMo1)t z^4nzZk+mFCoLIT=nJsoWlI0J#C*ivyrPlCpG=R93`E$iIW3_7vmWY=YjX&Q5%tnEp*&gJ_{Dszln5GUuRX9`HEx)w z2Ajz6U((?NbF<##?{SU=taJ+(!J-;*Rq?q>T@R-RAVxo49N2p8?QLxtbiKPQ6D1G{ zs3b8jKR9q5<1#Pt7h0t#OxGV*7zd3Jm=$Qs0#X-@((q)R&D&J7V^LxHJ-ztB1<^&bsZ1($IR;*WUi4<5^}_*2cPo zj^R#35jU7S@h`c*7@ z;}&Dx*7qlATVz{*0A@isE`N(|vb7ESK5q9{eNo31h&Q*L0c;G0(qfIs+_Ic>a|~wD zCDN`P;MicfPBayN@6*@bZ`}*UDB-B@6m2xf*!EAzG1Xrm3}2@=EsyVy`HG*8O#W=X zm`SgE>u^DdBSrp9mxdB-|HF5y#Q#zF>wp%1Lu_7A(f7*sefo}dqVsjbcDpU4q+|5& z_T@i~(;~IQr46P}H2-b5@&6m71@Ha;9S{5a;{Qfc;45wN1NlNcwyZPN#sEw1Antk9 zaHV#mmg|4}g9O9HZR-ARqQrD@-;VWHd@?mhiuS=~$>*Z~c$+}Y)bPY6<9Z0A+Erlc zM-{x1gn&=WY&YH?<3w<#fxL#5lQYr0#P&uJeeksHOW%xt^zwf%EAy+~WX6>tr=Fv> z=5DY1@^M(!#}VAET7};+iz43Jk`{$Uyn25&w(-z$lP~%gz294cUO+UI9Pt#$YE=+|Q|o1Wc5KsnK@13tiDiZN zZ=sKHXf}PmGK7~K3|D zw~Aoim|pbly~ESLi%x*uG@vY+3+2G8aBi~HTV-QqEPGk!%W z*cQVMUv<5_!M!ZuGXC_MV43swIt^^hGu;U_>LthWmfBTvG^{y5;LcC@L7@Pxj-tL z6!>98YHy}yu0Oour%v2|7Grrg%w*{lYd>!i(Ld`erBL(AelScwr2I{Jp({oh71;5K zAd1UO&QCRKV^g51X22)kVm!|C+{N7E_Hp(TfTOVr!M{@l1L88cViII3I?Pb7v=B#!t*F;6z!di$nkY^rQM_0&p>6_!{f{-XNQhe<9$%Ln2 zG;ohH)R^vX_Q_%a-q!~F5nk5;O00qpQEfV<3O`@cRS3w+%BE>%@uABFE?1I0S?|3? z#$hUhhmLwOR{9i}Uc9p_jUT4b+q-Uu+jLO9G#x8JDFy>0sEqEjuwca-=vt+d!amth z+Y1W)^I3{xPG7FPZ)q)Y*h=2yovl8H1;V)P&3v#2 zZfNi&&eGg^>=*XPR9+Am4=t@Y35sdXkRKc7AT1;FvZj<1*fLG)!HLD5vNd6?sB5SD z8)lSw1XHc)tIy6Y+0LjJ84f(g&5e;I_*Y%xr=+Dcmlp{ewMI>186QiZ%09>j~ z(%uXe_`+b8g!cRY5VA4-z#f%Te#+SY`J?Z{t$WU<-SWNwAccsBR{J-w{ zDJf|9>p-029T5H8NcHtnKgY7HR`AACex1S%g}H3|)ge3s1J1p~H5>NZXJ1ne7j;$` zGY>f}zf;Yq+bhP$0&z_(xYWgz+SATA8Sa*?Bx*WfLlEUtI6b1)S=`G7$A>nq(Ac&$ zPd|8b=1c?;%e1FG$EfS}l-DdHugwT{=oR?al8~l@S{wVI^5Hso{cTQo?z**~L5hj2 zX1+)kydI(J%4_G zPRjb~e;rgE1#a>^rUqBbsQ=h#YybTee0VSl&4>2IHo07BOFo{4fHR9NJDcJ`drQm1 zoQ#k)B4*u~&6jevI(xz86d<;~VzJ zMY2@w0Ie3tssY<_cvFKhdEp8U*^^QSfL*3x7|6?nl=lGf-9{hHap#l@p#y-ammoUs zO!?=4?l0Um#>rO88J`DHXaWM-2j)N@%rkD^?&?XMYyj5EnN*ORgfr=M4X>)hAG#|u zV3?$zkT95D1Eh?D9|qzu$w*bty*&<6Vn`l1C{|;>Rp4g~tz!G<&p$ofPgTGx&lr^2 zF{r0lNL-Hj$Sdc5jZmrga(k;e2asU#L`q6ZSB+L2Y~1r4+H4mA!nP{+FINSsiojYx zG)#biW2%|8n`ENvPBr%~F>%^#E|^4jx5cG*XJLN60d}o%XThIG$3U@y<##(r62H_v z+o*Ix^C`fgW2KQavW<#&KLpC@)c1FGvWmWD^5|$|{eq>dikMm3&0P%+4vrCU`OIrK zi`+@ju$x*_f%~g*dL~iYVRpEb+$$ZaoO%N4Ir;L7)(nHCk`#`Npqgw zDP|w&yAfhFHhOx8yG!9&Y`6*;juwuqW6)650GM1E&#S~71Q6Fcx+`fP`=V`id(e1H zY;JzOa-sbH4e`u2kLPsb0uF--OkoVr0ZOj-sdn~HEw?H89lFTbVg?Da0Cr{F@0MQ} z$|A44FMr);iMY*=;jb@QaP3|V%rb%Ny@a50xC^(z4e>$Ao<$x3%s)Jb?5I?Br40X1nGUabS5SZ?v#E1CzmX zYTVrL2-+PkYj`d0YXht@Ft;crp?=fz%o(^G(rYmY8xLAR`gp$^biV;MuP9x#=L6fM zX1Fxj=PztT=dlA>3=7w+ea=PblsS(kTcfud9<4#US!=i`fQ)O8j-={URq9ef6RX

0+Nnk`%j`uxE2I(YvOcyoID3zV#^ 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

  • 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%0DfcR})g_wG72+Eyvn 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 G#s2}i^b7R> literal 0 HcmV?d00001 diff --git a/.github/workflows/close-master-prs.yml b/.github/workflows/close-master-prs.yml index c610258..d0edfda 100644 --- a/.github/workflows/close-master-prs.yml +++ b/.github/workflows/close-master-prs.yml @@ -28,7 +28,12 @@ jobs: GH_REPO: ${{ github.repository }} PR_NUM: ${{ github.event.pull_request.number }} COMMENT: > - This PR is automatically closed because application submission - PRs must be made against the new-pr branch. If this is done - in error, please comment. - ![PR Image](https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/images/pr_image.png) + This PR is automatically closed because application + submission pull requests must be made against the new-pr + branch. Please choose the base repository as + "flathub/flathub" and the base as "new-pr" in the + "Comparing changes" screen when making the pull request. + The image below shows this. If this was closed in + error, please comment. + ![Image showing new-pr target branch in light mode](https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/images/pr_image_light.png#gh-light-mode-only) + ![Image showing new-pr target branch in dark mode](https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/images/pr_image_dark.png#gh-dark-mode-only) From b786968cb35ff7f8524310f1b87512b08ac47810 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 30 Mar 2025 07:44:04 +0530 Subject: [PATCH 202/319] lock-prs: Run hourly --- .github/workflows/lock-prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index feba59f..927d921 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -2,7 +2,7 @@ name: "Lock closed PRs" on: schedule: - - cron: "0 */6 * * *" + - cron: "0 * * * *" workflow_dispatch: jobs: From 245f9f053b4e8676145004af0252177e4dd05858 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 5 Apr 2025 12:34:13 +0530 Subject: [PATCH 203/319] Run label workflow only on open event and check for default title otherwise it relabels when a label is removed --- .github/workflows/tag-quality-mod-issues.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/tag-quality-mod-issues.yml b/.github/workflows/tag-quality-mod-issues.yml index 78d7f75..8e6e49a 100644 --- a/.github/workflows/tag-quality-mod-issues.yml +++ b/.github/workflows/tag-quality-mod-issues.yml @@ -11,7 +11,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Add quality-guidelines label + if: github.event.action == 'opened' run: | + if [[ "$ISSUE_TITLE" == "Quality guideline problems for " ]]; then + echo "Default title, likely invalid issue. Skipping labelling" + exit 0 + fi + has_label=$(gh issue view "$ISSUE_NUM" --json labels -q '.labels | any(.name == "quality-guidelines")') if [[ "$has_label" != "true" ]]; then gh issue edit "$ISSUE_NUM" --add-label "quality-guidelines" @@ -20,6 +26,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} GH_REPO: ${{ github.repository }} ISSUE_NUM: ${{ github.event.issue.number }} + ISSUE_TITLE: ${{ github.event.issue.title }} tag: runs-on: ubuntu-latest From 3100585b191e47c80c27ef51b7f79ff527acb68c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 16 Apr 2025 10:48:38 +0530 Subject: [PATCH 204/319] ci: Decrease frequency of some workflows --- .github/workflows/external-data-checker.yml | 2 +- .github/workflows/lock-prs.yml | 2 +- .github/workflows/stale.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index 83209d0..e7512e6 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -1,7 +1,7 @@ name: 'Check if external data changed across Flathub org' on: schedule: - - cron: '0 * * * *' + - cron: '0 */4 * * *' workflow_dispatch: diff --git a/.github/workflows/lock-prs.yml b/.github/workflows/lock-prs.yml index 927d921..a0e784c 100644 --- a/.github/workflows/lock-prs.yml +++ b/.github/workflows/lock-prs.yml @@ -2,7 +2,7 @@ name: "Lock closed PRs" on: schedule: - - cron: "0 * * * *" + - cron: "0 */12 * * *" workflow_dispatch: jobs: diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 176d118..5362588 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: "Close stale PR" on: schedule: - - cron: "0 0 * * *" + - cron: "0 0 1 * *" workflow_dispatch: jobs: From 793e9a4b6f811fc98c2047dff6f6731f3d4afa7f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 16 Apr 2025 10:50:55 +0530 Subject: [PATCH 205/319] ci: Trigger only on python file changes --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3696ac6..4064e51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,12 @@ name: CI on: push: branches: master + paths: + - '**.py' pull_request: branches: master + paths: + - '**.py' workflow_dispatch: jobs: From 6fc8b2c1bdafcb1c242e386b2860cc547eec4c90 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 22 Apr 2025 22:46:40 +0530 Subject: [PATCH 206/319] x-checker: Don't process untouched repos (Take 2) --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 7ec5b41..dc4bfa8 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -12,6 +12,7 @@ mkdir flathub cd flathub || exit gh repo list flathub --visibility public -L 8000 --json url --json isArchived --jq '.[] | select(.isArchived == false)|.url' | parallel "git clone --depth 1 {}" +curl -s https://raw.githubusercontent.com/bbhtt/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do printf "Removing %s\n" "$folder"; rm -rf "$folder" || true; done mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do From dc98d530ee569f54bbcc42278b97dd7fcfa69a25 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 22 Apr 2025 23:22:19 +0530 Subject: [PATCH 207/319] Add curl to x-checker action --- .github/actions/flatpak-external-data-checker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/Dockerfile b/.github/actions/flatpak-external-data-checker/Dockerfile index f16c226..8b63319 100644 --- a/.github/actions/flatpak-external-data-checker/Dockerfile +++ b/.github/actions/flatpak-external-data-checker/Dockerfile @@ -1,7 +1,7 @@ FROM ghcr.io/flathub/flatpak-external-data-checker:latest RUN apt-get update && \ - apt-get install -y gh jq parallel && \ + apt-get install -y gh jq parallel curl && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ADD gh-ls-org /usr/local/bin/gh-ls-org From ba4c708ce7793719e9a0a339fea1668789161f84 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 23 Apr 2025 08:30:23 +0530 Subject: [PATCH 208/319] x-checker: Switch to infra org and log verbosely about removals --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index dc4bfa8..9563a46 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -12,7 +12,8 @@ mkdir flathub cd flathub || exit gh repo list flathub --visibility public -L 8000 --json url --json isArchived --jq '.[] | select(.isArchived == false)|.url' | parallel "git clone --depth 1 {}" -curl -s https://raw.githubusercontent.com/bbhtt/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do printf "Removing %s\n" "$folder"; rm -rf "$folder" || true; done +echo "==> Deleting inactive repos" +curl -s https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do test -d "$folder" && rm -rfv "$folder" || true; done mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do From 288da91ac987ba4873d0421fd69a5b57d0292e31 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 24 Apr 2025 20:07:00 +0530 Subject: [PATCH 209/319] Add workflow to trigger builds via voro --- .github/workflows/trigger-flathub-build.yml | 39 +++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/trigger-flathub-build.yml diff --git a/.github/workflows/trigger-flathub-build.yml b/.github/workflows/trigger-flathub-build.yml new file mode 100644 index 0000000..296a5c0 --- /dev/null +++ b/.github/workflows/trigger-flathub-build.yml @@ -0,0 +1,39 @@ +name: Trigger Flathub Build + +on: + workflow_dispatch: + inputs: + git_branch: + description: 'Git branch to build' + required: true + default: 'master' + flatpak_id: + description: 'Flatpak ID' + required: true + +env: + API_URL: https://flathub-vorarbeiter.apps.openshift.gnome.org/api/pipelines + FLATPAK_ID: ${{ github.event.inputs.flatpak_id }} + GIT_BRANCH: ${{ github.event.inputs.git_branch }} + +jobs: + build: + permissions: {} + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Check for existence of repo and branch + run: | + git -c credential.interactive=false ls-remote --heads --exit-code \ + https://github.com/flathub/"$FLATPAK_ID".git "$GIT_BRANCH" + + - name: Trigger build + run: | + echo "Triggering build for \"$FLATPAK_ID\" for branch \"$GIT_BRANCH\"" + JSON_PAYLOAD="{\"app_id\": \"$FLATPAK_ID\", \"params\": {\"ref\": \"refs/heads/$GIT_BRANCH\"}}" + curl -X POST "$API_URL" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/json" \ + -d "$JSON_PAYLOAD" + env: + TOKEN: ${{ secrets.VORO_AUTH_TOKEN }} From 8f08a789a00527ab36a8f79b9ccc521805b60217 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 26 Apr 2025 08:04:05 +0530 Subject: [PATCH 210/319] Add logic to trigger test builds from master --- .github/workflows/trigger-flathub-build.yml | 37 ++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/.github/workflows/trigger-flathub-build.yml b/.github/workflows/trigger-flathub-build.yml index 296a5c0..34ead3e 100644 --- a/.github/workflows/trigger-flathub-build.yml +++ b/.github/workflows/trigger-flathub-build.yml @@ -1,4 +1,5 @@ name: Trigger Flathub Build +run-name: Build of ${{ inputs.flatpak_id }} from ref ${{ inputs.git_branch }} on: workflow_dispatch: @@ -10,11 +11,21 @@ on: flatpak_id: description: 'Flatpak ID' required: true + force_test: + description: 'Force test build on master' + required: true + default: 'false' + type: choice + options: + - 'true' + - 'false' env: API_URL: https://flathub-vorarbeiter.apps.openshift.gnome.org/api/pipelines FLATPAK_ID: ${{ github.event.inputs.flatpak_id }} GIT_BRANCH: ${{ github.event.inputs.git_branch }} + FORCE_TEST: ${{ github.event.inputs.force_test }} + GITHUB_URL: https://github.com/flathub jobs: build: @@ -25,12 +36,30 @@ jobs: - name: Check for existence of repo and branch run: | git -c credential.interactive=false ls-remote --heads --exit-code \ - https://github.com/flathub/"$FLATPAK_ID".git "$GIT_BRANCH" - + "$GITHUB_URL"/"$FLATPAK_ID".git "$GIT_BRANCH" + + - name: Print information + shell: bash + run: | + if [ "$FORCE_TEST" == "true" ]; then + echo -e "\n\n" + echo "Triggering test build from master branch of $FLATPAK_ID" + elif [ "$GIT_BRANCH" == "master" ] || [ "$GIT_BRANCH" == "beta" ]; then + echo -e "\n\n" + echo "Triggering official build from $GIT_BRANCH branch of $FLATPAK_ID" + else + echo -e "\n\n" + echo "Triggering test build from $GIT_BRANCH of $FLATPAK_ID" + fi + - name: Trigger build run: | - echo "Triggering build for \"$FLATPAK_ID\" for branch \"$GIT_BRANCH\"" - JSON_PAYLOAD="{\"app_id\": \"$FLATPAK_ID\", \"params\": {\"ref\": \"refs/heads/$GIT_BRANCH\"}}" + if [ "$FORCE_TEST" == "true" ]; then + JSON_PAYLOAD="{\"app_id\": \"$FLATPAK_ID\", \"params\": {}}" + else + JSON_PAYLOAD="{\"app_id\": \"$FLATPAK_ID\", \"params\": {\"ref\": \"refs/heads/$GIT_BRANCH\"}}" + fi + curl -X POST "$API_URL" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ From 4e0cdd30d251b161f8f476ecbdacf0b8ea4dd02d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 1 May 2025 07:37:43 +0530 Subject: [PATCH 211/319] stale: Once a week --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 5362588..1945a5b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,7 +1,7 @@ name: "Close stale PR" on: schedule: - - cron: "0 0 1 * *" + - cron: "0 5 * * 0" workflow_dispatch: jobs: From 47dbcad3a7c598fbb307f8bc386b60f055d37e4c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 13 May 2025 10:53:19 +0530 Subject: [PATCH 212/319] fedc: Support commit-only arg through flathub.json Fixes https://github.com/flathub-infra/flatpak-external-data-checker/issues/163 --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 9563a46..125c089 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -32,6 +32,10 @@ for repo in "${checker_apps[@]}"; do if jq -e '."require-important-update"' < "$repo"/flathub.json > /dev/null; then FEDC_OPTS+=("--require-important-update") fi + # disable sending PRs and only commit + if jq -e '."fedc-commit-only" == true' < "$repo"/flathub.json > /dev/null; then + FEDC_OPTS+=("--commit-only") + fi fi if [[ -f $repo/${repo}.yml ]]; then From 27da5466e3902741d909e48a7a729bc328bd9943 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 14 May 2025 11:48:21 +0530 Subject: [PATCH 213/319] Improve the PR template --- .github/pull_request_template.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 19e8b78..06bb062 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,11 +8,10 @@ - [ ] Please describe the application briefly. - [ ] The domain used for the application ID is [controlled by the application developer(s)][appid-domain] and the [application id guidelines][appid] are followed. -- [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2]. -- [ ] I have [built][build] and tested the submission locally. -- [ ] I am an author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** +- [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them. +- [ ] I am an _(please write whichever is applicable)_ author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** - + @@ -20,4 +19,3 @@ [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [reqs2]: https://docs.flathub.org/docs/for-app-authors/submission -[build]: https://docs.flathub.org/docs/for-app-authors/submission/#before-submission From 7c17cdc50cd4fc5e773aeb95b02d11be2614c589 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 24 May 2025 14:05:11 +0530 Subject: [PATCH 214/319] Update PR template --- .github/pull_request_template.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 06bb062..313cb28 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,21 +1,24 @@ - + - + ### Please confirm your submission meets all the criteria + + - [ ] Please describe the application briefly. -- [ ] The domain used for the application ID is [controlled by the application developer(s)][appid-domain] and the [application id guidelines][appid] are followed. +- [ ] Please include a screenrecord (10-20s) showcasing the application. +- [ ] The Flatpak ID follows all the rules listed in the [Application ID requirements][appid]. - [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them. -- [ ] I am an _(please write whichever is applicable)_ author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** +- [ ] I am an _(please write whichever is applicable)_ author/developer/upstream contributor to the project. + If not, I contacted upstream developers about this submission. **Link:** - + - + -[appid-domain]: https://docs.flathub.org/docs/for-app-authors/requirements/#control-over-domain-or-repository [appid]: https://docs.flathub.org/docs/for-app-authors/requirements#application-id [reqs]: https://docs.flathub.org/docs/for-app-authors/requirements [reqs2]: https://docs.flathub.org/docs/for-app-authors/submission From 6eb7d8dabae9f2817896a0710b23907244db1287 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 25 May 2025 11:59:33 +0530 Subject: [PATCH 215/319] Add new PR automation --- .github/scripts/validate.py | 27 ++++++++ .github/workflows/pr-check.yml | 113 +++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 .github/scripts/validate.py create mode 100644 .github/workflows/pr-check.yml diff --git a/.github/scripts/validate.py b/.github/scripts/validate.py new file mode 100644 index 0000000..86c406d --- /dev/null +++ b/.github/scripts/validate.py @@ -0,0 +1,27 @@ +import re +import os + + +def validate_title(title: str) -> int: + if not title.startswith("Add "): + return 42 + + appid = title[len("Add ") :].strip() + regex = r"^[A-Za-z_][\w\-]*$" + split = appid.split(".") + + if ( + len(split) > 255 + or len(split) < 3 + or not all(re.match(regex, sp) for sp in split) + ): + return 42 + + return 0 + + +if __name__ == "__main__": + title = os.environ["PR_TITLE"] + exit_code = validate_title(title) + print(f"EXIT_CODE={exit_code}") + exit(0) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..e2d1178 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,113 @@ +name: Check PRs + +on: + workflow_dispatch: + schedule: + - cron: '0 * * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + validate-prs: + runs-on: ubuntu-latest + timeout-minutes: 45 + permissions: + pull-requests: write + steps: + - name: Fetch recent PR numbers + run: | + prs_raw=$(gh pr list --base "new-pr" -L 100 --state open --json number,createdAt,isDraft \ + | jq -r '[.[] + | select(.isDraft == false + and .createdAt >= (now - (1 * 24 * 60 * 60) | todate)) + | .number] + | .[]') + + unreviewed_prs=() + while IFS= read -r pr_num; do + review_count=$(gh pr view "$pr_num" --json reviews -q '.reviews | length') + if [ "$review_count" -eq 0 ]; then + unreviewed_prs+=("$pr_num") + fi + done <<< "$prs_raw" + prs_list=$(printf '%s\n' "${unreviewed_prs[@]}" | head -30 | paste -sd "," -) + echo "PR_LIST=$prs_list" >> "$GITHUB_ENV" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + + - name: Validate PRs + run: | + IFS=',' read -ra PR_NUMBERS <<< "${{ env.PR_LIST }}" + + if [ ${#PR_NUMBERS[@]} -eq 0 ] || [ -z "${PR_NUMBERS[0]}" ]; then + echo "No PRs found, exiting." + exit 0 + fi + + for PR_NUM in "${PR_NUMBERS[@]}"; do + echo "Checking PR #$PR_NUM" + + json=$(gh pr view "$PR_NUM" --json body,title -q '{body: .body, title: .title}') + PR_BODY=$(echo "$json" | jq -r .body) + PR_TITLE=$(echo "$json" | jq -r .title) + + unset $PR_TITLE + export PR_TITLE="$PR_TITLE" + + EXIT_CODE=$(curl -sSL "$SCRIPT_URL" | python3 | grep 'EXIT_CODE=' | cut -d= -f2) + echo "EXIT_CODE is $EXIT_CODE" + unset $PR_TITLE + + BLOCKED=0 + + comment_exists() { + gh pr view "$PR_NUM" --json comments -q '.comments[].body' | grep -Fq "$PART_COMMENT" + } + + if [ "$EXIT_CODE" -ne 0 ]; then + echo "PR title validation failed" + BLOCKED=1 + fi + + CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- \[.?] [A-Za-z]+' || true) + echo "Total checklists found: $CHECKLIST_PRESENT" + UNCHECKED=$(printf "%s\n" "$PR_BODY" | grep -Ec '^- \[ \] [A-Za-z]+' || true) + echo "Unchecked checklists found: $UNCHECKED" + + if [ "$CHECKLIST_PRESENT" -eq 0 ]; then + echo "No checklist present in PR body" + BLOCKED=1 + elif [ "$UNCHECKED" -gt 0 ]; then + echo "Checklist incomplete in PR body" + BLOCKED=1 + fi + + echo "BLOCKED is set to $BLOCKED" + + if [ "$BLOCKED" -eq 0 ]; then + echo "Marking as awaiting-review" + gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "blocked" || true + else + echo "Marking as blocked" + gh pr edit "$PR_NUM" --add-label "blocked" --remove-label "awaiting-review" + if ! comment_exists; then + echo "Did not find comment, commenting" + gh pr comment "$PR_NUM" --body "$COMMENT" + else + echo "Found comment, skipping commenting" + fi + fi + done + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + SCRIPT_URL: https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/scripts/validate.py + PART_COMMENT: "This pull request is temporarily marked as blocked as some" + COMMENT: > + This pull request is temporarily marked as blocked as some + automated checks failed on it. Please make sure the pull + request title is `Add $FLATPAK_ID` and that all checklist + items in the pull request body are marked as complete. From 78391cf8dffb9d082da593da41676c046eb9db70 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 25 May 2025 12:22:22 +0530 Subject: [PATCH 216/319] pr-check: Run on all recent PRs --- .github/workflows/pr-check.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index e2d1178..c17e25c 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -18,21 +18,13 @@ jobs: steps: - name: Fetch recent PR numbers run: | - prs_raw=$(gh pr list --base "new-pr" -L 100 --state open --json number,createdAt,isDraft \ + prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,createdAt,isDraft \ | jq -r '[.[] | select(.isDraft == false - and .createdAt >= (now - (1 * 24 * 60 * 60) | todate)) + and .createdAt >= (now - (2 * 24 * 60 * 60) | todate)) | .number] | .[]') - - unreviewed_prs=() - while IFS= read -r pr_num; do - review_count=$(gh pr view "$pr_num" --json reviews -q '.reviews | length') - if [ "$review_count" -eq 0 ]; then - unreviewed_prs+=("$pr_num") - fi - done <<< "$prs_raw" - prs_list=$(printf '%s\n' "${unreviewed_prs[@]}" | head -30 | paste -sd "," -) + prs_list=$(printf '%s\n' $prs_raw | head -30 | paste -sd "," -) echo "PR_LIST=$prs_list" >> "$GITHUB_ENV" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1d379defa4b4021ca888c609d5a1bd641340ed5f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 25 May 2025 12:31:52 +0530 Subject: [PATCH 217/319] pr-check: Don't label as awaiting-review if already labeled --- .github/workflows/pr-check.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index c17e25c..c1e2b1e 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -77,9 +77,12 @@ jobs: BLOCKED=1 fi - echo "BLOCKED is set to $BLOCKED" + has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "blocked" or .name == "awaiting-upstream")') - if [ "$BLOCKED" -eq 0 ]; then + echo "BLOCKED is set to $BLOCKED" + echo "Reviewd labels is set to $has_label" + + if [ "$BLOCKED" -eq 0 ] && [ "$has_label" != "true" ]; then echo "Marking as awaiting-review" gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "blocked" || true else From 8c138f63c057bba50cc581e91bec18e52edadb50 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 25 May 2025 12:34:33 +0530 Subject: [PATCH 218/319] pr-check: Change else to elif --- .github/workflows/pr-check.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index c1e2b1e..4ee3bb4 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -85,7 +85,7 @@ jobs: if [ "$BLOCKED" -eq 0 ] && [ "$has_label" != "true" ]; then echo "Marking as awaiting-review" gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "blocked" || true - else + elif [ "$BLOCKED" -eq 1 ]; then echo "Marking as blocked" gh pr edit "$PR_NUM" --add-label "blocked" --remove-label "awaiting-review" if ! comment_exists; then @@ -94,6 +94,8 @@ jobs: else echo "Found comment, skipping commenting" fi + else + echo "Nothing to do" fi done env: From 33d1ef3483f07960d8bc556a26bc2cae2c0b1042 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 26 May 2025 07:35:30 +0530 Subject: [PATCH 219/319] validate: Allow title to start with lowercase add --- .github/scripts/validate.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/scripts/validate.py b/.github/scripts/validate.py index 86c406d..5e242e2 100644 --- a/.github/scripts/validate.py +++ b/.github/scripts/validate.py @@ -3,10 +3,12 @@ import os def validate_title(title: str) -> int: - if not title.startswith("Add "): + prefix_pattern = r"(?i)^add\s+" + matched = re.match(prefix_pattern, title) + if not matched: return 42 - appid = title[len("Add ") :].strip() + appid = title[matched.end() :].strip() regex = r"^[A-Za-z_][\w\-]*$" split = appid.split(".") From 7a01c0cdc10762297f29388c613fef95a630fca4 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 26 May 2025 07:35:57 +0530 Subject: [PATCH 220/319] pr-check: Make the regex to match checklists more specific --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 4ee3bb4..d9363af 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -64,7 +64,7 @@ jobs: BLOCKED=1 fi - CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- \[.?] [A-Za-z]+' || true) + CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- ?\[[xX]\] [A-Za-z]+' || true) echo "Total checklists found: $CHECKLIST_PRESENT" UNCHECKED=$(printf "%s\n" "$PR_BODY" | grep -Ec '^- \[ \] [A-Za-z]+' || true) echo "Unchecked checklists found: $UNCHECKED" From f14cec62359bb0a302fbb33ffe2ba436827c35fc Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 26 May 2025 21:07:01 +0530 Subject: [PATCH 221/319] pr-check: Remove blocked from has_label --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index d9363af..a28d765 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -77,7 +77,7 @@ jobs: BLOCKED=1 fi - has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "blocked" or .name == "awaiting-upstream")') + has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "awaiting-upstream")') echo "BLOCKED is set to $BLOCKED" echo "Reviewd labels is set to $has_label" From fd4decdd089de38fe96713e59038b147a4686f2b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 26 May 2025 21:08:29 +0530 Subject: [PATCH 222/319] pr-check: Fix spelling --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index a28d765..7c31e96 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -80,7 +80,7 @@ jobs: has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "awaiting-upstream")') echo "BLOCKED is set to $BLOCKED" - echo "Reviewd labels is set to $has_label" + echo "Reviewed labels is set to $has_label" if [ "$BLOCKED" -eq 0 ] && [ "$has_label" != "true" ]; then echo "Marking as awaiting-review" From da89fb501158874e387ebf5863033cfe38b59e75 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 27 May 2025 06:14:45 +0530 Subject: [PATCH 223/319] pr-check: Use a different blocked label --- .github/workflows/pr-check.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 7c31e96..3ae3ea2 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -77,17 +77,17 @@ jobs: BLOCKED=1 fi - has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "awaiting-upstream")') + has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "awaiting-upstream" or .name == "blocked")') echo "BLOCKED is set to $BLOCKED" echo "Reviewed labels is set to $has_label" if [ "$BLOCKED" -eq 0 ] && [ "$has_label" != "true" ]; then echo "Marking as awaiting-review" - gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "blocked" || true + gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "pr-check-blocked" || true elif [ "$BLOCKED" -eq 1 ]; then echo "Marking as blocked" - gh pr edit "$PR_NUM" --add-label "blocked" --remove-label "awaiting-review" + gh pr edit "$PR_NUM" --add-label "pr-check-blocked" --remove-label "awaiting-review" if ! comment_exists; then echo "Did not find comment, commenting" gh pr comment "$PR_NUM" --body "$COMMENT" From d16bc98786a2cd6c50fa81823b8018841cc1d138 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 29 May 2025 22:02:34 +0530 Subject: [PATCH 224/319] Be more explicit about screenrecord item --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 313cb28..98c1a90 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,7 +9,7 @@ - [ ] Please describe the application briefly. -- [ ] Please include a screenrecord (10-20s) showcasing the application. +- [ ] Please attach or link a screenrecord showcasing the application on Linux using the Flatpak. - [ ] The Flatpak ID follows all the rules listed in the [Application ID requirements][appid]. - [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them. - [ ] I am an _(please write whichever is applicable)_ author/developer/upstream contributor to the project. From 9236788bd2c0cedbfe75734c33473190fb87c623 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 3 Jun 2025 23:45:35 +0530 Subject: [PATCH 225/319] pr-check: Add link to PR template --- .github/workflows/pr-check.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 3ae3ea2..23055fd 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -106,5 +106,6 @@ jobs: COMMENT: > This pull request is temporarily marked as blocked as some automated checks failed on it. Please make sure the pull - request title is `Add $FLATPAK_ID` and that all checklist - items in the pull request body are marked as complete. + request title is `Add $FLATPAK_ID` and that all + [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) + in the pull request body are marked as complete. From 63df2b44ab6a05f7bf8998c405e017949193cc9d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 5 Jun 2025 08:09:50 +0530 Subject: [PATCH 226/319] pr-check: Add automation to start build automatically and misc fixes --- .github/workflows/pr-check.yml | 65 +++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 23055fd..cbd319b 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -40,23 +40,55 @@ jobs: fi for PR_NUM in "${PR_NUMBERS[@]}"; do - echo "Checking PR #$PR_NUM" + echo "Checking PR https://github.com/flathub/flathub/pull/$PR_NUM" json=$(gh pr view "$PR_NUM" --json body,title -q '{body: .body, title: .title}') PR_BODY=$(echo "$json" | jq -r .body) PR_TITLE=$(echo "$json" | jq -r .title) - unset $PR_TITLE + unset "$PR_TITLE" export PR_TITLE="$PR_TITLE" EXIT_CODE=$(curl -sSL "$SCRIPT_URL" | python3 | grep 'EXIT_CODE=' | cut -d= -f2) echo "EXIT_CODE is $EXIT_CODE" - unset $PR_TITLE + unset "$PR_TITLE" + + PR_COMMENTS="$(gh pr view "$PR_NUM" --json comments -q '.comments[].body')" + + PR_LABELS="$(gh pr view "$PR_NUM" --json labels -q '.labels[].name')" BLOCKED=0 comment_exists() { - gh pr view "$PR_NUM" --json comments -q '.comments[].body' | grep -Fq "$PART_COMMENT" + local comment="$1" + echo "$PR_COMMENTS" | grep -Fq "$comment" + } + + comment_exists_any() { + for comment in "$@"; do + if echo "$PR_COMMENTS" | grep -Fq "$comment"; then + return 0 + fi + done + return 1 + } + + label_exists_any() { + for label in "$@"; do + if echo "$PR_LABELS" | grep -Fq "$label"; then + return 0 + fi + done + return 1 + } + + start_build() { + if ! label_exists_any "pr-check-blocked" "blocked"; then + if ! comment_exists_any "$BUILD_START_COMMENT_PARTIAL" "$BUILD_ENQUEUED" "$BUILD_STARTED" "$BUILD_SUCCESS_COMMENT"; then + echo "PR is not marked as blocked and none of the build comments exist. Starting a build" + gh pr comment "$PR_NUM" --body "$BUILD_START_COMMENT" + fi + fi } if [ "$EXIT_CODE" -ne 0 ]; then @@ -77,35 +109,44 @@ jobs: BLOCKED=1 fi - has_label=$(gh pr view "$PR_NUM" --json labels -q '.labels | any(.name == "awaiting-changes" or .name == "awaiting-upstream" or .name == "blocked")') - echo "BLOCKED is set to $BLOCKED" - echo "Reviewed labels is set to $has_label" - if [ "$BLOCKED" -eq 0 ] && [ "$has_label" != "true" ]; then + if [ "$BLOCKED" -eq 0 ] && ! label_exists_any "awaiting-changes" "awaiting-upstream" "blocked" "reviewed-waiting"; then echo "Marking as awaiting-review" gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "pr-check-blocked" || true + start_build elif [ "$BLOCKED" -eq 1 ]; then echo "Marking as blocked" gh pr edit "$PR_NUM" --add-label "pr-check-blocked" --remove-label "awaiting-review" - if ! comment_exists; then + if ! comment_exists "$REVIEW_COMMENT_PARTIAL"; then echo "Did not find comment, commenting" - gh pr comment "$PR_NUM" --body "$COMMENT" + gh pr comment "$PR_NUM" --body "$REVIEW_COMMENT" else echo "Found comment, skipping commenting" fi else echo "Nothing to do" + start_build fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} SCRIPT_URL: https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/scripts/validate.py - PART_COMMENT: "This pull request is temporarily marked as blocked as some" - COMMENT: > + BUILD_ENQUEUED: "Test build [enqueued]" + BUILD_STARTED: "Started [test build]" + BUILD_SUCCESS_COMMENT: "[Test build succeeded]" + BUILD_START_COMMENT: | + Starting a test build of the submission. Please fix any + issues reported in the build log. You can restart the build + once the issue is fixed by commenting the phrase below. + + bot, build + BUILD_START_COMMENT_PARTIAL: "Starting a test build of the submission" + REVIEW_COMMENT: > This pull request is temporarily marked as blocked as some automated checks failed on it. Please make sure the pull request title is `Add $FLATPAK_ID` and that all [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) in the pull request body are marked as complete. + REVIEW_COMMENT_PARTIAL: "This pull request is temporarily marked as blocked as some" From 1ae25a580747ba3a5ccd85f0ee9633a9f1e54ee6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Jun 2025 07:35:03 +0530 Subject: [PATCH 227/319] pr-check: Fetch PRs by updated at --- .github/workflows/pr-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index cbd319b..b6017c0 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -18,10 +18,10 @@ jobs: steps: - name: Fetch recent PR numbers run: | - prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,createdAt,isDraft \ + prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,updatedAt,isDraft \ | jq -r '[.[] | select(.isDraft == false - and .createdAt >= (now - (2 * 24 * 60 * 60) | todate)) + and .updatedAt >= (now - (2 * 24 * 60 * 60) | todate)) | .number] | .[]') prs_list=$(printf '%s\n' $prs_raw | head -30 | paste -sd "," -) From 533839f41c167106f11e923599dd8e420af07840 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Jun 2025 07:36:04 +0530 Subject: [PATCH 228/319] pr-check: Count only BUILD_SUCCESS_COMMENT --- .github/workflows/pr-check.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index b6017c0..7edf1f1 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -84,7 +84,7 @@ jobs: start_build() { if ! label_exists_any "pr-check-blocked" "blocked"; then - if ! comment_exists_any "$BUILD_START_COMMENT_PARTIAL" "$BUILD_ENQUEUED" "$BUILD_STARTED" "$BUILD_SUCCESS_COMMENT"; then + if ! comment_exists_any "$BUILD_START_COMMENT_PARTIAL" "$BUILD_SUCCESS_COMMENT"; then echo "PR is not marked as blocked and none of the build comments exist. Starting a build" gh pr comment "$PR_NUM" --body "$BUILD_START_COMMENT" fi @@ -133,8 +133,6 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} SCRIPT_URL: https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/scripts/validate.py - BUILD_ENQUEUED: "Test build [enqueued]" - BUILD_STARTED: "Started [test build]" BUILD_SUCCESS_COMMENT: "[Test build succeeded]" BUILD_START_COMMENT: | Starting a test build of the submission. Please fix any From 2c602e1e0cce636a452b8094813e3a2b018f9dea Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 7 Jun 2025 08:03:39 +0530 Subject: [PATCH 229/319] merge: Explicitly check if a target repo already exists in the org --- .github/actions/merge/entrypoint.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 4cd454c..a3eb860 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -176,6 +176,22 @@ def main(): print(f"Detected {appid} as appid from {manifest_file}") + try: + org.get_repo(appid) + print( + f"Repository {appid} already exists in the flathub organisation, exiting." + ) + sys.exit(1) + except github.GithubException as err: + if err.status == 404: + print( + f"Repository {appid} does not exist in the flathub organisation, continuing." + ) + pass + else: + print(f"Unexpected error while checking for repository {appid}: {err}") + raise + print("Creating new repo on Flathub") repo = org.create_repo(appid) time.sleep(5) From 78c0bb0642c0edf3bbb233a3d4633985537786d9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:08:00 +0530 Subject: [PATCH 230/319] merge: Fetch PR metadata early --- .github/actions/merge/entrypoint.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index a3eb860..38cd2cd 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -151,19 +151,20 @@ def main(): reviewers = org.get_team_by_slug("reviewers") comment_author = gh.get_user(github_event["comment"]["user"]["login"]) + flathub = org.get_repo("flathub") + + pr_id = int(github_event["issue"]["number"]) + pr = flathub.get_pull(pr_id) + branch = pr.head.label.split(":")[1] + fork_url = pr.head.repo.clone_url + pr_author = pr.user.login + if not admins.has_in_members(comment_author) and not reviewers.has_in_members( comment_author ): print(f"{comment_author} is not a reviewer") sys.exit(1) - flathub = org.get_repo("flathub") - pr_id = int(github_event["issue"]["number"]) - pr = flathub.get_pull(pr_id) - pr_author = pr.user.login - branch = pr.head.label.split(":")[1] - fork_url = pr.head.repo.clone_url - tmpdir = tempfile.TemporaryDirectory() print(f"Cloning {fork_url} (branch: {branch})") clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=branch) From e1f3426b519657117dfa4400670822aab14f1488 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:09:33 +0530 Subject: [PATCH 231/319] merge: Check that comment starts with `/merge` --- .github/actions/merge/entrypoint.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 38cd2cd..d5455d1 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -137,7 +137,13 @@ def main(): print("The issue is not a pull request") sys.exit(0) - command_re = re.search("^/merge.*", github_event["comment"]["body"], re.M) + github_comment = github_event["comment"]["body"] + + if not github_comment.startswith("/merge"): + print("The comment does not start with '/merge'") + sys.exit(0) + + command_re = re.search("^/merge.*", github_comment, re.M) if not command_re: print("The comment doesn't contain '/merge' command") sys.exit(0) From 4d092986496bf3acd4eaac9cdba65fb27acf56f9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:16:20 +0530 Subject: [PATCH 232/319] merge: Change name of PR branch variable --- .github/actions/merge/entrypoint.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index d5455d1..0568ba1 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -161,7 +161,7 @@ def main(): pr_id = int(github_event["issue"]["number"]) pr = flathub.get_pull(pr_id) - branch = pr.head.label.split(":")[1] + pr_branch = pr.head.label.split(":")[1] fork_url = pr.head.repo.clone_url pr_author = pr.user.login @@ -172,8 +172,8 @@ def main(): sys.exit(1) tmpdir = tempfile.TemporaryDirectory() - print(f"Cloning {fork_url} (branch: {branch})") - clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=branch) + print(f"Cloning {fork_url} (branch: {pr_branch})") + clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=pr_branch) clone.submodules.update(init=True) manifest_file, appid = detect_appid(tmpdir.name) @@ -220,7 +220,7 @@ def main(): remote_branch = "master" print("Pushing changes to the new Flathub repo") - git_push = f"cd {tmpdir.name} && git push flathub {branch}:{remote_branch}" + git_push = f"cd {tmpdir.name} && git push flathub {pr_branch}:{remote_branch}" ret = subprocess.run( git_push, shell=True, From 2453cb48b7994b4bf7a3cb0f92ac4e1384bbb8c8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:15:36 +0530 Subject: [PATCH 233/319] merge: Use regex to extract everything --- .github/actions/merge/entrypoint.py | 45 +++++++++++++++++++---------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 0568ba1..d8abe2d 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -143,12 +143,33 @@ def main(): print("The comment does not start with '/merge'") sys.exit(0) - command_re = re.search("^/merge.*", github_comment, re.M) - if not command_re: - print("The comment doesn't contain '/merge' command") - sys.exit(0) + command_pattern = re.compile(r"^/merge(?::([\w.-]+))?(.*)$") + matched = command_pattern.search(github_comment) + if not matched: + print( + "The comment is not a valid '/merge' command.\n" + "Format: '/merge: " + "'" + ) + sys.exit(1) + + branch_match = matched.group(1) or "master" + if branch_match in ("master", "beta"): + target_repo_default_branch = branch_match else: - command = command_re.group() + target_repo_default_branch = f"branch/{branch_match}" + + print(f"Got target branch {target_repo_default_branch} from comment") + + rest_comment = matched.group(2) + + # https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/iam-configuration-reference/username-considerations-for-external-authentication#about-username-normalization + # > Usernames for user accounts on GitHub can only contain alphanumeric characters and dashes + # > If the username is longer than 39 characters (including underscore and short code), + # > the provisioning attempt will fail with a 400 error. + additional_colbs = [m[1:] for m in re.findall(r"@[a-zA-Z0-9-]{1,39}", rest_comment)] + + print(f"Got additional collaborators {additional_colbs} from comment") gh = github.Github(github_token) org = gh.get_organization("flathub") @@ -212,15 +233,10 @@ def main(): "flathub", f"https://x-access-token:{github_token}@github.com/flathub/{appid}" ) - try: - remote_branch = command.split()[0].split(":")[1] - if remote_branch != "beta": - remote_branch = f"branch/{remote_branch}" - except IndexError: - remote_branch = "master" - print("Pushing changes to the new Flathub repo") - git_push = f"cd {tmpdir.name} && git push flathub {pr_branch}:{remote_branch}" + git_push = ( + f"cd {tmpdir.name} && git push flathub {pr_branch}:{target_repo_default_branch}" + ) ret = subprocess.run( git_push, shell=True, @@ -248,8 +264,7 @@ def main(): kde_maintainers = org.get_team_by_slug("KDE") kde_maintainers.update_team_repository(repo, "push") - collaborators = {user.replace("@", "") for user in command.split()[1:]} - for user in collaborators: + for user in additional_colbs: try: print(f"adding {user} to collaborators") repo.add_to_collaborators(user, permission="push") From ac570277a04ae8c51683c20b4226a02b78b5e7e2 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:20:26 +0530 Subject: [PATCH 234/319] merge: Make sending PR head commit sha mandatory --- .github/actions/merge/entrypoint.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index d8abe2d..2207262 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -143,12 +143,13 @@ def main(): print("The comment does not start with '/merge'") sys.exit(0) - command_pattern = re.compile(r"^/merge(?::([\w.-]+))?(.*)$") + command_pattern = re.compile(r"^/merge(?::([\w.-]+))? head=([a-fA-F0-9]{40})(.*)$") matched = command_pattern.search(github_comment) if not matched: print( "The comment is not a valid '/merge' command.\n" "Format: '/merge: " + "head= " "'" ) sys.exit(1) @@ -161,7 +162,10 @@ def main(): print(f"Got target branch {target_repo_default_branch} from comment") - rest_comment = matched.group(2) + pr_head_sha = str(matched.group(2)) + print(f"Got PR HEAD SHA from comment: {pr_head_sha}") + + rest_comment = matched.group(3) # https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/iam-configuration-reference/username-considerations-for-external-authentication#about-username-normalization # > Usernames for user accounts on GitHub can only contain alphanumeric characters and dashes From 6d4a74c8a488a9b3f06a0f2d727a1c32dbb8e5e2 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:21:42 +0530 Subject: [PATCH 235/319] merge: Match PR sha with clone sha --- .github/actions/merge/entrypoint.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 2207262..2abf2a1 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -199,8 +199,12 @@ def main(): tmpdir = tempfile.TemporaryDirectory() print(f"Cloning {fork_url} (branch: {pr_branch})") clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=pr_branch) + clone_head_sha = str(clone.head.target) + print(f"Clone HEAD SHA: {clone_head_sha}") clone.submodules.update(init=True) + assert clone_head_sha == pr_head_sha + manifest_file, appid = detect_appid(tmpdir.name) if manifest_file is None or appid is None: print("Failed to detect appid") From c70bb2f9057fb4eb1f182d04b2e5e90e4d1932dd Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:22:43 +0530 Subject: [PATCH 236/319] merge: Print error from githubexception --- .github/actions/merge/entrypoint.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 2abf2a1..2d83191 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -276,8 +276,9 @@ def main(): try: print(f"adding {user} to collaborators") repo.add_to_collaborators(user, permission="push") - except github.GithubException: + except github.GithubException as err: print(f"Adding {user} failed") + print(err) pass close_comment = ( From 6129b073ecf8d80bdc8f89e87060a86dbd2c8a17 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 06:47:34 +0530 Subject: [PATCH 237/319] merge: Assert that remote head sha matches too Fix casing in print too --- .github/actions/merge/entrypoint.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 2d83191..4782c68 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -260,6 +260,11 @@ def main(): for branch in ("master", "main", "stable", "branch/*", "beta", "beta/*"): set_protected_branch(github_token, appid, branch) + remote_branch_obj = repo.get_branch(target_repo_default_branch) + remote_head_sha = str(remote_branch_obj.commit.sha) + print(f"Remote HEAD SHA: {remote_head_sha}") + assert pr_head_sha == remote_head_sha + print(f"Adding {pr_author} to collaborators") repo.add_to_collaborators(pr_author, permission="push") From 97b880b8b788de2ac3622a91c39dfcd1366f7b7f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 06:51:20 +0530 Subject: [PATCH 238/319] merge: Assert that target branch was protected --- .github/actions/merge/entrypoint.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 4782c68..1facb71 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -265,6 +265,10 @@ def main(): print(f"Remote HEAD SHA: {remote_head_sha}") assert pr_head_sha == remote_head_sha + assert remote_branch_obj.protected is True, ( + f"Branch '{target_repo_default_branch}' is not protected" + ) + print(f"Adding {pr_author} to collaborators") repo.add_to_collaborators(pr_author, permission="push") From 6a14077c6d7242002e8c5f891d7c54331aa19107 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 06:53:18 +0530 Subject: [PATCH 239/319] merge: Improve grammar in messages --- .github/actions/merge/entrypoint.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 1facb71..57364b2 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -272,21 +272,21 @@ def main(): print(f"Adding {pr_author} to collaborators") repo.add_to_collaborators(pr_author, permission="push") - print("Add trusted maintainers to collaborators") + print("Adding 'trusted-maintainers' to collaborators") trusted_maintainers = org.get_team_by_slug("trusted-maintainers") trusted_maintainers.update_team_repository(repo, "push") if repo.name.startswith("org.kde."): - print("Add KDE maintainers to collaborators") + print("Adding KDE maintainers to collaborators") kde_maintainers = org.get_team_by_slug("KDE") kde_maintainers.update_team_repository(repo, "push") for user in additional_colbs: try: - print(f"adding {user} to collaborators") + print(f"Adding mentioned {user} to collaborators") repo.add_to_collaborators(user, permission="push") except github.GithubException as err: - print(f"Adding {user} failed") + print(f"Adding mentioned {user} failed") print(err) pass From 7de304989080267cc7d59a42c343bb370242f0cb Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 06:56:39 +0530 Subject: [PATCH 240/319] merge: Add GNOME team for org.gnome. repos if the id has 3 components Rest might be org.gnome.gitlab or world not directly maintained by gnome release team --- .github/actions/merge/entrypoint.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 57364b2..6b4ddff 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -230,6 +230,7 @@ def main(): print("Creating new repo on Flathub") repo = org.create_repo(appid) + repo_name = repo.name time.sleep(5) repo.edit( homepage=f"https://flathub.org/apps/details/{appid}", @@ -276,11 +277,16 @@ def main(): trusted_maintainers = org.get_team_by_slug("trusted-maintainers") trusted_maintainers.update_team_repository(repo, "push") - if repo.name.startswith("org.kde."): + if repo_name.startswith("org.kde."): print("Adding KDE maintainers to collaborators") kde_maintainers = org.get_team_by_slug("KDE") kde_maintainers.update_team_repository(repo, "push") + if repo_name.startswith("org.gnome.") and repo_name.count(".") == 2: + print("Adding GNOME maintainers to collaborators") + gnome_maintainers = org.get_team_by_slug("GNOME") + gnome_maintainers.update_team_repository(repo, "push") + for user in additional_colbs: try: print(f"Adding mentioned {user} to collaborators") From a760da794e71d917ad894bfa3a7328df62e1f5b8 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:02:03 +0530 Subject: [PATCH 241/319] merge: Print final list of external colloborators --- .github/actions/merge/entrypoint.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 6b4ddff..9deb576 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -296,6 +296,9 @@ def main(): print(err) pass + final_colbs = [user.login for user in repo.get_collaborators(affiliation="outside")] + print(f"External colloborators added: {final_colbs}") + close_comment = ( f"A repository for this submission has been created: {repo.html_url} and it will be published to Flathub in 4-5 hours.", "\n", From bc686e06fa3699e2bceea54b73ce71a4772ab6fa Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:40:29 +0530 Subject: [PATCH 242/319] merge: Print stdout and stderr from git push only if it exists --- .github/actions/merge/entrypoint.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 9deb576..5d6ee11 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -253,8 +253,11 @@ def main(): stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ) - print(ret.stdout) - print(ret.stderr) + if ret.stdout: + print(f"Git push stdout:\n{ret.stdout.decode().strip()}") + if ret.stderr: + print(f"Git push stderr:\n{ret.stderr.decode().strip()}") + repo.remove_from_collaborators("flathubbot") print("Setting protected branches") From 07c941e5c9c80c51e5dc7f59333be59dd88abaa3 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 07:44:57 +0530 Subject: [PATCH 243/319] merge: Bump image commit --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 2344b3a..1ad74b6 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: - image: ghcr.io/flathub/actions/merge:latest@sha256:5ede625982e65dd0b495a6ace36c88cd206c25099da5f245a5f5a119f98728b8 + image: ghcr.io/flathub/actions/merge:latest@sha256:4ef07a13eb3266ba2f3f313776afc4c03a6c023f94521da6d33ccaee596bd113 steps: - name: Check if actor is reviewer id: check_reviewer From 4b4880054ef9a5d0769ec81618784ef41c243b19 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 08:06:18 +0530 Subject: [PATCH 244/319] merge: Assert PR state is open and current PR sha matches approved sha --- .github/actions/merge/entrypoint.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py index 5d6ee11..c842e85 100755 --- a/.github/actions/merge/entrypoint.py +++ b/.github/actions/merge/entrypoint.py @@ -203,6 +203,12 @@ def main(): print(f"Clone HEAD SHA: {clone_head_sha}") clone.submodules.update(init=True) + assert flathub.get_pull(pr_id).state == "open" + + assert flathub.get_pull(pr_id).head.sha == pr_head_sha, ( + f"Current PR HEAD SHA {flathub.get_pull(pr_id).head.sha} does not match approved SHA" + ) + assert clone_head_sha == pr_head_sha manifest_file, appid = detect_appid(tmpdir.name) @@ -266,6 +272,9 @@ def main(): remote_branch_obj = repo.get_branch(target_repo_default_branch) remote_head_sha = str(remote_branch_obj.commit.sha) + + assert flathub.get_pull(pr_id).state == "open" + print(f"Remote HEAD SHA: {remote_head_sha}") assert pr_head_sha == remote_head_sha @@ -299,6 +308,8 @@ def main(): print(err) pass + assert flathub.get_pull(pr_id).state == "open" + final_colbs = [user.login for user in repo.get_collaborators(affiliation="outside")] print(f"External colloborators added: {final_colbs}") From 869a5afc96d22e2ec7359b4c161456bfe7ee3d11 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 8 Jun 2025 08:24:25 +0530 Subject: [PATCH 245/319] merge: Bump image hash --- .github/workflows/merge.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 1ad74b6..e37d6ab 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -13,7 +13,7 @@ jobs: pull-requests: write if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} container: - image: ghcr.io/flathub/actions/merge:latest@sha256:4ef07a13eb3266ba2f3f313776afc4c03a6c023f94521da6d33ccaee596bd113 + image: ghcr.io/flathub/actions/merge:latest@sha256:8c1c910028b4bbf0f187fefe6fd69f50132d29a9ca5bad7cbbe820b83e34864c steps: - name: Check if actor is reviewer id: check_reviewer From 119935cd38bb36229804e3ed69e2a98773ab96d1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 9 Jun 2025 07:21:05 +0530 Subject: [PATCH 246/319] Update PR template --- .github/pull_request_template.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 98c1a90..3e749d5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,11 +8,11 @@ -- [ ] Please describe the application briefly. -- [ ] Please attach or link a screenrecord showcasing the application on Linux using the Flatpak. +- [ ] Please describe the application briefly. < Please insert the description here > +- [ ] Please attach or link a screenrecord showcasing the application on Linux using the Flatpak. < Please insert the screenrecord link/attachment here > - [ ] The Flatpak ID follows all the rules listed in the [Application ID requirements][appid]. - [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them. -- [ ] I am an _(please write whichever is applicable)_ author/developer/upstream contributor to the project. +- [ ] I am an _(please keep whichever is applicable and remove the rest)_ author/developer/upstream contributor to the project. If not, I contacted upstream developers about this submission. **Link:** From e3edefe60d63530e45cd6db8c1a4beca3360d2df Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Jun 2025 17:30:52 +0530 Subject: [PATCH 247/319] Use new merge action --- .github/workflows/merge.yml | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index e37d6ab..61865af 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -12,23 +12,7 @@ jobs: permissions: pull-requests: write if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} - container: - image: ghcr.io/flathub/actions/merge:latest@sha256:8c1c910028b4bbf0f187fefe6fd69f50132d29a9ca5bad7cbbe820b83e34864c steps: - - name: Check if actor is reviewer - id: check_reviewer - run: | - if gh api /orgs/"$REPO_OWNER"/teams/reviewers/memberships/"$ACTOR" --silent; then - echo "is-reviewer=true" >> "$GITHUB_OUTPUT" - else - echo "is-reviewer=false" >> "$GITHUB_OUTPUT" - fi - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} - REPO_OWNER: ${{ github.repository_owner }} - ACTOR: ${{ github.actor }} - - - run: /app/entrypoint.py - if: ${{ steps.check_reviewer.outputs.is-reviewer == 'true' }} - env: - GITHUB_TOKEN: ${{ secrets.FLATHUBBOT_TOKEN }} + - uses: flathub-infra/merge-action@main + with: + token: ${{ secrets.FLATHUBBOT_TOKEN }} From 29d96e01fe915706ffd1af4e51b09a3e835bb9c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 10 Jun 2025 08:48:40 +0000 Subject: [PATCH 248/319] build(deps): bump requests in /.github/actions/merge Bumps [requests](https://github.com/psf/requests) from 2.32.3 to 2.32.4. - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.32.3...v2.32.4) --- updated-dependencies: - dependency-name: requests dependency-version: 2.32.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- .github/actions/merge/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt index 564bcf8..73c3970 100644 --- a/.github/actions/merge/requirements.txt +++ b/.github/actions/merge/requirements.txt @@ -44,7 +44,7 @@ pynacl==1.5.0 # via pygithub pyyaml==6.0.1 # via -r requirements.in -requests==2.32.3 +requests==2.32.4 # via # gql # pygithub From 70538cd1c64faf50563cf0e3e0a1e2fabd02524b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 10 Jun 2025 21:13:08 +0530 Subject: [PATCH 249/319] merge: Add timeout and remove permissions and workflow_dispatch --- .github/workflows/merge.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 61865af..09c04a3 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -1,16 +1,14 @@ name: Automatic application merge -on: +on: issue_comment: types: - created - workflow_dispatch: jobs: merge: runs-on: ubuntu-latest - permissions: - pull-requests: write + timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - uses: flathub-infra/merge-action@main From 3a3823938b0bb8690c2b83f653d4e4e7a2cc0229 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 11:57:54 +0530 Subject: [PATCH 250/319] Drop merge action Now at https://github.com/flathub-infra/merge-action --- .github/actions/merge/Dockerfile | 24 -- .github/actions/merge/entrypoint.py | 336 ------------------------- .github/actions/merge/requirements.in | 4 - .github/actions/merge/requirements.txt | 65 ----- .github/workflows/build-merge.yml | 46 ---- 5 files changed, 475 deletions(-) delete mode 100644 .github/actions/merge/Dockerfile delete mode 100755 .github/actions/merge/entrypoint.py delete mode 100644 .github/actions/merge/requirements.in delete mode 100644 .github/actions/merge/requirements.txt delete mode 100644 .github/workflows/build-merge.yml diff --git a/.github/actions/merge/Dockerfile b/.github/actions/merge/Dockerfile deleted file mode 100644 index 2049e57..0000000 --- a/.github/actions/merge/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM python:3.12 AS builder - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libcairo2-dev libgirepository1.0-dev - -ADD requirements.txt . - -RUN python -m venv /venv && \ - /venv/bin/python -m pip install -r requirements.txt PyGObject==3.50.0 - -FROM python:3.12-slim -ENV PATH="/venv/bin:$PATH" - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - git gh jq libcairo2 libgirepository-1.0-1 gir1.2-json-1.0 && \ - apt-get clean && rm -rf /var/lib/apt/lists/* - -COPY --from=builder /venv /venv -COPY . /app -WORKDIR /app - -CMD ["/app/entrypoint.py"] diff --git a/.github/actions/merge/entrypoint.py b/.github/actions/merge/entrypoint.py deleted file mode 100755 index c842e85..0000000 --- a/.github/actions/merge/entrypoint.py +++ /dev/null @@ -1,336 +0,0 @@ -#!/usr/bin/env python3 - -import glob -import json -import os -import re -import subprocess -import sys -import tempfile -import time - -import gi -import github -import pygit2 -import yaml -from gql import Client, gql -from gql.transport.requests import RequestsHTTPTransport - -gi.require_version("Json", "1.0") -from gi.repository import Json # noqa: E402 - - -def set_protected_branch(token, repo, branch): - transport = RequestsHTTPTransport( - url="https://api.github.com/graphql", - headers={"Authorization": f"Bearer {token}"}, - ) - client = Client(transport=transport, fetch_schema_from_transport=False) - - gql_get_repo_id = gql( - """ - query get_repo_id($repo: String!) { - repository(name: $repo, owner: "flathub") { - id - } - } - """ - ) - - gql_add_branch_protection = gql( - """ - mutation add_branch_protection($repositoryID: ID!, $pattern: String!) { - createBranchProtectionRule( - input: { - allowsDeletions: false - allowsForcePushes: false - dismissesStaleReviews: false - isAdminEnforced: false - pattern: $pattern - repositoryId: $repositoryID - requiresApprovingReviews: true - requiredApprovingReviewCount: 0 - requiresCodeOwnerReviews: false - requiresStatusChecks: true - requiresStrictStatusChecks: true - restrictsReviewDismissals: false - requiredStatusCheckContexts: ["builds/x86_64"] - } - ) { - branchProtectionRule { - id - } - } - } - """ - ) - - repo_id = client.execute(gql_get_repo_id, variable_values={"repo": repo}) - repo_id = repo_id["repository"]["id"] - - result = client.execute( - gql_add_branch_protection, - variable_values={"repositoryID": repo_id, "pattern": branch}, - ) - return result - - -def detect_appid(dirname): - files = [] - ret = (None, None) - appid = None - - for ext in ("yml", "yaml", "json"): - files.extend(glob.glob(f"{dirname}/*.{ext}")) - - for filename in files: - print(f"Parsing {filename}") - if os.path.isfile(filename): - ext = filename.split(".")[-1] - - with open(filename) as f: - if ext in ("yml", "yaml"): - manifest = yaml.safe_load(f) - if "app-id" in manifest: - appid = manifest["app-id"] - elif "id" in manifest: - appid = manifest["id"] - else: - parser = Json.Parser() - if parser.load_from_file(filename): - root_node = parser.get_root() - if root_node.get_node_type() == Json.NodeType.OBJECT: - json_object = root_node.get_object() - if json_object.has_member("id"): - appid = json_object.get_string_member("id") - elif json_object.has_member("app-id"): - appid = json_object.get_string_member("app-id") - - if not appid: - continue - - if appid: - manifest_file = os.path.basename(filename) - if os.path.splitext(manifest_file)[0] != appid: - print(f"Skipping {manifest_file}, does not match appid {appid}") - continue - ret = (manifest_file, appid) - - return ret - - -def main(): - github_token = os.environ.get("GITHUB_TOKEN") - if not github_token: - print("GITHUB_TOKEN environment variable is not set") - sys.exit(1) - - github_event_path = os.environ.get("GITHUB_EVENT_PATH") - with open(github_event_path) as f: - github_event = json.load(f) - - if github_event["action"] != "created": - print("The event is not a comment") - sys.exit(0) - - if "pull_request" not in github_event["issue"]: - print("The issue is not a pull request") - sys.exit(0) - - github_comment = github_event["comment"]["body"] - - if not github_comment.startswith("/merge"): - print("The comment does not start with '/merge'") - sys.exit(0) - - command_pattern = re.compile(r"^/merge(?::([\w.-]+))? head=([a-fA-F0-9]{40})(.*)$") - matched = command_pattern.search(github_comment) - if not matched: - print( - "The comment is not a valid '/merge' command.\n" - "Format: '/merge: " - "head= " - "'" - ) - sys.exit(1) - - branch_match = matched.group(1) or "master" - if branch_match in ("master", "beta"): - target_repo_default_branch = branch_match - else: - target_repo_default_branch = f"branch/{branch_match}" - - print(f"Got target branch {target_repo_default_branch} from comment") - - pr_head_sha = str(matched.group(2)) - print(f"Got PR HEAD SHA from comment: {pr_head_sha}") - - rest_comment = matched.group(3) - - # https://docs.github.com/en/enterprise-cloud@latest/admin/managing-iam/iam-configuration-reference/username-considerations-for-external-authentication#about-username-normalization - # > Usernames for user accounts on GitHub can only contain alphanumeric characters and dashes - # > If the username is longer than 39 characters (including underscore and short code), - # > the provisioning attempt will fail with a 400 error. - additional_colbs = [m[1:] for m in re.findall(r"@[a-zA-Z0-9-]{1,39}", rest_comment)] - - print(f"Got additional collaborators {additional_colbs} from comment") - - gh = github.Github(github_token) - org = gh.get_organization("flathub") - - admins = org.get_team_by_slug("admins") - reviewers = org.get_team_by_slug("reviewers") - comment_author = gh.get_user(github_event["comment"]["user"]["login"]) - - flathub = org.get_repo("flathub") - - pr_id = int(github_event["issue"]["number"]) - pr = flathub.get_pull(pr_id) - pr_branch = pr.head.label.split(":")[1] - fork_url = pr.head.repo.clone_url - pr_author = pr.user.login - - if not admins.has_in_members(comment_author) and not reviewers.has_in_members( - comment_author - ): - print(f"{comment_author} is not a reviewer") - sys.exit(1) - - tmpdir = tempfile.TemporaryDirectory() - print(f"Cloning {fork_url} (branch: {pr_branch})") - clone = pygit2.clone_repository(fork_url, tmpdir.name, checkout_branch=pr_branch) - clone_head_sha = str(clone.head.target) - print(f"Clone HEAD SHA: {clone_head_sha}") - clone.submodules.update(init=True) - - assert flathub.get_pull(pr_id).state == "open" - - assert flathub.get_pull(pr_id).head.sha == pr_head_sha, ( - f"Current PR HEAD SHA {flathub.get_pull(pr_id).head.sha} does not match approved SHA" - ) - - assert clone_head_sha == pr_head_sha - - manifest_file, appid = detect_appid(tmpdir.name) - if manifest_file is None or appid is None: - print("Failed to detect appid") - sys.exit(1) - - print(f"Detected {appid} as appid from {manifest_file}") - - try: - org.get_repo(appid) - print( - f"Repository {appid} already exists in the flathub organisation, exiting." - ) - sys.exit(1) - except github.GithubException as err: - if err.status == 404: - print( - f"Repository {appid} does not exist in the flathub organisation, continuing." - ) - pass - else: - print(f"Unexpected error while checking for repository {appid}: {err}") - raise - - print("Creating new repo on Flathub") - repo = org.create_repo(appid) - repo_name = repo.name - time.sleep(5) - repo.edit( - homepage=f"https://flathub.org/apps/details/{appid}", - delete_branch_on_merge=True, - ) - - print("Adding flathub remote") - clone.remotes.create( - "flathub", f"https://x-access-token:{github_token}@github.com/flathub/{appid}" - ) - - print("Pushing changes to the new Flathub repo") - git_push = ( - f"cd {tmpdir.name} && git push flathub {pr_branch}:{target_repo_default_branch}" - ) - ret = subprocess.run( - git_push, - shell=True, - check=True, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - if ret.stdout: - print(f"Git push stdout:\n{ret.stdout.decode().strip()}") - if ret.stderr: - print(f"Git push stderr:\n{ret.stderr.decode().strip()}") - - repo.remove_from_collaborators("flathubbot") - - print("Setting protected branches") - for branch in ("master", "main", "stable", "branch/*", "beta", "beta/*"): - set_protected_branch(github_token, appid, branch) - - remote_branch_obj = repo.get_branch(target_repo_default_branch) - remote_head_sha = str(remote_branch_obj.commit.sha) - - assert flathub.get_pull(pr_id).state == "open" - - print(f"Remote HEAD SHA: {remote_head_sha}") - assert pr_head_sha == remote_head_sha - - assert remote_branch_obj.protected is True, ( - f"Branch '{target_repo_default_branch}' is not protected" - ) - - print(f"Adding {pr_author} to collaborators") - repo.add_to_collaborators(pr_author, permission="push") - - print("Adding 'trusted-maintainers' to collaborators") - trusted_maintainers = org.get_team_by_slug("trusted-maintainers") - trusted_maintainers.update_team_repository(repo, "push") - - if repo_name.startswith("org.kde."): - print("Adding KDE maintainers to collaborators") - kde_maintainers = org.get_team_by_slug("KDE") - kde_maintainers.update_team_repository(repo, "push") - - if repo_name.startswith("org.gnome.") and repo_name.count(".") == 2: - print("Adding GNOME maintainers to collaborators") - gnome_maintainers = org.get_team_by_slug("GNOME") - gnome_maintainers.update_team_repository(repo, "push") - - for user in additional_colbs: - try: - print(f"Adding mentioned {user} to collaborators") - repo.add_to_collaborators(user, permission="push") - except github.GithubException as err: - print(f"Adding mentioned {user} failed") - print(err) - pass - - assert flathub.get_pull(pr_id).state == "open" - - final_colbs = [user.login for user in repo.get_collaborators(affiliation="outside")] - print(f"External colloborators added: {final_colbs}") - - close_comment = ( - f"A repository for this submission has been created: {repo.html_url} and it will be published to Flathub in 4-5 hours.", - "\n", - f"You will receive an [invite]({repo.html_url}/invitations) to be a collaborator to the above repository. Please make sure to enable 2FA on GitHub and accept the invite within one week.", - "\n", - "Please go through the [App maintenance guide](https://docs.flathub.org/docs/for-app-authors/maintenance/) if you have never maintained an app on Flathub before.", - "\n", - "If you're the original developer (or an authorized party), please [verify your app](https://docs.flathub.org/docs/for-app-authors/verification) to let users know it's coming from you.", - "\n", - "Please follow the [Flathub blog](https://docs.flathub.org/blog) for the latest announcements.", - "\n", - "Thanks!", - ) - - print("Closing the pull request") - pr.create_issue_comment("\n".join(close_comment)) - pr.edit(state="closed") - - -if __name__ == "__main__": - main() diff --git a/.github/actions/merge/requirements.in b/.github/actions/merge/requirements.in deleted file mode 100644 index cc15727..0000000 --- a/.github/actions/merge/requirements.in +++ /dev/null @@ -1,4 +0,0 @@ -gql[requests] -pygit2 -PyGithub -PyYAML diff --git a/.github/actions/merge/requirements.txt b/.github/actions/merge/requirements.txt deleted file mode 100644 index 73c3970..0000000 --- a/.github/actions/merge/requirements.txt +++ /dev/null @@ -1,65 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.12 -# by the following command: -# -# pip-compile .github/actions/merge/requirements.in -# -anyio==4.4.0 - # via gql -backoff==2.2.1 - # via gql -certifi==2024.7.4 - # via requests -cffi==1.16.0 - # via - # cryptography - # pygit2 - # pynacl -charset-normalizer==3.3.2 - # via requests -cryptography==44.0.1 - # via pyjwt -deprecated==1.2.14 - # via pygithub -gql[requests]==3.5.0 - # via -r requirements.in -graphql-core==3.2.3 - # via gql -idna==3.7 - # via - # anyio - # requests - # yarl -multidict==6.0.5 - # via yarl -pycparser==2.22 - # via cffi -pygit2==1.15.0 - # via -r requirements.in -pygithub==2.3.0 - # via -r requirements.in -pyjwt[crypto]==2.8.0 - # via pygithub -pynacl==1.5.0 - # via pygithub -pyyaml==6.0.1 - # via -r requirements.in -requests==2.32.4 - # via - # gql - # pygithub - # requests-toolbelt -requests-toolbelt==1.0.0 - # via gql -sniffio==1.3.1 - # via anyio -typing-extensions==4.12.2 - # via pygithub -urllib3==2.2.2 - # via - # pygithub - # requests -wrapt==1.16.0 - # via deprecated -yarl==1.9.4 - # via gql diff --git a/.github/workflows/build-merge.yml b/.github/workflows/build-merge.yml deleted file mode 100644 index be29b62..0000000 --- a/.github/workflows/build-merge.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: 'Build image for merge workflow' - -on: - push: - branches: master - paths: - - ".github/actions/merge/*" - - .github/workflows/merge.yml - - .github/workflows/build-merge.yml - workflow_dispatch: - -jobs: - docker: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - # 4.2.2 - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - with: - persist-credentials: false - - - name: Set up Docker Buildx - # 3.10.0 - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 - - - name: Login to ghcr.io - # 3.4.0 - uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and push - id: docker_build - # 6.15.0 - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 - with: - context: .github/actions/merge - file: .github/actions/merge/Dockerfile - tags: ghcr.io/flathub/actions/merge:latest - push: true - cache-from: type=gha - cache-to: type=gha,mode=max From 0043ab009a1d0d1df7ed7ed24629303f6c2b13dc Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 12:05:11 +0530 Subject: [PATCH 251/319] ci: Drop cache from setup-python --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4064e51..3696e5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,9 +23,6 @@ jobs: # 5.4.0 - uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 - with: - python-version: '3.13' - cache: 'pip' - name: Install dependencies run: pip install --user 'ruff==0.11.0' From 02e0fec0279b4847db9a034beaa108c9d8c5b56d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 12:23:17 +0530 Subject: [PATCH 252/319] merge: Add concurrency --- .github/workflows/merge.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 09c04a3..fc71881 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -5,6 +5,10 @@ on: types: - created +concurrency: + group: merge-${{ github.event.issue.number }} + cancel-in-progress: true + jobs: merge: runs-on: ubuntu-latest From 84b9bc02f751e6d2944d886008c58303090359ad Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 18:48:29 +0530 Subject: [PATCH 253/319] pr-check: Check for one required item --- .github/workflows/pr-check.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 7edf1f1..d0c243a 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -45,6 +45,7 @@ jobs: json=$(gh pr view "$PR_NUM" --json body,title -q '{body: .body, title: .title}') PR_BODY=$(echo "$json" | jq -r .body) PR_TITLE=$(echo "$json" | jq -r .title) + NORMALIZED_PR_BODY=$(printf "%s\n" "$PR_BODY" | tr -d '\r') unset "$PR_TITLE" export PR_TITLE="$PR_TITLE" @@ -109,6 +110,13 @@ jobs: BLOCKED=1 fi + REQUIRED_ITEM="I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them." + REQUIRED_CHECKED=$(printf "%s\n" "$NORMALIZED_PR_BODY" | grep -Fi "[x] $REQUIRED_ITEM" || true) + + if [ -z "$REQUIRED_CHECKED" ]; then + BLOCKED=1 + fi + echo "BLOCKED is set to $BLOCKED" if [ "$BLOCKED" -eq 0 ] && ! label_exists_any "awaiting-changes" "awaiting-upstream" "blocked" "reviewed-waiting"; then From 8c43270b1ece6c8f2e9c63de4351a4c359785ea3 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 19:03:10 +0530 Subject: [PATCH 254/319] Revert "merge: Add concurrency" This reverts commit 02e0fec0279b4847db9a034beaa108c9d8c5b56d. --- .github/workflows/merge.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index fc71881..09c04a3 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -5,10 +5,6 @@ on: types: - created -concurrency: - group: merge-${{ github.event.issue.number }} - cancel-in-progress: true - jobs: merge: runs-on: ubuntu-latest From f50ed62dc5a0b3fe246fabf941a9ba435f7c0002 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 11 Jun 2025 19:49:00 +0530 Subject: [PATCH 255/319] merge: Use v1.0.0 tag --- .github/workflows/merge.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 09c04a3..2fb8266 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,6 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - - uses: flathub-infra/merge-action@main + # 1.0.0 + - uses: flathub-infra/merge-action@47cee166aa76dc56fb52f7108f985559dc99f0e5 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From e27ce10c6efa7cbcb210e1753922a967a17df565 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 15 Jun 2025 06:29:31 +0530 Subject: [PATCH 256/319] merge: Update to 1.0.1 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 2fb8266..0c60b3d 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.0 - - uses: flathub-infra/merge-action@47cee166aa76dc56fb52f7108f985559dc99f0e5 + # 1.0.1 + - uses: flathub-infra/merge-action@0df961887a9ef7e74a05dd077c9135d743674ca0 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From 88c3d1ef60197805ddf865ac96390550ae26670b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 16 Jun 2025 11:40:51 +0530 Subject: [PATCH 257/319] merge: Update to 1.0.2 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 0c60b3d..1fc6900 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.1 - - uses: flathub-infra/merge-action@0df961887a9ef7e74a05dd077c9135d743674ca0 + # 1.0.2 + - uses: flathub-infra/merge-action@04429da535ba042b6dcd177675aafd63753cf780 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From c4cf63cc26f8d69919c9ad1785460d1ea23ad80e Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 16 Jun 2025 12:01:41 +0530 Subject: [PATCH 258/319] merge: Update to v1.0.3 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 1fc6900..92aef00 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.2 - - uses: flathub-infra/merge-action@04429da535ba042b6dcd177675aafd63753cf780 + # 1.0.3 + - uses: flathub-infra/merge-action@eb50b94c17afa1f88743c59ed4c3d4d6d4ba9165 with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From 7872c290bce3fdf27caaebe9cf7bea9d03f2a256 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 16 Jun 2025 14:25:03 +0530 Subject: [PATCH 259/319] merge: Update to v1.0.4 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 92aef00..ac4deb7 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.3 - - uses: flathub-infra/merge-action@eb50b94c17afa1f88743c59ed4c3d4d6d4ba9165 + # 1.0.4 + - uses: flathub-infra/merge-action@67e97f6c6fc927bc9402d185110453bff865121b with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From 17f3ef8c945fad5f10ff7f03cb3754b94a2bd39f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 17 Jun 2025 07:28:33 +0530 Subject: [PATCH 260/319] pr-check: Match labels exactly --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index d0c243a..2f7b5e7 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -76,7 +76,7 @@ jobs: label_exists_any() { for label in "$@"; do - if echo "$PR_LABELS" | grep -Fq "$label"; then + if echo "$PR_LABELS" | grep -Fxq "$label"; then return 0 fi done From 244a839102acf67173da6cce08de88960b942a18 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 17 Jun 2025 21:53:54 +0530 Subject: [PATCH 261/319] merge: Update to v1.0.5 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index ac4deb7..85da2ce 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.4 - - uses: flathub-infra/merge-action@67e97f6c6fc927bc9402d185110453bff865121b + # 1.0.5 + - uses: flathub-infra/merge-action@079048393d2fbf7653e9fb133df713eb8022360b with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From da54e0ef4c42a7ed32fe99addc28ef35b8140837 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 17:30:27 +0530 Subject: [PATCH 262/319] pr-template: Change screenrecord to video --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3e749d5..e5da308 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -9,7 +9,7 @@ - [ ] Please describe the application briefly. < Please insert the description here > -- [ ] Please attach or link a screenrecord showcasing the application on Linux using the Flatpak. < Please insert the screenrecord link/attachment here > +- [ ] Please attach a video showcasing the application on Linux using the Flatpak. < Please insert the video here > - [ ] The Flatpak ID follows all the rules listed in the [Application ID requirements][appid]. - [ ] I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them. - [ ] I am an _(please keep whichever is applicable and remove the rest)_ author/developer/upstream contributor to the project. From 0d047e9c3d9e15e1ca17e37193bc844e7ccbc2b1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 17:29:41 +0530 Subject: [PATCH 263/319] stale: Exclude blocked issues --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 1945a5b..85c999e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -26,7 +26,7 @@ jobs: days-before-stale: 183 days-before-close: 7 any-of-issue-labels: quality-guidelines - any-of-pr-labels: awaiting-changes,blocked,work-in-progress,awaiting-upstream + any-of-pr-labels: awaiting-changes,work-in-progress,awaiting-upstream remove-stale-when-updated: true exempt-issue-labels: leave-open exempt-pr-labels: leave-open From 79b58eed22b01635d6d0e451f4d72f67a47d5900 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 17:35:23 +0530 Subject: [PATCH 264/319] Add separate stale workflow for blocked PRs --- .github/workflows/stale-blocked.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 .github/workflows/stale-blocked.yml diff --git a/.github/workflows/stale-blocked.yml b/.github/workflows/stale-blocked.yml new file mode 100644 index 0000000..64fa08d --- /dev/null +++ b/.github/workflows/stale-blocked.yml @@ -0,0 +1,29 @@ +name: "Close stale blocked PRs" +on: + schedule: + - cron: "0 0 * * 4" + workflow_dispatch: + +jobs: + stale: + permissions: + pull-requests: write + runs-on: ubuntu-latest + steps: + # 9.1.0 + - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-pr-message: |- + This pull request has not received any updates and it will be + automatically closed in 7 days. Please comment or reopen if + necessary. + days-before-stale: -1 + days-before-close: -1 + days-before-pr-stale: 30 + days-before-pr-close: 7 + any-of-pr-labels: blocked + remove-pr-stale-when-updated: true + exempt-pr-labels: leave-open + operations-per-run: 200 + ascending: true From e3130bd53a404f355536749bf74ec81c6b61d624 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 17:37:26 +0530 Subject: [PATCH 265/319] stale: Update wording --- .github/workflows/stale.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 85c999e..84d6440 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -16,11 +16,11 @@ jobs: with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: |- - This hasn't received any updates in 6 months and will be + This issue has not received any updates and it will be automatically closed in 7 days. Please comment or reopen if necessary. stale-pr-message: |- - This hasn't received any updates in 6 months and will be + This pull request has not received any updates and it will be automatically closed in 7 days. Please comment or reopen if necessary. days-before-stale: 183 From 5169de389319b3a506f8a8d79b6f141308876d29 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 18:29:15 +0530 Subject: [PATCH 266/319] pr-check: Ignore PRs with stale label --- .github/workflows/pr-check.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 2f7b5e7..de2eb98 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -18,12 +18,16 @@ jobs: steps: - name: Fetch recent PR numbers run: | - prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,updatedAt,isDraft \ - | jq -r '[.[] - | select(.isDraft == false - and .updatedAt >= (now - (2 * 24 * 60 * 60) | todate)) - | .number] - | .[]') + prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,updatedAt,isDraft,labels \ + | jq -r '[. + [] + | select( + .isDraft == false + and .updatedAt >= (now - (2 * 24 * 60 * 60) | todate) + and (all(.labels[].name; . != "Stale") or (.labels == [])) + ) + | .number + ] | .[]') prs_list=$(printf '%s\n' $prs_raw | head -30 | paste -sd "," -) echo "PR_LIST=$prs_list" >> "$GITHUB_ENV" env: From e7845b960e2ff62d1f52d7aa82d0a143fa110fbf Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 18:30:51 +0530 Subject: [PATCH 267/319] stale-blocked: Don't remove stale on update --- .github/workflows/stale-blocked.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-blocked.yml b/.github/workflows/stale-blocked.yml index 64fa08d..3389db2 100644 --- a/.github/workflows/stale-blocked.yml +++ b/.github/workflows/stale-blocked.yml @@ -23,7 +23,7 @@ jobs: days-before-pr-stale: 30 days-before-pr-close: 7 any-of-pr-labels: blocked - remove-pr-stale-when-updated: true + remove-pr-stale-when-updated: false exempt-pr-labels: leave-open operations-per-run: 200 ascending: true From f5b3217b5d3ee0b2207c409958e1e4a9098a827f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Thu, 19 Jun 2025 18:33:35 +0530 Subject: [PATCH 268/319] stale-blocked: Move the schedule a few days up --- .github/workflows/stale-blocked.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-blocked.yml b/.github/workflows/stale-blocked.yml index 3389db2..8c5b5f7 100644 --- a/.github/workflows/stale-blocked.yml +++ b/.github/workflows/stale-blocked.yml @@ -1,7 +1,7 @@ name: "Close stale blocked PRs" on: schedule: - - cron: "0 0 * * 4" + - cron: "0 0 * * 6" workflow_dispatch: jobs: From b665f2050d626ff2ed90c2221f07c602ceb2e5b6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 28 Jun 2025 07:18:29 +0530 Subject: [PATCH 269/319] merge: Update to 1.0.6 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 85da2ce..6cd7df5 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.5 - - uses: flathub-infra/merge-action@079048393d2fbf7653e9fb133df713eb8022360b + # 1.0.6 + - uses: flathub-infra/merge-action@8309eb7e763b1ffbd7406ccd6b6f76a8f357dc0f with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From 0397fee1be77757ccd9b6b9017df2477f391b6cd Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 30 Jun 2025 08:47:26 +0530 Subject: [PATCH 270/319] pr-check: Remove pr-check-blocked label when resolved --- .github/workflows/pr-check.yml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index de2eb98..692a791 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -123,9 +123,15 @@ jobs: echo "BLOCKED is set to $BLOCKED" - if [ "$BLOCKED" -eq 0 ] && ! label_exists_any "awaiting-changes" "awaiting-upstream" "blocked" "reviewed-waiting"; then - echo "Marking as awaiting-review" - gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "pr-check-blocked" || true + if [ "$BLOCKED" -eq 0 ]; then + if label_exists_any "pr-check-blocked"; then + echo "Removing pr-check-blocked label" + gh pr edit "$PR_NUM" --remove-label "pr-check-blocked" || true + fi + if ! label_exists_any "awaiting-changes" "awaiting-upstream" "blocked" "reviewed-waiting"; then + echo "Marking as awaiting-review" + gh pr edit "$PR_NUM" --add-label "awaiting-review" --remove-label "pr-check-blocked" || true + fi start_build elif [ "$BLOCKED" -eq 1 ]; then echo "Marking as blocked" From cd3114e686d028b4fbb9f508b1c101a59d301a4b Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 30 Jun 2025 08:56:45 +0530 Subject: [PATCH 271/319] pr-check: Set a cutoff date --- .github/workflows/pr-check.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 692a791..e3938b7 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -18,11 +18,13 @@ jobs: steps: - name: Fetch recent PR numbers run: | - prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,updatedAt,isDraft,labels \ - | jq -r '[. + CUTOFF_DATE="2025-05-25T00:00:00Z" + prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,createdAt,updatedAt,isDraft,labels \ + | jq -r --arg cutoff "$CUTOFF_DATE" '[. [] | select( .isDraft == false + and .createdAt >= $cutoff and .updatedAt >= (now - (2 * 24 * 60 * 60) | todate) and (all(.labels[].name; . != "Stale") or (.labels == [])) ) From a4dbffd210ce3cf6194b5c1771ba93a6a046159f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 30 Jun 2025 08:57:26 +0530 Subject: [PATCH 272/319] pr-check: Bump schedule to every 5 hours --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index e3938b7..6b534d1 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -3,7 +3,7 @@ name: Check PRs on: workflow_dispatch: schedule: - - cron: '0 * * * *' + - cron: '0 */5 * * *' concurrency: group: ${{ github.workflow }}-${{ github.ref }} From 71a8e811a91039ecb6c6fe846b89566eb532b4b0 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 1 Jul 2025 19:19:59 +0530 Subject: [PATCH 273/319] stale-blocked: Make the close within period exactly 30 days --- .github/workflows/stale-blocked.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale-blocked.yml b/.github/workflows/stale-blocked.yml index 8c5b5f7..e4c9493 100644 --- a/.github/workflows/stale-blocked.yml +++ b/.github/workflows/stale-blocked.yml @@ -20,7 +20,7 @@ jobs: necessary. days-before-stale: -1 days-before-close: -1 - days-before-pr-stale: 30 + days-before-pr-stale: 23 days-before-pr-close: 7 any-of-pr-labels: blocked remove-pr-stale-when-updated: false From de6eed11378daa48eb67c118cb01e310540d8bb1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 1 Jul 2025 20:02:35 +0530 Subject: [PATCH 274/319] stale-blocked: Ignore updates and handle pr-check-blocked too --- .github/workflows/stale-blocked.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stale-blocked.yml b/.github/workflows/stale-blocked.yml index e4c9493..f98a202 100644 --- a/.github/workflows/stale-blocked.yml +++ b/.github/workflows/stale-blocked.yml @@ -22,8 +22,9 @@ jobs: days-before-close: -1 days-before-pr-stale: 23 days-before-pr-close: 7 - any-of-pr-labels: blocked - remove-pr-stale-when-updated: false + any-of-pr-labels: blocked,pr-check-blocked + remove-stale-when-updated: false exempt-pr-labels: leave-open operations-per-run: 200 ascending: true + ignore-updates: true From 12d28f5879cacbfe1356e22d631a11ed4d417b2c Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 08:24:21 +0530 Subject: [PATCH 275/319] x-checker: Bump to 4-ish hours --- .github/workflows/external-data-checker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/external-data-checker.yml b/.github/workflows/external-data-checker.yml index e7512e6..aa9a9d3 100644 --- a/.github/workflows/external-data-checker.yml +++ b/.github/workflows/external-data-checker.yml @@ -12,7 +12,7 @@ concurrency: jobs: flathub-data-checker-global: runs-on: ubuntu-latest - timeout-minutes: 120 + timeout-minutes: 230 steps: # 4.2.2 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 From de20eea7ffb7472eadc159c49827a74ce8fe5ba1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 08:27:29 +0530 Subject: [PATCH 276/319] archive_eol: Reduce activity threshold to 13 weeks --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index b6fc707..575f704 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -132,7 +132,7 @@ def main() -> None: return earliest = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta( - weeks=60 + weeks=13 ) count = 0 while count < len(eols): From 59dccb1d1346bf8aa1fa7249be8add9cc96152bf Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 08:52:36 +0530 Subject: [PATCH 277/319] archive_eol: Lowercase everything before passing to GitHub GH is case insensitive but ref IDs aren't so if a rename was EOL-ed eg. `org.gnome.chess` -> `org.gnome.Chess` and the exclusion had only one of them, the repo would still get EOL-ed as both resolves to the same github repo --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 575f704..888133e 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -126,7 +126,7 @@ def main() -> None: beta = get_eol_refs("x86_64", "flathub-beta") | get_eol_refs( "aarch64", "flathub-beta" ) - eols = list((stable | beta) - excludes) + eols = {x.lower() for x in (stable | beta)} - {x.lower() for x in excludes} if not eols: return From fa40371e6d3c37f6758b42cf4fff57774160f42a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 08:56:44 +0530 Subject: [PATCH 278/319] archive_eol: Add some more exclusions --- .github/scripts/archive_eol.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 888133e..e9982dd 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -86,6 +86,9 @@ def main() -> None: "org.freedesktop.LinuxAudio.Plugins.Sorcer", "org.freedesktop.LinuxAudio.Plugins.ADLplug", "org.freedesktop.LinuxAudio.Plugins.Fabla", + "org.freedesktop.LinuxAudio.Plugins.Geonkick", + "org.freedesktop.LinuxAudio.Plugins.Helm", + "org.freedesktop.LinuxAudio.Plugins.Dexed", # 1.6 branch is EOL "org.freedesktop.Sdk.Extension.golang", # 19.08, 20.08, 21.08 are EOL @@ -120,6 +123,7 @@ def main() -> None: "org.videolan.VLC.Plugin.bdj", # 3-1.6, 3-18.08 is EOL "org.videolan.VLC.Plugin.fdkaac", + "org.kde.PlatformTheme.QGnomePlatform", } stable = get_eol_refs("x86_64", "flathub") | get_eol_refs("aarch64", "flathub") From 302c3a10ae19b22de9d6539a6fbfc0f9d2f47a5a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 08:59:19 +0530 Subject: [PATCH 279/319] archive_eol: Convert to list --- .github/scripts/archive_eol.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index e9982dd..e630118 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -130,7 +130,7 @@ def main() -> None: beta = get_eol_refs("x86_64", "flathub-beta") | get_eol_refs( "aarch64", "flathub-beta" ) - eols = {x.lower() for x in (stable | beta)} - {x.lower() for x in excludes} + eols = list({x.lower() for x in (stable | beta)} - {x.lower() for x in excludes}) if not eols: return From af3316670d2fe7d3a5a67a729d0517be6b65e05f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 2 Jul 2025 09:06:29 +0530 Subject: [PATCH 280/319] archive_eol: Add some more exclusions --- .github/scripts/archive_eol.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index e630118..5adefb7 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -124,6 +124,10 @@ def main() -> None: # 3-1.6, 3-18.08 is EOL "org.videolan.VLC.Plugin.fdkaac", "org.kde.PlatformTheme.QGnomePlatform", + "com.github.wwmm.easyeffects", + "com.yubico.yubioath", + "com.icanblink.blink", + "com.github.wwmm.pulseeffects", } stable = get_eol_refs("x86_64", "flathub") | get_eol_refs("aarch64", "flathub") From f6ed3fbbcf0087abfe15cda778e3b74a718bd51d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 6 Jul 2025 09:39:59 +0530 Subject: [PATCH 281/319] x-checker: Just print the folder name being deleted --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 125c089..d01fee1 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -13,7 +13,7 @@ cd flathub || exit gh repo list flathub --visibility public -L 8000 --json url --json isArchived --jq '.[] | select(.isArchived == false)|.url' | parallel "git clone --depth 1 {}" echo "==> Deleting inactive repos" -curl -s https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do test -d "$folder" && rm -rfv "$folder" || true; done +curl -s https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do test -d "$folder" && echo "==> Deleting $folder" && rm -rf "$folder" || true; done mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do From bd6b2547db3453bbef9471ddf87f374a2786cf04 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 6 Jul 2025 09:43:33 +0530 Subject: [PATCH 282/319] x-checker: Handle manual exclusion --- .../actions/flatpak-external-data-checker/entrypoint.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index d01fee1..6c43c1e 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -12,8 +12,15 @@ mkdir flathub cd flathub || exit gh repo list flathub --visibility public -L 8000 --json url --json isArchived --jq '.[] | select(.isArchived == false)|.url' | parallel "git clone --depth 1 {}" + echo "==> Deleting inactive repos" -curl -s https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/inactive.txt | while read folder; do test -d "$folder" && echo "==> Deleting $folder" && rm -rf "$folder" || true; done +base_url="https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/" +for file in inactive.txt manual_inactive.txt; do + curl -s "${base_url}${file}" | while read folder; do + test -d "$folder" && echo "==> Deleting $folder" && rm -rf "$folder" + done +done + mapfile -t checker_apps < <( grep -rl -E 'extra-data|x-checker-data|\.AppImage' | cut -d/ -f1 | sort -u | shuf ) for repo in "${checker_apps[@]}"; do From 3f65a573befdb4225976b17473d57c34bcb01698 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 6 Jul 2025 09:47:18 +0530 Subject: [PATCH 283/319] x-checker: Restore pipe to true --- .github/actions/flatpak-external-data-checker/entrypoint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/flatpak-external-data-checker/entrypoint.sh b/.github/actions/flatpak-external-data-checker/entrypoint.sh index 6c43c1e..c50578d 100755 --- a/.github/actions/flatpak-external-data-checker/entrypoint.sh +++ b/.github/actions/flatpak-external-data-checker/entrypoint.sh @@ -17,7 +17,7 @@ echo "==> Deleting inactive repos" base_url="https://raw.githubusercontent.com/flathub-infra/flathub-inactive-repo-list/refs/heads/main/" for file in inactive.txt manual_inactive.txt; do curl -s "${base_url}${file}" | while read folder; do - test -d "$folder" && echo "==> Deleting $folder" && rm -rf "$folder" + test -d "$folder" && echo "==> Deleting $folder" && rm -rf "$folder" || true done done From ec85636219e996bb2a53a59588b500b1a52d1e89 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 12 Jul 2025 23:02:26 +0530 Subject: [PATCH 284/319] pr-check: Partial match for required checkliste item --- .github/workflows/pr-check.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 6b534d1..0ad4197 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -116,10 +116,11 @@ jobs: BLOCKED=1 fi - REQUIRED_ITEM="I have read and followed all the [Submission requirements][reqs] and the [Submission guide][reqs2] and I agree to them." + REQUIRED_ITEM="I have read and followed all the [Submission requirements]" REQUIRED_CHECKED=$(printf "%s\n" "$NORMALIZED_PR_BODY" | grep -Fi "[x] $REQUIRED_ITEM" || true) if [ -z "$REQUIRED_CHECKED" ]; then + echo "Required checklist not found in PR body" BLOCKED=1 fi From ee084337aa067463054e85fb22e83960fe09ddf6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Wed, 30 Jul 2025 18:55:17 +0530 Subject: [PATCH 285/319] pr-check: Auto lock blocked PRs with too many failing builds --- .github/workflows/pr-check.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 0ad4197..11baec4 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -21,7 +21,7 @@ jobs: CUTOFF_DATE="2025-05-25T00:00:00Z" prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,createdAt,updatedAt,isDraft,labels \ | jq -r --arg cutoff "$CUTOFF_DATE" '[. - [] + [] | select( .isDraft == false and .createdAt >= $cutoff @@ -149,6 +149,14 @@ jobs: echo "Nothing to do" start_build fi + if [ "$BLOCKED" -eq 1 ] \ + && label_exists_any "pr-check-blocked" "blocked" \ + && ! comment_exists_any "$BUILD_SUCCESS_COMMENT" \ + && [ "$(echo "$PR_COMMENTS" | grep -E -c 'Test build.*failed')" -gt 10 ]; then + echo "PR is blocked and too many failing builds. Locking" + gh pr comment "$PR_NUM" --body "$LOCKED_COMMENT" + gh pr lock "$PR_NUM" || true + fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -168,4 +176,9 @@ jobs: request title is `Add $FLATPAK_ID` and that all [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) in the pull request body are marked as complete. + LOCKED_COMMENT: > + This pull request is marked as blocked and has too many + builds failing. Locking this PR temporarily. Please build + it locally following the instructions and push the relevant + changes first. REVIEW_COMMENT_PARTIAL: "This pull request is temporarily marked as blocked as some" From 3ad48f38403b98773635aecfccf62ef8f7cd7be7 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 06:55:51 +0530 Subject: [PATCH 286/319] Add script to get domain from appid --- .github/scripts/domain_from_appid.py | 41 ++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/scripts/domain_from_appid.py diff --git a/.github/scripts/domain_from_appid.py b/.github/scripts/domain_from_appid.py new file mode 100644 index 0000000..3e49ff9 --- /dev/null +++ b/.github/scripts/domain_from_appid.py @@ -0,0 +1,41 @@ +import sys +from publicsuffixlist import PublicSuffixList + +CODE_HOSTS = ( + "io.github.", + "io.frama.", + "io.gitlab.", + "page.codeberg.", + "io.sourceforge.", + "net.sourceforge.", + "org.gnome.gitlab.", + "org.freedesktop.gitlab.", + "site.srht.", +) + +def demangle(name: str) -> str: + if name.startswith("_"): + name = name[1:] + return name.replace("_", "-") + +def get_domain(appid: str) -> str | None: + if appid.startswith(CODE_HOSTS) or appid.count(".") < 2: + return None + + if appid.startswith("org.gnome.") and not appid.startswith("org.gnome.gitlab."): + return "gnome.org" + elif appid.startswith("org.kde."): + return "kde.org" + elif appid.startswith("org.freedesktop.") and not appid.startswith("org.freedesktop.gitlab."): + return "freedesktop.org" + else: + fqdn = ".".join(reversed(appid.split("."))).lower() + psl = PublicSuffixList() + if psl.is_private(fqdn): + return demangle(psl.privatesuffix(fqdn)) + else: + return ".".join(reversed([demangle(i) for i in appid.split(".")[:-1]])).lower() + +if __name__ == "__main__": + appid = sys.argv[1] + print(get_domain(appid)) From d55ea885fa7fcf09371c7dae697dbad2dde5b70a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 07:10:16 +0530 Subject: [PATCH 287/319] pr-check: Add automation to post calculated domain --- .github/workflows/pr-check.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 11baec4..84984c7 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -16,6 +16,10 @@ jobs: permissions: pull-requests: write steps: + - name: Install deps + run: | + pip install 'publicsuffixlist==1.0.2.20250802' + - name: Fetch recent PR numbers run: | CUTOFF_DATE="2025-05-25T00:00:00Z" @@ -101,6 +105,17 @@ jobs: if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" BLOCKED=1 + else + APPID=$(echo "$PR_TITLE" | sed -E 's/^[[:space:]]*[Aa]dd[[:space:]]+//') + DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$APPID") + if [ "$DOMAIN" != "None" ] && [ -n "$DOMAIN" ]; then + echo "Domain is: $DOMAIN" + if ! comment_exists "$DOMAIN_COMMENT_PARTIAL"; then + echo "Did not find domain comment, commenting" + DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. Please comment if incorrect." + gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" + fi + fi fi CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- ?\[[xX]\] [A-Za-z]+' || true) @@ -162,6 +177,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} SCRIPT_URL: https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/scripts/validate.py + DOMAIN_SCRIPT_URL: https://raw.githubusercontent.com/flathub/flathub/refs/heads/master/.github/scripts/domain_from_appid.py BUILD_SUCCESS_COMMENT: "[Test build succeeded]" BUILD_START_COMMENT: | Starting a test build of the submission. Please fix any @@ -182,3 +198,4 @@ jobs: it locally following the instructions and push the relevant changes first. REVIEW_COMMENT_PARTIAL: "This pull request is temporarily marked as blocked as some" + DOMAIN_COMMENT_PARTIAL: "The domain to be used for verification is" From a58741e451590b49ec2a6f74e033a0191a2ca902 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 07:14:32 +0530 Subject: [PATCH 288/319] pr-check: Match the full comment for domain comment --- .github/workflows/pr-check.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 84984c7..91e7162 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -75,6 +75,11 @@ jobs: echo "$PR_COMMENTS" | grep -Fq "$comment" } + comment_exists_full() { + local comment="$1" + echo "$PR_COMMENTS" | grep -Fxq "$comment" + } + comment_exists_any() { for comment in "$@"; do if echo "$PR_COMMENTS" | grep -Fq "$comment"; then @@ -110,9 +115,9 @@ jobs: DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$APPID") if [ "$DOMAIN" != "None" ] && [ -n "$DOMAIN" ]; then echo "Domain is: $DOMAIN" - if ! comment_exists "$DOMAIN_COMMENT_PARTIAL"; then + DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. Please comment if incorrect." + if ! comment_exists_full "$DOMAIN_COMMENT"; then echo "Did not find domain comment, commenting" - DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. Please comment if incorrect." gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" fi fi From c71ad0d7b9144ddfc0b2cf2536a243ab9e5f8964 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 07:34:20 +0530 Subject: [PATCH 289/319] pr-check: Remove awaiting-review when review comments are/were posted --- .github/workflows/pr-check.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 91e7162..0776394 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -68,6 +68,9 @@ jobs: PR_LABELS="$(gh pr view "$PR_NUM" --json labels -q '.labels[].name')" + PR_THREAD_COUNT=$(gh api repos/$GH_REPO/pulls/$PR_NUM/comments \ + --jq '[.[] | select(.position != null)] | length') + BLOCKED=0 comment_exists() { @@ -177,6 +180,10 @@ jobs: gh pr comment "$PR_NUM" --body "$LOCKED_COMMENT" gh pr lock "$PR_NUM" || true fi + if label_exists_any "awaiting-review" && [ "$PR_THREAD_COUNT" -gt 0 ]; then + echo "Has awaiting-review label and review comments, marking as awaiting-changes" + gh pr edit "$PR_NUM" --add-label "awaiting-changes" --remove-label "awaiting-review" || true + fi done env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 006286498b9717a73906e11e4298ae3c53e41c07 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 10:16:21 +0530 Subject: [PATCH 290/319] domain_from_appid: Fix the script and post more detailed comment --- .github/scripts/domain_from_appid.py | 53 ++++++++++++++++++---------- .github/workflows/pr-check.yml | 9 ++--- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/.github/scripts/domain_from_appid.py b/.github/scripts/domain_from_appid.py index 3e49ff9..5beb021 100644 --- a/.github/scripts/domain_from_appid.py +++ b/.github/scripts/domain_from_appid.py @@ -1,41 +1,56 @@ +# ONLY handle appids that need to use `org.flathub.VerifiedApps.txt` + import sys +import re from publicsuffixlist import PublicSuffixList -CODE_HOSTS = ( +LOGINS = ( + "com.github.", + "com.gitlab.", "io.github.", - "io.frama.", "io.gitlab.", - "page.codeberg.", - "io.sourceforge.", - "net.sourceforge.", "org.gnome.gitlab.", - "org.freedesktop.gitlab.", - "site.srht.", + "org.gnome.World.", + "org.gnome.design", + "org.kde.", + "org.gnome.", ) + def demangle(name: str) -> str: if name.startswith("_"): name = name[1:] return name.replace("_", "-") -def get_domain(appid: str) -> str | None: - if appid.startswith(CODE_HOSTS) or appid.count(".") < 2: - return None - if appid.startswith("org.gnome.") and not appid.startswith("org.gnome.gitlab."): - return "gnome.org" - elif appid.startswith("org.kde."): - return "kde.org" - elif appid.startswith("org.freedesktop.") and not appid.startswith("org.freedesktop.gitlab."): - return "freedesktop.org" +def get_domain(appid: str) -> str | None: + if appid.startswith(LOGINS) or appid.count(".") < 2: + return None + elif appid.startswith( + ("io.frama.", "page.codeberg.", "io.sourceforge.", "net.sourceforge.") + ): + tld, domain, name = appid.split(".")[0:3] + name = demangle(name) + if domain == "sourceforge": + return f"{name}.{domain}.io".lower() + else: + return f"{name}.{domain}.{tld}".lower() + elif appid.startswith(("io.sourceforge.", "net.sourceforge.")): + [tld, domain, projectname] = appid.split(".")[0:3] + projectname = demangle(projectname) + return f"{projectname}.{domain}.io".lower() else: fqdn = ".".join(reversed(appid.split("."))).lower() psl = PublicSuffixList() if psl.is_private(fqdn): return demangle(psl.privatesuffix(fqdn)) else: - return ".".join(reversed([demangle(i) for i in appid.split(".")[:-1]])).lower() + return ".".join( + reversed([demangle(i) for i in appid.split(".")[:-1]]) + ).lower() + if __name__ == "__main__": - appid = sys.argv[1] - print(get_domain(appid)) + # PR title as input "(Aa)dd com.foo.bar" + appid = re.sub(r"^\s*add\s+", "", sys.argv[1], flags=re.IGNORECASE) + print(get_domain(appid).strip()) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 0776394..cfbd510 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -114,11 +114,12 @@ jobs: echo "PR title validation failed" BLOCKED=1 else - APPID=$(echo "$PR_TITLE" | sed -E 's/^[[:space:]]*[Aa]dd[[:space:]]+//') - DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$APPID") - if [ "$DOMAIN" != "None" ] && [ -n "$DOMAIN" ]; then + DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$PR_TITLE") + if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then echo "Domain is: $DOMAIN" - DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. Please comment if incorrect." + VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" + VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this." + DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." if ! comment_exists_full "$DOMAIN_COMMENT"; then echo "Did not find domain comment, commenting" gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" From 35e4389109ca85a8d2f8b154ab1a30d4ad11d285 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 9 Aug 2025 10:19:26 +0530 Subject: [PATCH 291/319] domain_from_appid: Return none string --- .github/scripts/domain_from_appid.py | 4 ++-- .github/workflows/pr-check.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/scripts/domain_from_appid.py b/.github/scripts/domain_from_appid.py index 5beb021..a4b01eb 100644 --- a/.github/scripts/domain_from_appid.py +++ b/.github/scripts/domain_from_appid.py @@ -23,9 +23,9 @@ def demangle(name: str) -> str: return name.replace("_", "-") -def get_domain(appid: str) -> str | None: +def get_domain(appid: str) -> str: if appid.startswith(LOGINS) or appid.count(".") < 2: - return None + return "None" elif appid.startswith( ("io.frama.", "page.codeberg.", "io.sourceforge.", "net.sourceforge.") ): diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index cfbd510..f384b2d 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -118,7 +118,7 @@ jobs: if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then echo "Domain is: $DOMAIN" VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" - VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this." + VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this" DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." if ! comment_exists_full "$DOMAIN_COMMENT"; then echo "Did not find domain comment, commenting" From fe41a6c84b5d6e30deaaad815ab7b483fa33674a Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 10 Aug 2025 06:34:40 +0530 Subject: [PATCH 292/319] domain_from_appid: Ignore extensions and baseapp these don't get verified --- .github/scripts/domain_from_appid.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/.github/scripts/domain_from_appid.py b/.github/scripts/domain_from_appid.py index a4b01eb..db838e7 100644 --- a/.github/scripts/domain_from_appid.py +++ b/.github/scripts/domain_from_appid.py @@ -24,8 +24,30 @@ def demangle(name: str) -> str: def get_domain(appid: str) -> str: + ret_none = "None" + if appid.startswith(LOGINS) or appid.count(".") < 2: - return "None" + return ret_none + + if appid.endswith(".BaseApp"): + return ret_none + + # correctly checking for extension requires checking out + # untrusted code from PRs so rely on some heuristics + + if appid.split(".")[-2].lower() in ( + "addon", + "addons", + "extension", + "extensions", + "plugin", + "plugins", + ): + return ret_none + + if appid.startswith("org.gtk.Gtk3theme."): + return ret_none + elif appid.startswith( ("io.frama.", "page.codeberg.", "io.sourceforge.", "net.sourceforge.") ): From bd86627896c3bafd238c4e126a915cd66c622a36 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 10 Aug 2025 15:58:45 +0530 Subject: [PATCH 293/319] domain_from_appid: Ignore more extension patterns --- .github/scripts/domain_from_appid.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/scripts/domain_from_appid.py b/.github/scripts/domain_from_appid.py index db838e7..4c13a85 100644 --- a/.github/scripts/domain_from_appid.py +++ b/.github/scripts/domain_from_appid.py @@ -45,7 +45,19 @@ def get_domain(appid: str) -> str: ): return ret_none - if appid.startswith("org.gtk.Gtk3theme."): + if appid.startswith( + ( + "org.freedesktop.Platform.GStreamer.", + "org.freedesktop.Platform.Icontheme.", + "org.freedesktop.Platform.VulkanLayer.", + "org.freedesktop.Sdk.Extension.", + "org.gtk.Gtk3theme.", + "org.kde.KStyle.", + "org.kde.PlatformInputContexts.", + "org.kde.PlatformTheme.", + "org.kde.WaylandDecoration.", + ) + ): return ret_none elif appid.startswith( From 01a150ae133883334ad660c9cd3c74807d19ca20 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 12 Aug 2025 16:48:28 +0530 Subject: [PATCH 294/319] merge: Update to v1.0.7 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 6cd7df5..942ff9c 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.6 - - uses: flathub-infra/merge-action@8309eb7e763b1ffbd7406ccd6b6f76a8f357dc0f + # 1.0.7 + - uses: flathub-infra/merge-action@254c47133f4f4898125389ef7533ac54ae2a19af with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From ee7425c9b1f954c9d0c456ff8a412a042171de00 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 12 Aug 2025 17:10:51 +0530 Subject: [PATCH 295/319] merge: Update to 1.0.8 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index 942ff9c..a7ca85a 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.7 - - uses: flathub-infra/merge-action@254c47133f4f4898125389ef7533ac54ae2a19af + # 1.0.8 + - uses: flathub-infra/merge-action@9b7a39db258a32c10d1686481c3fa4c827b7a53b with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From a8123f4ceb0b2cc7caa79acd0ef888bad0d292d3 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Tue, 12 Aug 2025 17:40:43 +0530 Subject: [PATCH 296/319] merge: Update to 1.0.9 --- .github/workflows/merge.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml index a7ca85a..1a3c0d9 100644 --- a/.github/workflows/merge.yml +++ b/.github/workflows/merge.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 30 if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/merge') }} steps: - # 1.0.8 - - uses: flathub-infra/merge-action@9b7a39db258a32c10d1686481c3fa4c827b7a53b + # 1.0.9 + - uses: flathub-infra/merge-action@6c25245b7ef599ac1861b2e1be84f553fd1e9bde with: token: ${{ secrets.FLATHUBBOT_TOKEN }} From ca3bac9a42753b95468e1e5427b5ac21766cd81d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 23 Aug 2025 07:53:27 +0530 Subject: [PATCH 297/319] pr-check: Don't post the domain comment until checklists are complete --- .github/workflows/pr-check.yml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index f384b2d..3ddd780 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -113,18 +113,6 @@ jobs: if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" BLOCKED=1 - else - DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$PR_TITLE") - if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then - echo "Domain is: $DOMAIN" - VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" - VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this" - DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." - if ! comment_exists_full "$DOMAIN_COMMENT"; then - echo "Did not find domain comment, commenting" - gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" - fi - fi fi CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- ?\[[xX]\] [A-Za-z]+' || true) @@ -151,6 +139,17 @@ jobs: echo "BLOCKED is set to $BLOCKED" if [ "$BLOCKED" -eq 0 ]; then + DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$PR_TITLE") + if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then + echo "Domain is: $DOMAIN" + VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" + VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this" + DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." + if ! comment_exists_full "$DOMAIN_COMMENT"; then + echo "Did not find domain comment, commenting" + gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" + fi + fi if label_exists_any "pr-check-blocked"; then echo "Removing pr-check-blocked label" gh pr edit "$PR_NUM" --remove-label "pr-check-blocked" || true From 077487c851a6e21c8c6bbf824d7d3fbe6eed3ea1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sat, 23 Aug 2025 07:54:23 +0530 Subject: [PATCH 298/319] pr-check: Run every 2 hours --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 3ddd780..b143861 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -3,7 +3,7 @@ name: Check PRs on: workflow_dispatch: schedule: - - cron: '0 */5 * * *' + - cron: '0 */2 * * *' concurrency: group: ${{ github.workflow }}-${{ github.ref }} From fb5e7cfe386e62dd8ece546af4ddaa33b76f9a29 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 31 Aug 2025 08:08:24 +0530 Subject: [PATCH 299/319] pr-check: Label draft PRs automatically --- .github/workflows/pr-check.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index b143861..4db6322 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -36,10 +36,40 @@ jobs: ] | .[]') prs_list=$(printf '%s\n' $prs_raw | head -30 | paste -sd "," -) echo "PR_LIST=$prs_list" >> "$GITHUB_ENV" + draft_prs_raw=$(gh pr list --base "new-pr" -L 50 --state open --json number,createdAt,updatedAt,isDraft,labels \ + | jq -r --arg cutoff "$CUTOFF_DATE" '[. + [] + | select( + .isDraft == true + and .createdAt >= $cutoff + and .updatedAt >= (now - (2 * 24 * 60 * 60) | todate) + and (all(.labels[].name; . != "Stale") or (.labels == [])) + ) + | .number + ] | .[]') + draft_prs_list=$(printf '%s\n' $draft_prs_raw | head -30 | paste -sd "," -) + echo "DRAFT_PR_LIST=$draft_prs_list" >> "$GITHUB_ENV" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_REPO: ${{ github.repository }} + - name: Label draft PRs + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + run: | + IFS=',' read -ra PR_NUMBERS <<< "${{ env.DRAFT_PR_LIST }}" + + if [ ${#PR_NUMBERS[@]} -eq 0 ] || [ -z "${PR_NUMBERS[0]}" ]; then + echo "No PRs found, exiting." + exit 0 + fi + + for PR_NUM in "${PR_NUMBERS[@]}"; do + echo "Checking PR https://github.com/flathub/flathub/pull/$PR_NUM" + gh pr edit "$PR_NUM" --add-label "work-in-progress" || true + done + - name: Validate PRs run: | IFS=',' read -ra PR_NUMBERS <<< "${{ env.PR_LIST }}" From 1393bb988aec743fc97e023f4dbb5cc7d4f89cd7 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 5 Sep 2025 16:56:20 +0530 Subject: [PATCH 300/319] pr-check: Don't post domain comment if pr is marked as blocked --- .github/workflows/pr-check.yml | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 4db6322..0c7f89c 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -169,15 +169,17 @@ jobs: echo "BLOCKED is set to $BLOCKED" if [ "$BLOCKED" -eq 0 ]; then - DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$PR_TITLE") - if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then - echo "Domain is: $DOMAIN" - VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" - VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this" - DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." - if ! comment_exists_full "$DOMAIN_COMMENT"; then - echo "Did not find domain comment, commenting" - gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" + if ! label_exists_any "blocked"; then + DOMAIN=$(curl -sSL "$DOMAIN_SCRIPT_URL" | python3 - "$PR_TITLE") + if [ -n "$DOMAIN" ] && [ "$DOMAIN" != "None" ]; then + echo "Domain is: $DOMAIN" + VERIF_URL="https://$DOMAIN/.well-known/org.flathub.VerifiedApps.txt" + VERIF_COMMENT="If you intend to verify this app, please confirm that you can upload $VERIF_URL. Otherwise, ignore this" + DOMAIN_COMMENT="$DOMAIN_COMMENT_PARTIAL $DOMAIN. $VERIF_COMMENT. Please comment if this incorrect." + if ! comment_exists_full "$DOMAIN_COMMENT"; then + echo "Did not find domain comment, commenting" + gh pr comment "$PR_NUM" --body "$DOMAIN_COMMENT" + fi fi fi if label_exists_any "pr-check-blocked"; then From 8793b5f80616db8620cbd413723e8693d0f3f376 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 12 Sep 2025 18:30:47 +0530 Subject: [PATCH 301/319] Mark builds from branch/* as official too --- .github/workflows/trigger-flathub-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/trigger-flathub-build.yml b/.github/workflows/trigger-flathub-build.yml index 34ead3e..48055b8 100644 --- a/.github/workflows/trigger-flathub-build.yml +++ b/.github/workflows/trigger-flathub-build.yml @@ -44,7 +44,7 @@ jobs: if [ "$FORCE_TEST" == "true" ]; then echo -e "\n\n" echo "Triggering test build from master branch of $FLATPAK_ID" - elif [ "$GIT_BRANCH" == "master" ] || [ "$GIT_BRANCH" == "beta" ]; then + elif [ "$GIT_BRANCH" == "master" ] || [ "$GIT_BRANCH" == "beta" ] || [[ "$GIT_BRANCH" == branch/* ]]; then echo -e "\n\n" echo "Triggering official build from $GIT_BRANCH branch of $FLATPAK_ID" else From ed894a71551e43a11734a7048859cad517a37641 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 10:39:24 +0530 Subject: [PATCH 302/319] pr-check: Add new checks --- .github/workflows/pr-check.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 0c7f89c..845e5d9 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -101,6 +101,10 @@ jobs: PR_THREAD_COUNT=$(gh api repos/$GH_REPO/pulls/$PR_NUM/comments \ --jq '[.[] | select(.position != null)] | length') + COMMIT_COUNT="(gh api repos/$GH_REPO/pulls/$PR_NUM --jq '.commits')" + + CONTAINS_MASTER=$(gh api repos/$GH_REPO/pulls/$PR_NUM/commits --jq '.[1] | (.commit.author.email == "mclasen@redhat.com" and .commit.message == "Add some instructions")') + BLOCKED=0 comment_exists() { @@ -140,6 +144,16 @@ jobs: fi } + if [ "$CONTAINS_MASTER" = "true" ]; then + echo "PR contains commits from master branch" + BLOCKED=1 + fi + + if [ "$CONTAINS_MASTER" = "true" ]; then + echo "PR contains commits from master branch" + BLOCKED=1 + fi + if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" BLOCKED=1 @@ -230,6 +244,16 @@ jobs: bot, build BUILD_START_COMMENT_PARTIAL: "Starting a test build of the submission" + REVIEW_COMMENT: | + This pull request is temporarily marked as blocked as some + automated checks failed on it. Please make sure the + following are items are done: + + 1. The title of the pull request is `Add $FLATPAK_ID`. + 2. All [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) + in the pull request body are marked as complete. + 3. The pull request does not contain commits from the `master` + branch of [this repository](https://github.com/flathub/flathub/commits/master/). REVIEW_COMMENT: > This pull request is temporarily marked as blocked as some automated checks failed on it. Please make sure the pull From ea174f50cad4dce402125d812294f9528aa9c012 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 10:40:09 +0530 Subject: [PATCH 303/319] pr-check: Drop dupe review comment --- .github/workflows/pr-check.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 845e5d9..120f574 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -254,12 +254,6 @@ jobs: in the pull request body are marked as complete. 3. The pull request does not contain commits from the `master` branch of [this repository](https://github.com/flathub/flathub/commits/master/). - REVIEW_COMMENT: > - This pull request is temporarily marked as blocked as some - automated checks failed on it. Please make sure the pull - request title is `Add $FLATPAK_ID` and that all - [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) - in the pull request body are marked as complete. LOCKED_COMMENT: > This pull request is marked as blocked and has too many builds failing. Locking this PR temporarily. Please build From 632c67b897d9356a30ee8019fe98f386e722d1b2 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 10:41:43 +0530 Subject: [PATCH 304/319] pr-check: Drop dupe check --- .github/workflows/pr-check.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 120f574..56e0333 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -149,11 +149,6 @@ jobs: BLOCKED=1 fi - if [ "$CONTAINS_MASTER" = "true" ]; then - echo "PR contains commits from master branch" - BLOCKED=1 - fi - if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" BLOCKED=1 From 165b0d0fc7420802bd53fff63be71339d094b2e1 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 10:42:48 +0530 Subject: [PATCH 305/319] pr-check: Fix comment indentation --- .github/workflows/pr-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 56e0333..bf6f487 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -245,8 +245,8 @@ jobs: following are items are done: 1. The title of the pull request is `Add $FLATPAK_ID`. - 2. All [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) - in the pull request body are marked as complete. + 2. All [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) in the pull request body + are marked as complete. 3. The pull request does not contain commits from the `master` branch of [this repository](https://github.com/flathub/flathub/commits/master/). LOCKED_COMMENT: > From 27a86ea4f4d867cf23ba3a7df373e5ec9228a1f6 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 10:48:37 +0530 Subject: [PATCH 306/319] pr-check: Remove draft labels from non draft PRs --- .github/workflows/pr-check.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index bf6f487..0a50c83 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -107,6 +107,9 @@ jobs: BLOCKED=0 + gh pr view $PR_NUM --json isDraft --jq '.isDraft' | grep -q false && \ + gh pr edit $PR_NUM --remove-label "work-in-progress" || true + comment_exists() { local comment="$1" echo "$PR_COMMENTS" | grep -Fq "$comment" From f01a7a0205641622c19d675a6aeca9459c3c0d75 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 11:09:26 +0530 Subject: [PATCH 307/319] pr-check: Build review comment dynamically --- .github/workflows/pr-check.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 0a50c83..8a0348f 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -106,6 +106,7 @@ jobs: CONTAINS_MASTER=$(gh api repos/$GH_REPO/pulls/$PR_NUM/commits --jq '.[1] | (.commit.author.email == "mclasen@redhat.com" and .commit.message == "Add some instructions")') BLOCKED=0 + REVIEW_COMMENT_LINES=() gh pr view $PR_NUM --json isDraft --jq '.isDraft' | grep -q false && \ gh pr edit $PR_NUM --remove-label "work-in-progress" || true @@ -149,11 +150,13 @@ jobs: if [ "$CONTAINS_MASTER" = "true" ]; then echo "PR contains commits from master branch" + REVIEW_COMMENT_LINES+=("- PR contains commits from master branch") BLOCKED=1 fi if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" + REVIEW_COMMENT_LINES+=("- PR title should be `Add $FLATPAK_ID`") BLOCKED=1 fi @@ -164,9 +167,11 @@ jobs: if [ "$CHECKLIST_PRESENT" -eq 0 ]; then echo "No checklist present in PR body" + REVIEW_COMMENT_LINES+=("- No checklist present in PR body") BLOCKED=1 elif [ "$UNCHECKED" -gt 0 ]; then echo "Checklist incomplete in PR body" + REVIEW_COMMENT_LINES+=("- Some checklist items are not checked") BLOCKED=1 fi @@ -175,6 +180,7 @@ jobs: if [ -z "$REQUIRED_CHECKED" ]; then echo "Required checklist not found in PR body" + REVIEW_COMMENT_LINES+=("- Required submission checklist not marked as complete") BLOCKED=1 fi @@ -208,6 +214,10 @@ jobs: gh pr edit "$PR_NUM" --add-label "pr-check-blocked" --remove-label "awaiting-review" if ! comment_exists "$REVIEW_COMMENT_PARTIAL"; then echo "Did not find comment, commenting" + REVIEW_COMMENT="$BASE_REVIEW_COMMENT" + for line in "${REVIEW_COMMENT_LINES[@]}"; do + REVIEW_COMMENT="$REVIEW_COMMENT"$'\n'"$line" + done gh pr comment "$PR_NUM" --body "$REVIEW_COMMENT" else echo "Found comment, skipping commenting" @@ -242,16 +252,10 @@ jobs: bot, build BUILD_START_COMMENT_PARTIAL: "Starting a test build of the submission" - REVIEW_COMMENT: | + BASE_REVIEW_COMMENT: | This pull request is temporarily marked as blocked as some automated checks failed on it. Please make sure the following are items are done: - - 1. The title of the pull request is `Add $FLATPAK_ID`. - 2. All [checklist items](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md) in the pull request body - are marked as complete. - 3. The pull request does not contain commits from the `master` - branch of [this repository](https://github.com/flathub/flathub/commits/master/). LOCKED_COMMENT: > This pull request is marked as blocked and has too many builds failing. Locking this PR temporarily. Please build From cb8c8f6e458387abc6efce407532d8e0f9170248 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Sun, 14 Sep 2025 12:35:32 +0530 Subject: [PATCH 308/319] pr-check: Fix some comments --- .github/workflows/pr-check.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 8a0348f..8a5a24c 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -150,13 +150,13 @@ jobs: if [ "$CONTAINS_MASTER" = "true" ]; then echo "PR contains commits from master branch" - REVIEW_COMMENT_LINES+=("- PR contains commits from master branch") + REVIEW_COMMENT_LINES+=("- PR does not contain commits from the [master branch](https://github.com/flathub/flathub/commits/master/)") BLOCKED=1 fi if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" - REVIEW_COMMENT_LINES+=("- PR title should be `Add $FLATPAK_ID`") + REVIEW_COMMENT_LINES+=("- PR title is `Add $FLATPAK_ID`") BLOCKED=1 fi @@ -167,11 +167,11 @@ jobs: if [ "$CHECKLIST_PRESENT" -eq 0 ]; then echo "No checklist present in PR body" - REVIEW_COMMENT_LINES+=("- No checklist present in PR body") + REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") BLOCKED=1 elif [ "$UNCHECKED" -gt 0 ]; then echo "Checklist incomplete in PR body" - REVIEW_COMMENT_LINES+=("- Some checklist items are not checked") + REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") BLOCKED=1 fi @@ -180,7 +180,7 @@ jobs: if [ -z "$REQUIRED_CHECKED" ]; then echo "Required checklist not found in PR body" - REVIEW_COMMENT_LINES+=("- Required submission checklist not marked as complete") + REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") BLOCKED=1 fi From dd8b34945abff2e95e5b58dc0c7a5b8858dd9f5f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 07:52:02 +0530 Subject: [PATCH 309/319] pr-check: Don't add duplicate review comments --- .github/workflows/pr-check.yml | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 8a5a24c..ad4bf69 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -106,6 +106,7 @@ jobs: CONTAINS_MASTER=$(gh api repos/$GH_REPO/pulls/$PR_NUM/commits --jq '.[1] | (.commit.author.email == "mclasen@redhat.com" and .commit.message == "Add some instructions")') BLOCKED=0 + CHECKLIST_FAILED=0 REVIEW_COMMENT_LINES=() gh pr view $PR_NUM --json isDraft --jq '.isDraft' | grep -q false && \ @@ -167,11 +168,11 @@ jobs: if [ "$CHECKLIST_PRESENT" -eq 0 ]; then echo "No checklist present in PR body" - REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") + CHECKLIST_FAILED=1 BLOCKED=1 elif [ "$UNCHECKED" -gt 0 ]; then echo "Checklist incomplete in PR body" - REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") + CHECKLIST_FAILED=1 BLOCKED=1 fi @@ -180,10 +181,14 @@ jobs: if [ -z "$REQUIRED_CHECKED" ]; then echo "Required checklist not found in PR body" - REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") + CHECKLIST_FAILED=1 BLOCKED=1 fi + if [ "$CHECKLIST_FAILED" -eq 1 ]; then + REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") + fi + echo "BLOCKED is set to $BLOCKED" if [ "$BLOCKED" -eq 0 ]; then From 1e8d9a43327b87b1121c50f894f8401eff3af38f Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:08:14 +0530 Subject: [PATCH 310/319] pr-check: Add some more checks for PR file structure --- .github/workflows/pr-check.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index ad4bf69..6ab7ff2 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -101,6 +101,8 @@ jobs: PR_THREAD_COUNT=$(gh api repos/$GH_REPO/pulls/$PR_NUM/comments \ --jq '[.[] | select(.position != null)] | length') + PR_FILES=$(gh pr view "$PR_NUM" --json files --jq '.files[].path') + COMMIT_COUNT="(gh api repos/$GH_REPO/pulls/$PR_NUM --jq '.commits')" CONTAINS_MASTER=$(gh api repos/$GH_REPO/pulls/$PR_NUM/commits --jq '.[1] | (.commit.author.email == "mclasen@redhat.com" and .commit.message == "Add some instructions")') @@ -161,6 +163,18 @@ jobs: BLOCKED=1 fi + if echo "$PR_FILES" | grep -qE '.*/flathub\.json$'; then + echo "flathub.json not at toplevel" + BLOCKED=1 + REVIEW_COMMENT_LINES+=("- `flathub.json` file is at toplevel") + fi + + if ! echo "$PR_FILES" | grep -qE '^[^/]+\.(ya?ml|json)$'; then + echo "No JSON/YAML files at toplevel" + BLOCKED=1 + REVIEW_COMMENT_LINES+=("- Flatpak manifest is at toplevel) + fi + CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- ?\[[xX]\] [A-Za-z]+' || true) echo "Total checklists found: $CHECKLIST_PRESENT" UNCHECKED=$(printf "%s\n" "$PR_BODY" | grep -Ec '^- \[ \] [A-Za-z]+' || true) From 83f4ff3b8a7b07eb9c6542d3d9303e563a93e80d Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:10:05 +0530 Subject: [PATCH 311/319] pr-check: Fix syntax error --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 6ab7ff2..5aab413 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -172,7 +172,7 @@ jobs: if ! echo "$PR_FILES" | grep -qE '^[^/]+\.(ya?ml|json)$'; then echo "No JSON/YAML files at toplevel" BLOCKED=1 - REVIEW_COMMENT_LINES+=("- Flatpak manifest is at toplevel) + REVIEW_COMMENT_LINES+=("- Flatpak manifest is at toplevel") fi CHECKLIST_PRESENT=$(printf "%s\n" "$PR_BODY" | grep -cE '^- ?\[[xX]\] [A-Za-z]+' || true) From d369f9f3e23c995e306a01c8b785c4b8d86d89f9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:13:06 +0530 Subject: [PATCH 312/319] pr-check: Fix another syntax error --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 5aab413..c890894 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -166,7 +166,7 @@ jobs: if echo "$PR_FILES" | grep -qE '.*/flathub\.json$'; then echo "flathub.json not at toplevel" BLOCKED=1 - REVIEW_COMMENT_LINES+=("- `flathub.json` file is at toplevel") + REVIEW_COMMENT_LINES+=("- flathub.json file is at toplevel") fi if ! echo "$PR_FILES" | grep -qE '^[^/]+\.(ya?ml|json)$'; then From 39194c14eaa24f152935b28c19dd2972feafc4a7 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:16:37 +0530 Subject: [PATCH 313/319] pr-check: Fix another potential syntax error --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index c890894..4c75683 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -159,7 +159,7 @@ jobs: if [ "$EXIT_CODE" -ne 0 ]; then echo "PR title validation failed" - REVIEW_COMMENT_LINES+=("- PR title is `Add $FLATPAK_ID`") + REVIEW_COMMENT_LINES+=('- PR title is "Add $FLATPAK_ID"') BLOCKED=1 fi From a3492dbb831ec5f91f13332097d00f106834b492 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:36:42 +0530 Subject: [PATCH 314/319] pr-check: Add a generic reminder to follow requirements --- .github/workflows/pr-check.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 4c75683..bcbc6aa 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -203,6 +203,10 @@ jobs: REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") fi + if [ "$BLOCKED" -eq 1 ]; then + REVIEW_COMMENT_LINES+=("- The [requirements](https://docs.flathub.org/docs/for-app-authors/requirements) and [submission process](https://docs.flathub.org/docs/for-app-authors/submission) have been followed") + fi + echo "BLOCKED is set to $BLOCKED" if [ "$BLOCKED" -eq 0 ]; then From 816dd383cf2bb9bea706130447713f32743db511 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:39:43 +0530 Subject: [PATCH 315/319] pr-check: Tweak a review comment --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index bcbc6aa..fe6a9cb 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -200,7 +200,7 @@ jobs: fi if [ "$CHECKLIST_FAILED" -eq 1 ]; then - REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are completed") + REVIEW_COMMENT_LINES+=("- All [checklists](https://github.com/flathub/flathub/blob/master/.github/pull_request_template.md?plain=1) are present in PR body and are completed") fi if [ "$BLOCKED" -eq 1 ]; then From 3155ae628301fa11104584ed996b54ca89badfea Mon Sep 17 00:00:00 2001 From: bbhtt Date: Mon, 15 Sep 2025 08:41:40 +0530 Subject: [PATCH 316/319] pr-check: Fix grammar in base review comment --- .github/workflows/pr-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index fe6a9cb..1ebd61e 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -278,7 +278,7 @@ jobs: BASE_REVIEW_COMMENT: | This pull request is temporarily marked as blocked as some automated checks failed on it. Please make sure the - following are items are done: + following items are done: LOCKED_COMMENT: > This pull request is marked as blocked and has too many builds failing. Locking this PR temporarily. Please build From 0dbdbd27ab8444edb0a3afa721265cdf7732c1f9 Mon Sep 17 00:00:00 2001 From: bbhtt Date: Fri, 19 Sep 2025 19:10:24 +0530 Subject: [PATCH 317/319] Exclude org.nicotine_plus.Nicotine from EOL action --- .github/scripts/archive_eol.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/scripts/archive_eol.py b/.github/scripts/archive_eol.py index 5adefb7..76d7800 100644 --- a/.github/scripts/archive_eol.py +++ b/.github/scripts/archive_eol.py @@ -128,6 +128,8 @@ def main() -> None: "com.yubico.yubioath", "com.icanblink.blink", "com.github.wwmm.pulseeffects", + # beta branch is eol + "org.nicotine_plus.Nicotine", } stable = get_eol_refs("x86_64", "flathub") | get_eol_refs("aarch64", "flathub") From 9e9986ef2874c41ccbf3d7c1ccd206ad0c087a6a Mon Sep 17 00:00:00 2001 From: quexeky Date: Fri, 26 Sep 2025 08:35:23 +1000 Subject: [PATCH 318/319] chore: Copy flatpak over to flathub Signed-off-by: quexeky --- .gitignore | 4 +++ .gitmodules | 3 ++ flatpak.metainfo.xml | 40 ++++++++++++++++++++++ org.droposs.app.yml | 79 ++++++++++++++++++++++++++++++++++++++++++++ shared-modules | 1 + 5 files changed, 127 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 flatpak.metainfo.xml create mode 100644 org.droposs.app.yml create mode 160000 shared-modules diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..20dbbf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.flatpak-builder +builddir +repo +drop-app/ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..1e7a990 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "shared-modules"] + path = shared-modules + url = https://github.com/flathub/shared-modules.git diff --git a/flatpak.metainfo.xml b/flatpak.metainfo.xml new file mode 100644 index 0000000..f22e364 --- /dev/null +++ b/flatpak.metainfo.xml @@ -0,0 +1,40 @@ + + + org.droposs.app + + Game + GameTool + + + + app + Drop client for Linux + + CC-BY-SA-4.0 + AGPL-3.0-or-later + + + pointing + keyboard + touch + + + +

    + The companion app for the Drop Server +

    +
    + + org.droposs.app.desktop + + + https://raw.githubusercontent.com/Drop-OSS/media-sources/refs/heads/main/library_game_page.png + + + https://raw.githubusercontent.com/Drop-OSS/media-sources/refs/heads/main/library.png + + + https://raw.githubusercontent.com/Drop-OSS/media-sources/refs/heads/main/library_game_page.png + + +
    \ No newline at end of file diff --git a/org.droposs.app.yml b/org.droposs.app.yml new file mode 100644 index 0000000..bdf03bc --- /dev/null +++ b/org.droposs.app.yml @@ -0,0 +1,79 @@ +id: org.droposs.app + +runtime: org.gnome.Platform +runtime-version: '48' +sdk: org.gnome.Sdk + +command: drop-app +finish-args: + - --share=ipc + - --share=network + - --socket=fallback-x11 + - --socket=wayland + - --socket=pulseaudio + - --device=all + - --share=network + - --allow=multiarch + - --allow=devel + - --talk-name=org.gnome.Mutter.DisplayConfig + - --talk-name=org.freedesktop.ScreenSaver + - --system-talk-name=org.freedesktop.UDisks2 + - --filesystem=/run/media + # For Steam Deck HDR support + - --env=LD_LIBRARY_PATH=/usr/lib/extensions/vulkan/gamescope/lib + - --filesystem=xdg-run/gamescope-0:ro + # For Debian + - --filesystem=/media + - --filesystem=~/.config/MangoHud:ro + - --filesystem=~/.var/app/org.droposs.app/data/ + - --env=PATH=/app/bin:/usr/bin:/app/utils/bin:/usr/lib/extensions/vulkan/MangoHud/bin/:/app/jre/bin/:/usr/lib/extensions/vulkan/gamescope/bin + - --env=GST_PLUGIN_SYSTEM_PATH=/app/lib32/gstreamer-1.0:/app/lib/gstreamer-1.0:/usr/lib/i386-linux-gnu/gstreamer-1.0:/usr/lib/x86_64-linux-gnu/gstreamer-1.0 + # Disable access to xdg-data/flatpak as it's causing a finish-args-unnecessary-xdg-data-access error. + # Flatpak talk API might be enough but this might break features like Steam games detection. + # - --filesystem=xdg-data/flatpak:ro + # Needed for appimages + - --env=APPIMAGE_EXTRACT_AND_RUN=1 + # See: https://github.com/flathub/net.lutris.Lutris/pull/368#issuecomment-1751381312 + - --env=WEBKIT_DISABLE_DMABUF_RENDERER=1 + - --env=NO_TRAY_ICON=true + +modules: + - shared-modules/SDL/SDL-1.2.15.json + - name: main + buildsystem: simple + + sources: + # If you use GitHub releases, you can target an existing remote file + - type: file + url: https://github.com/Drop-OSS/drop-app/releases/download/v0.3.3/Drop.Desktop.Client_0.3.3_amd64.deb + sha256: c3da6761db3c9bc0c04b3083377069f9417509cad6db81b6ef838b55d9f32242 # This is required if you are using a remote source + only-arches: [x86_64] + - type: file + path: flatpak.metainfo.xml + build-commands: + - set -e + - ls + + # Extract the deb package + - mkdir deb-extract + - ar -x *.deb --output deb-extract + - tar -C deb-extract -xf deb-extract/data.tar.gz + + # Copy binary + - ls deb-extract + - ls deb-extract/usr + - ls deb-extract/usr/bin + - 'install -Dm755 deb-extract/usr/bin/drop-app /app/bin/drop-app' + + # Copy desktop file + ensure the right icon is set + - cat deb-extract/usr/share/applications/Drop\ Desktop\ Client.desktop + - sed -i 's/^Icon=.*/Icon=org.droposs.app/' deb-extract/usr/share/applications/Drop\ Desktop\ Client.desktop + + # Copy icons + - install -Dm644 deb-extract/usr/share/icons/hicolor/128x128/apps/drop-app.png /app/share/icons/hicolor/128x128/apps/org.droposs.app.png + - install -Dm644 deb-extract/usr/share/icons/hicolor/32x32/apps/drop-app.png /app/share/icons/hicolor/32x32/apps/org.droposs.app.png + - install -Dm644 deb-extract/usr/share/icons/hicolor/256x256@2/apps/drop-app.png /app/share/icons/hicolor/256x256@2/apps/org.droposs.app.png + + - install -Dm644 deb-extract/usr/share/applications/Drop\ Desktop\ Client.desktop /app/share/applications/org.droposs.app.desktop + + - install -Dm644 flatpak.metainfo.xml /app/share/metainfo/org.droposs.app.metainfo.xml \ No newline at end of file diff --git a/shared-modules b/shared-modules new file mode 160000 index 0000000..57e1de8 --- /dev/null +++ b/shared-modules @@ -0,0 +1 @@ +Subproject commit 57e1de8b2ee9794e081c9de6058e23100b49b5a2 From 54eefc0959d902a9053640552c78d148e65f2b0f Mon Sep 17 00:00:00 2001 From: quexeky Date: Mon, 29 Sep 2025 20:33:32 +1000 Subject: [PATCH 319/319] chore: Update .gitignore Signed-off-by: quexeky --- .gitignore | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 20dbbf5..73ff59a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -.flatpak-builder -builddir -repo -drop-app/ \ No newline at end of file +* +!flatpak.metainfo.xml +!org.droposs.app.yml \ No newline at end of file
  • b5E7*#+Fxa+Xq&hojM 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 literal 0 HcmV?d00001 diff --git a/.github/images/pr_image_light.png b/.github/images/pr_image_light.png new file mode 100644 index 0000000000000000000000000000000000000000..86be30727348e2d9a9e86b5516e788b2947508a9 GIT binary patch literal 83935 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 {a?6AcXibIh-Ulo620X(Ou)Lx_5x-Uw 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