diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 60580813dcc0..13d2d547569b 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -24,7 +24,7 @@ "rollForward": false }, "microsoft.dotnet.xharness.cli": { - "version": "9.0.0-prerelease.25207.3", + "version": "9.0.0-prerelease.25214.1", "commands": [ "xharness" ], diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index bc4f230aa1cc..fe467c1887c5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,8 @@ + +> [!NOTE] +> Are you waiting for the changes in this PR to be merged? +> It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! + diff --git a/.github/policies/resourceManagement.yml b/.github/policies/resourceManagement.yml index ce401f610d91..675d7c8ee028 100644 --- a/.github/policies/resourceManagement.yml +++ b/.github/policies/resourceManagement.yml @@ -375,9 +375,6 @@ configuration: - isActivitySender: user: roubachof issueAuthor: False - - isActivitySender: - user: davidbritch - issueAuthor: False then: - addLabel: label: i/great-reporter @@ -557,16 +554,16 @@ configuration: label: "t/breaking \U0001F4A5" then: - addReply: - reply: "\U0001F6A8 API change(s) detected @davidbritch FYI" - description: Tag Dave Britch when a breaking change is tagged on an issue + reply: "\U0001F6A8 API change(s) detected @davidortinau @rachelkang FYI" + description: Tag David Ortinau and Rachel Kang when a breaking change is tagged on an issue - if: - payloadType: Pull_Request - labelAdded: label: "t/breaking \U0001F4A5" then: - addReply: - reply: "\U0001F6A8 API change(s) detected @davidbritch FYI" - description: Tag Dave Britch when a breaking change is tagged on an PR + reply: "\U0001F6A8 API change(s) detected @davidortinau @rachelkang FYI" + description: Tag David Ortinau and Rachel Kang when a breaking change is tagged on an PR - if: - payloadType: Issue_Comment - isIssue diff --git a/.github/prompts/contributors.json b/.github/prompts/contributors.json new file mode 100644 index 000000000000..39c75906ee2a --- /dev/null +++ b/.github/prompts/contributors.json @@ -0,0 +1,3926 @@ +[ + { + "login": "rmarinho", + "id": 1235097, + "type": "User", + "contributions": 2079 + }, + { + "login": "PureWeen", + "id": 5375137, + "type": "User", + "contributions": 1710 + }, + { + "login": "mattleibow", + "id": 1096616, + "type": "User", + "contributions": 1679 + }, + { + "login": "jsuarezruiz", + "id": 6755973, + "type": "User", + "contributions": 1035 + }, + { + "login": "hartez", + "id": 538025, + "type": "User", + "contributions": 958 + }, + { + "login": "dotnet-maestro[bot]", + "id": 42748379, + "type": "Bot", + "contributions": 895 + }, + { + "login": "StephaneDelcroix", + "id": 313003, + "type": "User", + "contributions": 856 + }, + { + "login": "Redth", + "id": 271950, + "type": "User", + "contributions": 781 + }, + { + "login": "github-actions[bot]", + "id": 41898282, + "type": "Bot", + "contributions": 443 + }, + { + "login": "jfversluis", + "id": 939291, + "type": "User", + "contributions": 430 + }, + { + "login": "samhouts", + "id": 7827070, + "type": "User", + "contributions": 415 + }, + { + "login": "jamesmontemagno", + "id": 1676321, + "type": "User", + "contributions": 370 + }, + { + "login": "dependabot[bot]", + "id": 49699333, + "type": "Bot", + "contributions": 337 + }, + { + "login": "jonathanpeppers", + "id": 840039, + "type": "User", + "contributions": 327 + }, + { + "login": "jonlipsky", + "id": 1466386, + "type": "User", + "contributions": 169 + }, + { + "login": "kingces95", + "id": 4120386, + "type": "User", + "contributions": 145 + }, + { + "login": "Eilon", + "id": 202643, + "type": "User", + "contributions": 134 + }, + { + "login": "kubaflo", + "id": 42434498, + "type": "User", + "contributions": 117 + }, + { + "name": "Pavel Yakovlev", + "email": "v-payako@microsoft.com", + "type": "Anonymous", + "contributions": 109 + }, + { + "login": "adrianknight89", + "id": 16855542, + "type": "User", + "contributions": 107 + }, + { + "login": "rookiejava", + "id": 1029134, + "type": "User", + "contributions": 105 + }, + { + "login": "pauldipietro", + "id": 1251024, + "type": "User", + "contributions": 94 + }, + { + "login": "rachelkang", + "id": 21988533, + "type": "User", + "contributions": 92 + }, + { + "login": "anandhan-rajagopal", + "id": 97146406, + "type": "User", + "contributions": 86 + }, + { + "login": "Clancey", + "id": 256046, + "type": "User", + "contributions": 79 + }, + { + "name": "Jason Smith", + "email": "jason.smith@xamarin.com", + "type": "Anonymous", + "contributions": 76 + }, + { + "login": "simonrozsival", + "id": 374616, + "type": "User", + "contributions": 69 + }, + { + "login": "Foda", + "id": 890772, + "type": "User", + "contributions": 66 + }, + { + "login": "pjcollins", + "id": 2000163, + "type": "User", + "contributions": 64 + }, + { + "login": "AndreiMisiukevich", + "id": 10124814, + "type": "User", + "contributions": 61 + }, + { + "login": "myroot", + "id": 1029155, + "type": "User", + "contributions": 60 + }, + { + "login": "tj-devel709", + "id": 50846373, + "type": "User", + "contributions": 60 + }, + { + "login": "MartyIX", + "id": 203266, + "type": "User", + "contributions": 57 + }, + { + "login": "davidortinau", + "id": 41873, + "type": "User", + "contributions": 55 + }, + { + "login": "mandel-macaque", + "id": 2190086, + "type": "User", + "contributions": 55 + }, + { + "login": "pictos", + "id": 20712372, + "type": "User", + "contributions": 51 + }, + { + "login": "drasticactions", + "id": 898335, + "type": "User", + "contributions": 47 + }, + { + "login": "dimonovdd", + "id": 59065470, + "type": "User", + "contributions": 47 + }, + { + "login": "eerhardt", + "id": 8291187, + "type": "User", + "contributions": 42 + }, + { + "login": "albyrock87", + "id": 1423005, + "type": "User", + "contributions": 40 + }, + { + "name": "Mike Corsaro", + "email": "mikecorsaro@microsoft.com", + "type": "Anonymous", + "contributions": 39 + }, + { + "login": "swharden", + "id": 4165489, + "type": "User", + "contributions": 37 + }, + { + "login": "MichaelNorman", + "id": 1462796, + "type": "User", + "contributions": 37 + }, + { + "login": "Tamilarasan-Paranthaman", + "id": 93904422, + "type": "User", + "contributions": 34 + }, + { + "login": "TanayParikh", + "id": 14852843, + "type": "User", + "contributions": 34 + }, + { + "login": "jknaudt21", + "id": 32918747, + "type": "User", + "contributions": 33 + }, + { + "login": "moljac", + "id": 1768576, + "type": "User", + "contributions": 33 + }, + { + "login": "jstedfast", + "id": 338984, + "type": "User", + "contributions": 32 + }, + { + "login": "andreinitescu", + "id": 743918, + "type": "User", + "contributions": 32 + }, + { + "name": "Schilli, Niklas", + "email": "schilli@ams-berlin.de", + "type": "Anonymous", + "contributions": 31 + }, + { + "login": "vividos", + "id": 429902, + "type": "User", + "contributions": 31 + }, + { + "login": "jimmgarrido", + "id": 4087358, + "type": "User", + "contributions": 29 + }, + { + "login": "sbanni", + "id": 1885888, + "type": "User", + "contributions": 28 + }, + { + "login": "shyunMin", + "id": 20968023, + "type": "User", + "contributions": 28 + }, + { + "login": "ravinderjangra", + "id": 9795917, + "type": "User", + "contributions": 28 + }, + { + "name": "Jason Smith", + "email": "jas@microsoft.com", + "type": "Anonymous", + "contributions": 27 + }, + { + "login": "antonfirsov", + "id": 6835152, + "type": "User", + "contributions": 27 + }, + { + "name": "Jonathan Dick", + "email": "jond@hey.com", + "type": "Anonymous", + "contributions": 25 + }, + { + "login": "kvpt", + "id": 1446221, + "type": "User", + "contributions": 25 + }, + { + "login": "mohachouch", + "id": 25939826, + "type": "User", + "contributions": 25 + }, + { + "login": "akihikodaki", + "id": 17036990, + "type": "User", + "contributions": 24 + }, + { + "login": "dustin-wojciechowski", + "id": 89540402, + "type": "User", + "contributions": 24 + }, + { + "login": "NirmalKumarYuvaraj", + "id": 97871636, + "type": "User", + "contributions": 22 + }, + { + "login": "JoonghyunCho", + "id": 14328614, + "type": "User", + "contributions": 22 + }, + { + "login": "jcmanke", + "id": 6132629, + "type": "User", + "contributions": 20 + }, + { + "login": "yurkinh", + "id": 17849938, + "type": "User", + "contributions": 20 + }, + { + "login": "bmacombe", + "id": 15127788, + "type": "User", + "contributions": 20 + }, + { + "login": "BradChase2011", + "id": 13279060, + "type": "User", + "contributions": 20 + }, + { + "login": "devanathan-vaithiyanathan", + "id": 114395405, + "type": "User", + "contributions": 19 + }, + { + "login": "HarishKumarSF4517", + "id": 171316288, + "type": "User", + "contributions": 19 + }, + { + "name": "Luke Westendorf", + "email": "lukewest@microsoft.com", + "type": "Anonymous", + "contributions": 18 + }, + { + "login": "Vignesh-SF3580", + "id": 102575140, + "type": "User", + "contributions": 18 + }, + { + "login": "BretJohnson", + "id": 245892, + "type": "User", + "contributions": 18 + }, + { + "login": "janusw", + "id": 484108, + "type": "User", + "contributions": 17 + }, + { + "login": "lutzroeder", + "id": 438516, + "type": "User", + "contributions": 17 + }, + { + "login": "spadapet", + "id": 2523431, + "type": "User", + "contributions": 17 + }, + { + "login": "newky2k", + "id": 6675766, + "type": "User", + "contributions": 16 + }, + { + "login": "melimion", + "id": 33512073, + "type": "User", + "contributions": 16 + }, + { + "login": "cshung", + "id": 3410332, + "type": "User", + "contributions": 15 + }, + { + "login": "sung-su", + "id": 10704816, + "type": "User", + "contributions": 15 + }, + { + "login": "javiercn", + "id": 6995051, + "type": "User", + "contributions": 14 + }, + { + "login": "MackinnonBuck", + "id": 10456961, + "type": "User", + "contributions": 14 + }, + { + "name": "Niklas Schilli", + "email": "schillinik@yahoo.de", + "type": "Anonymous", + "contributions": 14 + }, + { + "login": "dotMorten", + "id": 1378165, + "type": "User", + "contributions": 14 + }, + { + "login": "symbiogenesis", + "id": 1724472, + "type": "User", + "contributions": 13 + }, + { + "name": "GitHub Actions Autoformatter", + "email": "autoformat@example.com", + "type": "Anonymous", + "contributions": 13 + }, + { + "login": "jkurdek", + "id": 59935235, + "type": "User", + "contributions": 13 + }, + { + "login": "LogishaSelvarajSF4525", + "id": 171314950, + "type": "User", + "contributions": 13 + }, + { + "login": "MarkoBL", + "id": 273464, + "type": "User", + "contributions": 13 + }, + { + "login": "SuthiYuvaraj", + "id": 92777079, + "type": "User", + "contributions": 12 + }, + { + "login": "lytico", + "id": 1479980, + "type": "User", + "contributions": 12 + }, + { + "login": "emaf", + "id": 3286258, + "type": "User", + "contributions": 12 + }, + { + "login": "nivetha-nagalingam", + "id": 170066931, + "type": "User", + "contributions": 11 + }, + { + "login": "dellis1972", + "id": 810617, + "type": "User", + "contributions": 11 + }, + { + "login": "BagavathiPerumal", + "id": 93652794, + "type": "User", + "contributions": 11 + }, + { + "login": "VladislavAntonyuk", + "id": 33021114, + "type": "User", + "contributions": 10 + }, + { + "login": "ivanpovazan", + "id": 55002338, + "type": "User", + "contributions": 10 + }, + { + "login": "alanmcgovern", + "id": 264396, + "type": "User", + "contributions": 10 + }, + { + "login": "vpenades", + "id": 5433822, + "type": "User", + "contributions": 10 + }, + { + "login": "Depechie", + "id": 351693, + "type": "User", + "contributions": 10 + }, + { + "login": "csigs", + "id": 13859395, + "type": "User", + "contributions": 10 + }, + { + "name": "Damian Karzon", + "email": "dkarzon@skedulo.com", + "type": "Anonymous", + "contributions": 10 + }, + { + "login": "kzu", + "id": 169707, + "type": "User", + "contributions": 10 + }, + { + "login": "krdmllr", + "id": 11095003, + "type": "User", + "contributions": 10 + }, + { + "login": "SteveSandersonMS", + "id": 1101362, + "type": "User", + "contributions": 10 + }, + { + "login": "mikescandy", + "id": 2494505, + "type": "User", + "contributions": 9 + }, + { + "login": "alanag13", + "id": 5409649, + "type": "User", + "contributions": 9 + }, + { + "login": "Ahamed-Ali", + "id": 102580874, + "type": "User", + "contributions": 9 + }, + { + "login": "japarson", + "id": 59936622, + "type": "User", + "contributions": 9 + }, + { + "login": "activa", + "id": 650710, + "type": "User", + "contributions": 9 + }, + { + "login": "buyaa-n", + "id": 45579687, + "type": "User", + "contributions": 8 + }, + { + "login": "dalexsoto", + "id": 204671, + "type": "User", + "contributions": 8 + }, + { + "login": "ylatuya", + "id": 111134, + "type": "User", + "contributions": 8 + }, + { + "login": "NanthiniMahalingam", + "id": 105482474, + "type": "User", + "contributions": 8 + }, + { + "name": "Mrnikbobjeff", + "email": "schillinik@yahoo.de", + "type": "Anonymous", + "contributions": 8 + }, + { + "login": "mjbond-msft", + "id": 35508883, + "type": "User", + "contributions": 8 + }, + { + "login": "techduggu", + "id": 17450941, + "type": "User", + "contributions": 7 + }, + { + "login": "etvorun", + "id": 48451158, + "type": "User", + "contributions": 7 + }, + { + "login": "felipebaltazar", + "id": 19656249, + "type": "User", + "contributions": 7 + }, + { + "login": "henricm", + "id": 3715975, + "type": "User", + "contributions": 7 + }, + { + "login": "VitalyKnyazev", + "id": 12721191, + "type": "User", + "contributions": 7 + }, + { + "login": "almirvuk", + "id": 15986629, + "type": "User", + "contributions": 7 + }, + { + "login": "brunck", + "id": 4502210, + "type": "User", + "contributions": 7 + }, + { + "login": "conceptdev", + "id": 199373, + "type": "User", + "contributions": 7 + }, + { + "login": "yourina", + "id": 20967778, + "type": "User", + "contributions": 6 + }, + { + "login": "kicsiede", + "id": 4233752, + "type": "User", + "contributions": 6 + }, + { + "login": "dotnet-bot", + "id": 9011267, + "type": "User", + "contributions": 6 + }, + { + "login": "bentmar", + "id": 10244000, + "type": "User", + "contributions": 6 + }, + { + "login": "knocte", + "id": 331303, + "type": "User", + "contributions": 6 + }, + { + "login": "dansiegel", + "id": 3860573, + "type": "User", + "contributions": 6 + }, + { + "login": "ionixjunior", + "id": 519642, + "type": "User", + "contributions": 6 + }, + { + "login": "WayaFlyfeather", + "id": 3807144, + "type": "User", + "contributions": 6 + }, + { + "login": "GalaxiaGuy", + "id": 475450, + "type": "User", + "contributions": 6 + }, + { + "login": "sps014", + "id": 45932883, + "type": "User", + "contributions": 6 + }, + { + "login": "TimBarham", + "id": 9665847, + "type": "User", + "contributions": 6 + }, + { + "login": "Viridovics", + "id": 6348792, + "type": "User", + "contributions": 6 + }, + { + "login": "mkieres", + "id": 8372764, + "type": "User", + "contributions": 5 + }, + { + "login": "eltociear", + "id": 22633385, + "type": "User", + "contributions": 5 + }, + { + "login": "bill2004158", + "id": 211855, + "type": "User", + "contributions": 5 + }, + { + "login": "bruzkovsky", + "id": 10390959, + "type": "User", + "contributions": 5 + }, + { + "login": "molesmoke", + "id": 3227864, + "type": "User", + "contributions": 5 + }, + { + "login": "lindexi", + "id": 16054566, + "type": "User", + "contributions": 5 + }, + { + "login": "VSadov", + "id": 8218165, + "type": "User", + "contributions": 5 + }, + { + "login": "vs-mobiletools-engineering-service2", + "id": 67918504, + "type": "User", + "contributions": 5 + }, + { + "login": "peterfoot", + "id": 3985053, + "type": "User", + "contributions": 5 + }, + { + "login": "dhindrik", + "id": 6691971, + "type": "User", + "contributions": 5 + }, + { + "login": "TheCodeTraveler", + "id": 13558917, + "type": "User", + "contributions": 5 + }, + { + "login": "Dhivya-SF4094", + "id": 127717131, + "type": "User", + "contributions": 5 + }, + { + "login": "edsnider", + "id": 557602, + "type": "User", + "contributions": 5 + }, + { + "login": "f1nzer", + "id": 1970236, + "type": "User", + "contributions": 5 + }, + { + "login": "MSLukeWest", + "id": 42553283, + "type": "User", + "contributions": 5 + }, + { + "login": "mgoertz-msft", + "id": 14282894, + "type": "User", + "contributions": 5 + }, + { + "login": "mrlacey", + "id": 189547, + "type": "User", + "contributions": 5 + }, + { + "name": "Matthew Richardson", + "email": "matthew@velocitysystems.co.nz", + "type": "Anonymous", + "contributions": 5 + }, + { + "login": "mhutch", + "id": 183285, + "type": "User", + "contributions": 5 + }, + { + "login": "NafeelaNazhir", + "id": 171174978, + "type": "User", + "contributions": 5 + }, + { + "login": "bhavanesh2001", + "id": 184209926, + "type": "User", + "contributions": 4 + }, + { + "login": "slang25", + "id": 1341446, + "type": "User", + "contributions": 4 + }, + { + "login": "Cheesebaron", + "id": 249719, + "type": "User", + "contributions": 4 + }, + { + "login": "WonyoungChoi", + "id": 1029205, + "type": "User", + "contributions": 4 + }, + { + "login": "KSemenenko", + "id": 4385716, + "type": "User", + "contributions": 4 + }, + { + "login": "memu8", + "id": 66331238, + "type": "User", + "contributions": 4 + }, + { + "login": "prakashKannanSf3972", + "id": 127308739, + "type": "User", + "contributions": 4 + }, + { + "login": "vishnumenon2684", + "id": 95695113, + "type": "User", + "contributions": 4 + }, + { + "login": "jonpryor", + "id": 155958, + "type": "User", + "contributions": 4 + }, + { + "login": "IlGalvo", + "id": 17992288, + "type": "User", + "contributions": 4 + }, + { + "login": "CliffAgius", + "id": 5613809, + "type": "User", + "contributions": 4 + }, + { + "login": "mfkl", + "id": 3928834, + "type": "User", + "contributions": 4 + }, + { + "login": "vhugogarcia", + "id": 1047398, + "type": "User", + "contributions": 4 + }, + { + "login": "bares43", + "id": 956930, + "type": "User", + "contributions": 4 + }, + { + "login": "flish", + "id": 3818800, + "type": "User", + "contributions": 4 + }, + { + "login": "BrayanKhosravian", + "id": 35541212, + "type": "User", + "contributions": 4 + }, + { + "login": "daltzctr", + "id": 105223895, + "type": "User", + "contributions": 4 + }, + { + "login": "ederbond", + "id": 12549812, + "type": "User", + "contributions": 4 + }, + { + "login": "adamped", + "id": 13672662, + "type": "User", + "contributions": 4 + }, + { + "login": "filipnavara", + "id": 1764393, + "type": "User", + "contributions": 4 + }, + { + "login": "praeclarum", + "id": 323548, + "type": "User", + "contributions": 4 + }, + { + "login": "J-Swift", + "id": 734158, + "type": "User", + "contributions": 4 + }, + { + "login": "jvansickle", + "id": 7631608, + "type": "User", + "contributions": 4 + }, + { + "login": "MartinZikmund", + "id": 1075116, + "type": "User", + "contributions": 4 + }, + { + "login": "BioTurboNick", + "id": 1438610, + "type": "User", + "contributions": 4 + }, + { + "login": "legistek", + "id": 13384523, + "type": "User", + "contributions": 4 + }, + { + "login": "pranavkm", + "id": 174281, + "type": "User", + "contributions": 4 + }, + { + "login": "rolfbjarne", + "id": 249268, + "type": "User", + "contributions": 4 + }, + { + "login": "scastria", + "id": 4534494, + "type": "User", + "contributions": 4 + }, + { + "name": "Paul DiPietro", + "email": "paul.dipietro@microsoft.com", + "type": "Anonymous", + "contributions": 3 + }, + { + "login": "rogihee", + "id": 4984486, + "type": "User", + "contributions": 3 + }, + { + "login": "stmoor", + "id": 77985069, + "type": "User", + "contributions": 3 + }, + { + "login": "sthewissen", + "id": 2419439, + "type": "User", + "contributions": 3 + }, + { + "login": "SubhikshaSf4851", + "id": 184361895, + "type": "User", + "contributions": 3 + }, + { + "login": "TamilarasanSF4853", + "id": 184361845, + "type": "User", + "contributions": 3 + }, + { + "login": "YZahringer", + "id": 4254116, + "type": "User", + "contributions": 3 + }, + { + "login": "Youssef1313", + "id": 31348972, + "type": "User", + "contributions": 3 + }, + { + "login": "jzeferino", + "id": 10722952, + "type": "User", + "contributions": 3 + }, + { + "login": "puppetSpace", + "id": 14003064, + "type": "User", + "contributions": 3 + }, + { + "login": "solomonfried", + "id": 36649129, + "type": "User", + "contributions": 3 + }, + { + "login": "tessarolli", + "id": 11618432, + "type": "User", + "contributions": 3 + }, + { + "login": "magoolation", + "id": 626364, + "type": "User", + "contributions": 3 + }, + { + "login": "beeradmoore", + "id": 904737, + "type": "User", + "contributions": 3 + }, + { + "login": "jgold6", + "id": 4606509, + "type": "User", + "contributions": 3 + }, + { + "login": "akoeplinger", + "id": 1376924, + "type": "User", + "contributions": 3 + }, + { + "login": "patridge", + "id": 713665, + "type": "User", + "contributions": 3 + }, + { + "login": "aaronfranke", + "id": 1646875, + "type": "User", + "contributions": 3 + }, + { + "login": "artemious7", + "id": 16724889, + "type": "User", + "contributions": 3 + }, + { + "login": "artemvalieiev", + "id": 3391032, + "type": "User", + "contributions": 3 + }, + { + "login": "Axemasta", + "id": 33064621, + "type": "User", + "contributions": 3 + }, + { + "login": "BjornVanslembrouck", + "id": 44607491, + "type": "User", + "contributions": 3 + }, + { + "login": "daniel-luberda", + "id": 13569983, + "type": "User", + "contributions": 3 + }, + { + "login": "DianaSoltani", + "id": 31975705, + "type": "User", + "contributions": 3 + }, + { + "login": "ooikengsiang", + "id": 19687809, + "type": "User", + "contributions": 3 + }, + { + "login": "mikeparker104", + "id": 12763221, + "type": "User", + "contributions": 3 + }, + { + "login": "MichaelRumpler", + "id": 8309363, + "type": "User", + "contributions": 3 + }, + { + "login": "mkhamoyan", + "id": 96171496, + "type": "User", + "contributions": 3 + }, + { + "login": "Lehonti", + "id": 17771375, + "type": "User", + "contributions": 3 + }, + { + "login": "jeffhandley", + "id": 1031940, + "type": "User", + "contributions": 3 + }, + { + "login": "SotoiGhost", + "id": 5924210, + "type": "User", + "contributions": 3 + }, + { + "login": "GiampaoloGabba", + "id": 8319337, + "type": "User", + "contributions": 3 + }, + { + "login": "felipemomm", + "id": 6777353, + "type": "User", + "contributions": 3 + }, + { + "login": "espenrl", + "id": 4621581, + "type": "User", + "contributions": 3 + }, + { + "login": "jpobst", + "id": 179295, + "type": "User", + "contributions": 2 + }, + { + "login": "RodgerLeblanc", + "id": 6235690, + "type": "User", + "contributions": 2 + }, + { + "login": "SpiegelSoft", + "id": 557824, + "type": "User", + "contributions": 2 + }, + { + "login": "rick-palmsens", + "id": 57390463, + "type": "User", + "contributions": 2 + }, + { + "login": "nogginbox", + "id": 729381, + "type": "User", + "contributions": 2 + }, + { + "login": "JTOne123", + "id": 3457140, + "type": "User", + "contributions": 2 + }, + { + "login": "PaulAndersonS", + "id": 42271912, + "type": "User", + "contributions": 2 + }, + { + "login": "ntherning", + "id": 135765, + "type": "User", + "contributions": 2 + }, + { + "login": "pingzing", + "id": 5133649, + "type": "User", + "contributions": 2 + }, + { + "login": "manutdkid77", + "id": 14297705, + "type": "User", + "contributions": 2 + }, + { + "login": "nwestfall", + "id": 4753021, + "type": "User", + "contributions": 2 + }, + { + "login": "Moha69100", + "id": 6330427, + "type": "User", + "contributions": 2 + }, + { + "login": "mjmostachetti", + "id": 6486831, + "type": "User", + "contributions": 2 + }, + { + "login": "migueldeicaza", + "id": 36863, + "type": "User", + "contributions": 2 + }, + { + "login": "mauroa", + "id": 2921919, + "type": "User", + "contributions": 2 + }, + { + "login": "mattjohnsonpint", + "id": 1396388, + "type": "User", + "contributions": 2 + }, + { + "login": "martincostello", + "id": 1439341, + "type": "User", + "contributions": 2 + }, + { + "login": "marcmognol", + "id": 8171300, + "type": "User", + "contributions": 2 + }, + { + "login": "domagojmedo", + "id": 12157224, + "type": "User", + "contributions": 2 + }, + { + "login": "DavidRoqueni", + "id": 45717673, + "type": "User", + "contributions": 2 + }, + { + "login": "Dresel", + "id": 1769090, + "type": "User", + "contributions": 2 + }, + { + "login": "Adam--", + "id": 2179171, + "type": "User", + "contributions": 2 + }, + { + "login": "workgroupengineering", + "id": 12531229, + "type": "User", + "contributions": 2 + }, + { + "login": "ruby-verma", + "id": 20953456, + "type": "User", + "contributions": 2 + }, + { + "login": "praveenkumarkarunanithi", + "id": 100338903, + "type": "User", + "contributions": 2 + }, + { + "login": "neolithos", + "id": 9724420, + "type": "User", + "contributions": 2 + }, + { + "login": "maonaoda", + "id": 32831595, + "type": "User", + "contributions": 2 + }, + { + "login": "flyofsky", + "id": 16184582, + "type": "User", + "contributions": 2 + }, + { + "login": "dotnet-policy-service[bot]", + "id": 123482357, + "type": "Bot", + "contributions": 2 + }, + { + "name": "dend", + "email": "dend@outlook.com", + "type": "Anonymous", + "contributions": 2 + }, + { + "login": "campersau", + "id": 4009570, + "type": "User", + "contributions": 2 + }, + { + "login": "WeihanLi", + "id": 7604648, + "type": "User", + "contributions": 2 + }, + { + "login": "vitek-karas", + "id": 10670590, + "type": "User", + "contributions": 2 + }, + { + "login": "surayya-MS", + "id": 114938397, + "type": "User", + "contributions": 2 + }, + { + "login": "stephen-hawley", + "id": 15199050, + "type": "User", + "contributions": 2 + }, + { + "login": "sanyandreichuk", + "id": 8818052, + "type": "User", + "contributions": 2 + }, + { + "login": "Rustamxon", + "id": 123984585, + "type": "User", + "contributions": 2 + }, + { + "login": "maxkoshevoi", + "id": 6609929, + "type": "User", + "contributions": 2 + }, + { + "login": "dmariogatto", + "id": 8588913, + "type": "User", + "contributions": 2 + }, + { + "login": "breenbob", + "id": 6000851, + "type": "User", + "contributions": 2 + }, + { + "login": "cadsit", + "id": 9328605, + "type": "User", + "contributions": 2 + }, + { + "login": "cschwarz", + "id": 717934, + "type": "User", + "contributions": 2 + }, + { + "login": "csteeg", + "id": 431177, + "type": "User", + "contributions": 2 + }, + { + "login": "chabiss", + "id": 14151258, + "type": "User", + "contributions": 2 + }, + { + "login": "bricelam", + "id": 1226749, + "type": "User", + "contributions": 2 + }, + { + "login": "Bobface", + "id": 10945014, + "type": "User", + "contributions": 2 + }, + { + "login": "BitooBit", + "id": 59031286, + "type": "User", + "contributions": 2 + }, + { + "login": "BurningLights", + "id": 14267553, + "type": "User", + "contributions": 2 + }, + { + "login": "mkArtakMSFT", + "id": 34246760, + "type": "User", + "contributions": 2 + }, + { + "login": "andres-fg", + "id": 16245738, + "type": "User", + "contributions": 2 + }, + { + "login": "SkyeHoefling", + "id": 17751436, + "type": "User", + "contributions": 2 + }, + { + "login": "AArnott", + "id": 3548, + "type": "User", + "contributions": 2 + }, + { + "login": "andreas-nesheim", + "id": 11583629, + "type": "User", + "contributions": 2 + }, + { + "login": "aheubusch", + "id": 11393955, + "type": "User", + "contributions": 2 + }, + { + "login": "appsourcers", + "id": 36886162, + "type": "User", + "contributions": 2 + }, + { + "login": "agaluzzi", + "id": 5098044, + "type": "User", + "contributions": 2 + }, + { + "login": "akamud", + "id": 954102, + "type": "User", + "contributions": 2 + }, + { + "login": "HavenDV", + "id": 3002068, + "type": "User", + "contributions": 2 + }, + { + "login": "KarthikRajaKalaimani", + "id": 92777139, + "type": "User", + "contributions": 2 + }, + { + "login": "jorisvergeer", + "id": 1906639, + "type": "User", + "contributions": 2 + }, + { + "login": "Suplanus", + "id": 2002916, + "type": "User", + "contributions": 2 + }, + { + "login": "lateralusX", + "id": 11529140, + "type": "User", + "contributions": 2 + }, + { + "login": "joelmartinez", + "id": 90380, + "type": "User", + "contributions": 2 + }, + { + "login": "jsmarcus", + "id": 1919776, + "type": "User", + "contributions": 2 + }, + { + "name": "Dave Humphreys", + "email": "dave@thing.com", + "type": "Anonymous", + "contributions": 2 + }, + { + "login": "dend", + "id": 1389609, + "type": "User", + "contributions": 2 + }, + { + "login": "breyed", + "id": 1299073, + "type": "User", + "contributions": 2 + }, + { + "login": "thudugala", + "id": 4112014, + "type": "User", + "contributions": 2 + }, + { + "login": "EmilAlipiev", + "id": 10422347, + "type": "User", + "contributions": 2 + }, + { + "name": "Israel Soto", + "email": "issoto@microsoft.com", + "type": "Anonymous", + "contributions": 2 + }, + { + "login": "terrajobst", + "id": 5169960, + "type": "User", + "contributions": 2 + }, + { + "login": "ethanis", + "id": 8703324, + "type": "User", + "contributions": 2 + }, + { + "login": "fredeil", + "id": 17533404, + "type": "User", + "contributions": 2 + }, + { + "login": "ghuntley", + "id": 127353, + "type": "User", + "contributions": 2 + }, + { + "name": "Stefan de Vogelaere", + "email": "stefan@cavebirdlabs.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Stefan Gerasch", + "email": "stefangerasch1991@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Stanislav", + "email": "stasbav@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sreeraj P R", + "email": "sreerajpr.mec@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Soundman32", + "email": "neil.scales@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Soichi Ikebe", + "email": "souichi1997@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Softlion (Benjamin Mayrargue)", + "email": "benjamin@vapolia.fr", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Softlion (Benjamin Mayrargue)", + "email": "benjamin@mayrargue.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Smit Patel", + "email": "smitpatel@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sivamuthu Kumar", + "email": "sivamuthukumar07@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sivakumar", + "email": "sivakumarr@syncfusion.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Simon Cropp", + "email": "simon.cropp@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Shalini-Ashokan", + "email": "102292178+shalini-ashokan@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sergio Escalada", + "email": "sescalada@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sergej Derjabkin", + "email": "sergej@sendev.de", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sebastian Rauer", + "email": "info@sebastianrauer.de", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sean Killeen", + "email": "seankilleen@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sean Davies", + "email": "spdavies2@live.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sandro Cavazzoni", + "email": "sandro@ideaful.it", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Samir GC", + "email": "55045516+samirgcofficial@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Todd", + "email": "thenderson21@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "TingtingAn", + "email": "antingting2009@qq.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Timothé Larivière", + "email": "timothe.lariviere@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tim Johnson", + "email": "t-johnson@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tianqi Zhang", + "email": "tianqizhang@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Thomas Muller", + "email": "imuller@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Thomas Mijieux", + "email": "tmijieux@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Thetyne", + "email": "thetyne@live.fr", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Theodore Tsirpanis", + "email": "teo-tsirpanis@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Takym (たかやま)", + "email": "15681312+takym@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Takaaki Suzuki", + "email": "xin9le@live.jp", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sławomir Kulików", + "email": "slawomir.kulikow@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sławomir Kulików", + "email": "kulikow@logotec.pl", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sören Nils Kuklau", + "email": "chucker@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Symbai", + "email": "14368203+symbai@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sylvain Gravel", + "email": "lrp-sgravel@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "SyedAbdulAzeemSF4852", + "email": "syedabdulazeem.a@syncfusion.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sven Boemer", + "email": "sbomer@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Surayya Huseyn Zada", + "email": "shuseynzada@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sunner", + "email": "sunnerlp@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "StevenGranados", + "email": "51818199+stevengranados@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Steve", + "email": "steverichey@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Stephen Halter", + "email": "halter73@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Sam", + "email": "28056243+faheys@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Peter Spada", + "email": "spadapet@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "PawKanarek", + "email": "paw.kanarek@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "PavloLukianets", + "email": "109070173+pavlolukianets@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Pavel Yakovlev (Akvelon)", + "email": "v-payako@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Patrick Long", + "email": "pat@munkiisoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Patrick Hartman", + "email": "patrick@leglock.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Patrick Allwood", + "email": "patchandthat@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Parker Bibus", + "email": "pbibus@hotmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Parker Bibus", + "email": "parkerbibus@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "P3PPP", + "email": "ticktackmob@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Oren Novotny", + "email": "oren@novotny.org", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ooi Keng Siang", + "email": "ks@ooiks.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Omniq-APL-Rollving", + "email": "61408543+omniq-apl-rollving@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Oleksandr Dobrynin", + "email": "shuron1988@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Oleh Kaliuzhnyi", + "email": "oleg.kaliuzhny@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Oddbjørn Bakke", + "email": "oddbjorn.bakke@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Oberdan Bitencourt Ferreira", + "email": "oberdan.bitencourt@arctouch.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Noam Yogev", + "email": "noamyogev84@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Niklas Therning", + "email": "nitherni@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Niklas Schilli", + "email": "niklasschilli@mailbox.org", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Niklas Schilli", + "email": "n.schilli@inno-focus.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Niels van der Knaap", + "email": "niels@nielsknaap.nl", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "CartBlanche", + "id": 271363, + "type": "User", + "contributions": 1 + }, + { + "name": "Salar K", + "email": "1272095+salarcode@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Safia Abdalla", + "email": "safia@safia.rocks", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ryo Tsunoda", + "email": "try0.development@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ryan Robidou", + "email": "robidou@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ryan Davis", + "email": "ryandavis.au@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ryan Buckley", + "email": "9486206+rabuckley@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Rui Marinho", + "email": "ruimarinho@msft-m3-pro.ihome", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Roy", + "email": "royvou@hotmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ronny Gunawan", + "email": "3048897+ronnygunawan@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Ronan", + "email": "burkuscat@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Roger Hardiman", + "email": "rogerhardiman@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Rasto", + "email": "rasto@duracellko.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Rastislav Novotný", + "email": "rasto@duracellko.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Raka Rasell", + "email": "rrrraka@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Rafal", + "email": "rkdevel@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Precious Nyasulu", + "email": "preciousnyasulu441@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Praga Siva", + "email": "praga@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Poppyto", + "email": "poppyto@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Pieter Nijs", + "email": "pieternijs@live.be", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Pierre Henri", + "email": "pierrehenrikt@kleartouch.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Pierre Galaup", + "email": "pierregalaup@outlook.fr", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Philipp Sumi", + "email": "hardcodet@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Phil Henning", + "email": "phenning@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "nextfool", + "email": "nextfool@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "nels83", + "email": "nels+git@pgroupe.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "nalka0", + "email": "30848600+nalka0@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "mos379", + "email": "45105519+mos379@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "mohsen bagheri", + "email": "85581484+mohsenbgi@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "michalpobuta", + "email": "52126292+michalpobuta@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "matt4pi", + "email": "matt@4pi.com.au", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "masonyc", + "email": "mason.yunchen@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "mallibone", + "email": "mallibone@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "maexsp", + "email": "maex.sp@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "luyajun0205", + "email": "v-yajlu@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "lewcianci", + "email": "lewcianci@hotmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "kadiryazgan", + "email": "kadiryazgan@msn.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "juliuszint", + "email": "julius.zint@awin-software.de", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "jpiechowiak", + "email": "jerzy.piechowiak@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "jonlipsky", + "email": "jonlipsky@github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "john-larson", + "email": "21021544+john-larson@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "joepgrooten", + "email": "52749854+joepgrooten@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "jaytilly", + "email": "jt@jaybirdlabs.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "jacobmcgoogan", + "email": "jacob.mcgoogan@allscripts.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "inforithmics", + "email": "thomas.stocker@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "indydawgy", + "email": "tophe112@yahoo.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Xiangwei Cai", + "email": "v-caxian@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "zhuXinghan", + "email": "1097278366@qq.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "z3ut", + "email": "z3ut@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "ytn3rd", + "email": "b.moore@4pilabs.com.au", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "yone64", + "email": "yone64@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "wplong11", + "email": "wplong11@naver.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "woutermeuwis", + "email": "wouter.meuwis@3factr.be", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "webwarrior-ws", + "email": "webwarrior-ws@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "weases", + "email": "richard.wiesinger@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "v-haroha", + "email": "51649153+v-haroha@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "tomeverin", + "email": "24466690+tomeverin@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "tj-devel709", + "email": "tj.devel709@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "thisisthekap", + "email": "christian.kapplmueller@tonestro.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "thisisthekap", + "email": "c.kapplmueller@me.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "spruceDevelopment", + "email": "33689503+sprucedevelopment@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "softlion", + "email": "benjamin@vapolia.fr", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "sheiksyedm", + "email": "sheiksyedm@syncfusion.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "sahi82", + "email": "sahi82@yahoo.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "rjantz3", + "email": "rjantz3@msn.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "qmark", + "email": "dimka.qmark@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "pit", + "email": "37137614+pitmobile@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "piotrkonowalski", + "email": "piotrkonowalski@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "pRopia", + "email": "pratik.ropia@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "nor0x", + "email": "nor0x@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Will Davies", + "email": "wdavies973@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "WdeBruin", + "email": "wouterdebruin88@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vũ Đức Tuyến", + "email": "tuyen@naxam.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Víctor Martos", + "email": "vmareg@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Víctor Guzmán", + "email": "vgzman+github@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vojtěch Mádr", + "email": "madrvojtech@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vlada Shubina", + "email": "vshubina@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vinicius Jarina", + "email": "viniciusjarina@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vincent Hoogendoorn", + "email": "vincenth.net@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vincent Dondain", + "email": "vincentdondain@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vincent Costel", + "email": "vincent.costel@apcurium.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Vijay Anand E G", + "email": "81947404+egvijayanand@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tushar Koshti", + "email": "koshtitushar1994@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Trung Nguyen", + "email": "57174311+trungnt2910@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Trivalik", + "email": "3148279+trivalik@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Toni Petrina", + "email": "tonipetrina@hotmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tomáš Ondřej", + "email": "45392392+tomond@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tommi Gustafsson", + "email": "tommi.gustafsson@hyvanmielenpelit.fi", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tomasz Ścisłowicz", + "email": "toomasz@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tomasz Cielecki", + "email": "249719+cheesebaron@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tom Meschter", + "email": "tom.meschter@valinor.org", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Tom Gilder", + "email": "tom@tom.me.uk", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "hydrogen-software-ff", + "email": "81678363+hydrogen-software-ff@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "humhei", + "email": "humhei@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "gleblebedev", + "email": "gleb@gleblebedev.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "genriquez", + "email": "genriquez@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "fengrui", + "email": "fengrui358@163.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "dottienet", + "email": "61212782+dottienet@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "dogukandemir", + "email": "dogukandemir@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "digitaldirk", + "email": "22691956+digitaldirk@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "dgeller-OUHSC", + "email": "dgeller@ouhsc.edu", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "dartasen", + "email": "10561268+dartasen@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "cliff v", + "email": "powerdude@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "ckrempp91", + "email": "chrisk@msidata.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "chenrensong", + "email": "chenrensong@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "cat0363", + "email": "125236133+cat0363@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "borrmann", + "email": "max.borrmann@gmx.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "atoghyani", + "email": "ariantoghyani@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "adammeaney", + "email": "meaneykid2@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "acuntex", + "email": "werner@welsch.cc", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Yusuke Yamada", + "email": "yamachu.dev@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Yunus Efendi", + "email": "19399214+yunusefendi52@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Yun Chen", + "email": "mason.yunchen@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Youssef Victor", + "email": "31348972+youssef1313@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Yaser Moradi", + "email": "ysmoradi@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "LyalinDotCom", + "id": 2363526, + "type": "User", + "contributions": 1 + }, + { + "login": "ChasakisD", + "id": 23040695, + "type": "User", + "contributions": 1 + }, + { + "login": "humblehacker", + "id": 117582, + "type": "User", + "contributions": 1 + }, + { + "login": "EislerDavid", + "id": 48833197, + "type": "User", + "contributions": 1 + }, + { + "login": "davidbritch", + "id": 8092460, + "type": "User", + "contributions": 1 + }, + { + "name": "Dave Humphreys", + "email": "dave@none.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "danielwilliamson", + "id": 6487407, + "type": "User", + "contributions": 1 + }, + { + "login": "danielmarbach", + "id": 174258, + "type": "User", + "contributions": 1 + }, + { + "login": "danielchalmers", + "id": 7112040, + "type": "User", + "contributions": 1 + }, + { + "login": "danmoseley", + "id": 6385855, + "type": "User", + "contributions": 1 + }, + { + "login": "DamianMehers", + "id": 1457446, + "type": "User", + "contributions": 1 + }, + { + "login": "dkarzon", + "id": 214449, + "type": "User", + "contributions": 1 + }, + { + "login": "Csaba8472", + "id": 483692, + "type": "User", + "contributions": 1 + }, + { + "login": "craigloewen-msft", + "id": 42221804, + "type": "User", + "contributions": 1 + }, + { + "login": "CleanCodeDeveloper", + "id": 16760760, + "type": "User", + "contributions": 1 + }, + { + "login": "csdinon", + "id": 24420845, + "type": "User", + "contributions": 1 + }, + { + "login": "Choza-rajan", + "id": 92723643, + "type": "User", + "contributions": 1 + }, + { + "login": "Chase-William", + "id": 46757278, + "type": "User", + "contributions": 1 + }, + { + "login": "ChaseMarsh", + "id": 19700403, + "type": "User", + "contributions": 1 + }, + { + "login": "charlesroddie", + "id": 19760720, + "type": "User", + "contributions": 1 + }, + { + "name": "Charles Petzold", + "email": "chape@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "kvochko", + "id": 2308830, + "type": "User", + "contributions": 1 + }, + { + "name": "Max Brister", + "email": "a+github@2bass.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "Giviruk", + "id": 42971690, + "type": "User", + "contributions": 1 + }, + { + "login": "giuseppe-guerra", + "id": 11569903, + "type": "User", + "contributions": 1 + }, + { + "login": "Ghostbird", + "id": 1202149, + "type": "User", + "contributions": 1 + }, + { + "login": "tarasverq", + "id": 8226275, + "type": "User", + "contributions": 1 + }, + { + "login": "JoergMeier106", + "id": 22917826, + "type": "User", + "contributions": 1 + }, + { + "login": "gabor-nemeth", + "id": 37656640, + "type": "User", + "contributions": 1 + }, + { + "login": "FriedrichRehren", + "id": 22966022, + "type": "User", + "contributions": 1 + }, + { + "login": "fredyadriano90", + "id": 25233851, + "type": "User", + "contributions": 1 + }, + { + "login": "kiok85", + "id": 158862689, + "type": "User", + "contributions": 1 + }, + { + "login": "francedot", + "id": 11706033, + "type": "User", + "contributions": 1 + }, + { + "login": "fenxu", + "id": 12146082, + "type": "User", + "contributions": 1 + }, + { + "login": "IIFabixn", + "id": 92400234, + "type": "User", + "contributions": 1 + }, + { + "login": "EP01", + "id": 22454118, + "type": "User", + "contributions": 1 + }, + { + "login": "eth-ellis", + "id": 13865151, + "type": "User", + "contributions": 1 + }, + { + "login": "Eschryn", + "id": 8217655, + "type": "User", + "contributions": 1 + }, + { + "login": "modplug", + "id": 789588, + "type": "User", + "contributions": 1 + }, + { + "login": "jingliancui", + "id": 16309962, + "type": "User", + "contributions": 1 + }, + { + "login": "eliaspuurunen", + "id": 695294, + "type": "User", + "contributions": 1 + }, + { + "login": "Elashi", + "id": 12378171, + "type": "User", + "contributions": 1 + }, + { + "login": "wachs", + "id": 12235778, + "type": "User", + "contributions": 1 + }, + { + "name": "Edwin Wachs", + "email": "edwin.wachs@tecfinance.com.br", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "Eden-Mor", + "id": 20691183, + "type": "User", + "contributions": 1 + }, + { + "name": "Andrew Hoefling", + "email": "andrew@hoeflingsoftware.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "awaescher", + "id": 3630638, + "type": "User", + "contributions": 1 + }, + { + "login": "AndersRasmussen", + "id": 213707, + "type": "User", + "contributions": 1 + }, + { + "login": "AmrAlSayed0", + "id": 2955032, + "type": "User", + "contributions": 1 + }, + { + "login": "AlleSchonWeg", + "id": 6727366, + "type": "User", + "contributions": 1 + }, + { + "login": "aritchie", + "id": 1431555, + "type": "User", + "contributions": 1 + }, + { + "login": "alfredmyers", + "id": 12210687, + "type": "User", + "contributions": 1 + }, + { + "login": "AxelUser", + "id": 7935489, + "type": "User", + "contributions": 1 + }, + { + "login": "cacti-acaprais", + "id": 43949501, + "type": "User", + "contributions": 1 + }, + { + "login": "NordAlex", + "id": 6042648, + "type": "User", + "contributions": 1 + }, + { + "login": "ahouben", + "id": 2446666, + "type": "User", + "contributions": 1 + }, + { + "name": "Alexander Hardwicke", + "email": "alex.hardwicke@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "Pandalink", + "id": 18328783, + "type": "User", + "contributions": 1 + }, + { + "login": "adrianhall", + "id": 1489465, + "type": "User", + "contributions": 1 + }, + { + "login": "adamsitnik", + "id": 6011991, + "type": "User", + "contributions": 1 + }, + { + "login": "APoukar", + "id": 36044908, + "type": "User", + "contributions": 1 + }, + { + "name": "Adam Pedley", + "email": "adam.pedley@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "adamivancza", + "id": 19835917, + "type": "User", + "contributions": 1 + }, + { + "login": "adambarath", + "id": 14049972, + "type": "User", + "contributions": 1 + }, + { + "login": "1iveowl", + "id": 12871120, + "type": "User", + "contributions": 1 + }, + { + "login": "1d0n7kn0w", + "id": 3910210, + "type": "User", + "contributions": 1 + }, + { + "login": "1c3f0x84", + "id": 35239416, + "type": "User", + "contributions": 1 + }, + { + "name": "Chad Kimes", + "email": "chad.kimes@iticentral.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "kericbowman", + "id": 12725288, + "type": "User", + "contributions": 1 + }, + { + "login": "breezy64", + "id": 3731287, + "type": "User", + "contributions": 1 + }, + { + "login": "bkaankose", + "id": 12009960, + "type": "User", + "contributions": 1 + }, + { + "login": "Brucepimenta", + "id": 37835327, + "type": "User", + "contributions": 1 + }, + { + "login": "brainoffline", + "id": 1763877, + "type": "User", + "contributions": 1 + }, + { + "login": "bradencohen", + "id": 11482832, + "type": "User", + "contributions": 1 + }, + { + "login": "TrueGeek", + "id": 90821, + "type": "User", + "contributions": 1 + }, + { + "login": "bbenetskyy", + "id": 8330262, + "type": "User", + "contributions": 1 + }, + { + "name": "Bohdan Benetskyi", + "email": "bbenetskyi@pgs-soft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "bwoebi", + "id": 3154871, + "type": "User", + "contributions": 1 + }, + { + "login": "BinaryCraX", + "id": 5560801, + "type": "User", + "contributions": 1 + }, + { + "login": "billvenhaus", + "id": 6692379, + "type": "User", + "contributions": 1 + }, + { + "login": "BenBtg", + "id": 70525, + "type": "User", + "contributions": 1 + }, + { + "login": "baskren", + "id": 2528888, + "type": "User", + "contributions": 1 + }, + { + "login": "BarryNolte", + "id": 4474173, + "type": "User", + "contributions": 1 + }, + { + "login": "BaY1251", + "id": 48309205, + "type": "User", + "contributions": 1 + }, + { + "login": "axelgorris", + "id": 11756311, + "type": "User", + "contributions": 1 + }, + { + "login": "atsushieno", + "id": 53929, + "type": "User", + "contributions": 1 + }, + { + "login": "artemutin", + "id": 7271331, + "type": "User", + "contributions": 1 + }, + { + "login": "mellson", + "id": 167574, + "type": "User", + "contributions": 1 + }, + { + "login": "AndrewLang", + "id": 3375370, + "type": "User", + "contributions": 1 + }, + { + "login": "AndreKraemer", + "id": 312671, + "type": "User", + "contributions": 1 + }, + { + "name": "Mausam Shrestha", + "email": "46900712+mausam-shrestha@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mauro Agnoletti", + "email": "mauro.agnoletti@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mattias Sjögren", + "email": "github@msjogren.net", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matthijs ter Woord", + "email": "matthijsterwoord@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matthew Robbins", + "email": "matthew.ch.robbins@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Ward", + "email": "ward.matt@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Ward", + "email": "matt.ward@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Soucoup", + "email": "masoucou@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Regul", + "email": "mareg@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Mitchell", + "email": "mmitche@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Matt Goldman", + "email": "matt.goldman@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mathias Storm", + "email": "mathias@storm.lc", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mateus Luiz Camilo", + "email": "37350787+mathewlc@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Martin Kuckert", + "email": "m.kuckert@salt-and-pepper.eu", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Martin", + "email": "modermatt@tuta.io", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Martijn van Dijk", + "email": "mhvdijk@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mark", + "email": "mrcull@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "Marioo1357", + "id": 45981364, + "type": "User", + "contributions": 1 + }, + { + "login": "MariovanZeist", + "id": 12493059, + "type": "User", + "contributions": 1 + }, + { + "login": "Marcus-L", + "id": 1369184, + "type": "User", + "contributions": 1 + }, + { + "login": "mgierlasinski", + "id": 19707868, + "type": "User", + "contributions": 1 + }, + { + "login": "john-hollander", + "id": 11653688, + "type": "User", + "contributions": 1 + }, + { + "name": "Nicolò Carandini", + "email": "ncarandini@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "NicolD", + "email": "nicolgit@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Nick Kovalsky", + "email": "taublast@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Nick Gamroth", + "email": "thebeekeeper@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Neville Nazerane", + "email": "31866047+neville-nazerane@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Muzib", + "email": "thisismuzib@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mitchell Hwang", + "email": "16830051+mdh1418@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mikhail", + "email": "om2804@mail.ru", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mike Schwörer", + "email": "mailport@mikescher.de", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mike Parker", + "email": "mjbparker@outlook.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mike Parker", + "email": "mikeparker104", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mike Norman", + "email": "mike.norman@xamarin.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mike Irving", + "email": "79252299+mikeirvingweb@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mihhail Maslakov", + "email": "mihhail.maslakov@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael Yanni", + "email": "miyanni@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael S. Scherotter", + "email": "mischero@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael Dwan", + "email": "m@dwan.io", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael Cummings (MSFT)", + "email": "mcumming@microsoft.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael Cao", + "email": "poppop208@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Michael", + "email": "michael@zpf.fr", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Mendy Berger", + "email": "12537668+mendyberger@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "MemeMan", + "email": "52583316+imememani@users.noreply.github.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "name": "Maximo Piva", + "email": "maximo.piva@gmail.com", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "johannesegger", + "id": 237707, + "type": "User", + "contributions": 1 + }, + { + "login": "johankson", + "id": 1113636, + "type": "User", + "contributions": 1 + }, + { + "login": "JogyBlack", + "id": 1275686, + "type": "User", + "contributions": 1 + }, + { + "name": "Joakim Carselind", + "email": "joakim.carselind@cub.se", + "type": "Anonymous", + "contributions": 1 + }, + { + "login": "jimbobbennett", + "id": 1710385, + "type": "User", + "contributions": 1 + }, + { + "login": "jrjrguo", + "id": 27794646, + "type": "User", + "contributions": 1 + }, + { + "login": "Powerhelmsman", + "id": 33136632, + "type": "User", + "contributions": 1 + }, + { + "login": "solvingj", + "id": 8557737, + "type": "User", + "contributions": 1 + }, + { + "login": "lirkki", + "id": 665778, + "type": "User", + "contributions": 1 + }, + { + "login": "JanKrivanek", + "id": 3809076, + "type": "User", + "contributions": 1 + }, + { + "login": "JimBobSquarePants", + "id": 385879, + "type": "User", + "contributions": 1 + }, + { + "login": "licon4812", + "id": 32421608, + "type": "User", + "contributions": 1 + }, + { + "login": "jadenrogers", + "id": 8000621, + "type": "User", + "contributions": 1 + }, + { + "login": "lamest", + "id": 7779341, + "type": "User", + "contributions": 1 + }, + { + "login": "RussKie", + "id": 4403806, + "type": "User", + "contributions": 1 + }, + { + "login": "ice-j", + "id": 3597015, + "type": "User", + "contributions": 1 + }, + { + "login": "ChummerUA", + "id": 12427312, + "type": "User", + "contributions": 1 + }, + { + "login": "hemantbeast", + "id": 10476066, + "type": "User", + "contributions": 1 + }, + { + "login": "Happypig375", + "id": 19922066, + "type": "User", + "contributions": 1 + }, + { + "login": "tracplus-hpaterson", + "id": 87885287, + "type": "User", + "contributions": 1 + }, + { + "login": "gatm50", + "id": 440179, + "type": "User", + "contributions": 1 + }, + { + "login": "GuidoNeele", + "id": 1301586, + "type": "User", + "contributions": 1 + }, + { + "login": "MarcelStommel", + "id": 45386201, + "type": "User", + "contributions": 1 + }, + { + "login": "FaithfulDev", + "id": 16925901, + "type": "User", + "contributions": 1 + }, + { + "login": "manishkungwani", + "id": 673367, + "type": "User", + "contributions": 1 + }, + { + "login": "mairaw", + "id": 12971179, + "type": "User", + "contributions": 1 + }, + { + "login": "MagicAndre1981", + "id": 8274816, + "type": "User", + "contributions": 1 + }, + { + "login": "guardrex", + "id": 1622880, + "type": "User", + "contributions": 1 + }, + { + "login": "lizharems", + "id": 103444841, + "type": "User", + "contributions": 1 + }, + { + "login": "leoMehlig", + "id": 9119485, + "type": "User", + "contributions": 1 + }, + { + "login": "rs-lkroneman", + "id": 66680815, + "type": "User", + "contributions": 1 + }, + { + "login": "lobrien", + "id": 181571, + "type": "User", + "contributions": 1 + }, + { + "login": "lewing", + "id": 24063, + "type": "User", + "contributions": 1 + }, + { + "login": "KyNam", + "id": 1797185, + "type": "User", + "contributions": 1 + }, + { + "login": "pineapple216", + "id": 7579094, + "type": "User", + "contributions": 1 + }, + { + "login": "koviant", + "id": 23036313, + "type": "User", + "contributions": 1 + }, + { + "login": "thekbb", + "id": 8903473, + "type": "User", + "contributions": 1 + }, + { + "login": "kentcb", + "id": 1901832, + "type": "User", + "contributions": 1 + }, + { + "login": "khuongntrd", + "id": 8498480, + "type": "User", + "contributions": 1 + }, + { + "login": "dahlbyk", + "id": 133987, + "type": "User", + "contributions": 1 + }, + { + "login": "Kahbazi", + "id": 19396090, + "type": "User", + "contributions": 1 + }, + { + "login": "garuma", + "id": 104105, + "type": "User", + "contributions": 1 + }, + { + "login": "tondat", + "id": 383380, + "type": "User", + "contributions": 1 + }, + { + "login": "JFMG", + "id": 100067782, + "type": "User", + "contributions": 1 + }, + { + "login": "Jon2G", + "id": 24820069, + "type": "User", + "contributions": 1 + } +] diff --git a/.github/prompts/release_notes.prompt.md b/.github/prompts/release_notes.prompt.md new file mode 100644 index 000000000000..4210177b4ed1 --- /dev/null +++ b/.github/prompts/release_notes.prompt.md @@ -0,0 +1,419 @@ +# .NET MAUI Release Notes Generator + +You are an Open Source release notes generator assistant responsible for classifying and generating comprehensive release notes between two commits from the repository the user specifies. + +## Understanding Categories + +You will classify all commits into exactly ONE of the following categories: + +1. **MAUI Product Fixes**: Bug fixes, improvements, and features related to the MAUI product itself +2. **Dependency Updates**: Updates to dependencies, packages, libraries, or SDKs +3. **Testing**: Test-related changes, test infrastructure, and test improvements +4. **Docs**: Documentation changes, samples, and tutorials +5. **Housekeeping**: Build system changes, CI pipeline, code cleanup, formatting, and any other changes + +Every commit must be classified into exactly one category. When uncertain about where to place a commit, follow the classification rules below or default to Housekeeping. + +## Process for Creating Release Notes + +When asked to create release notes for a particular branch, follow these steps: + +### 1. Finding the Commits to Compare + +* When user specifies two branches or commits, use these for comparison +* If only one branch/commit is provided, you'll need to determine the previous release point, ask the user to tell you what is the previous release branch you can try something like `git branch -a | grep -E "release/10.0.*preview"` +* If needed, ask the user for the comparison point or the previous branch + +### 2. Retrieving the Commit Log + +* Use `git log` or equivalent to get the commits between the two commits/branches and save it to a file like this exmaple `git log --pretty=format:"%h - %s - #%cd (%an - %ae)" --date=short release/10.0.1xx-preview2..release/10.0.1xx-preview3 > release_notes_commits.txt` +* Ensure you capture all commits within the specified range +* Pay attention to merge commits that might indicate important feature merges + +### 3. Find the correct Github username for each commit + +* For each commit on the list, look up the corresponding GitHub username from the actual GitHub PR, not just the commit author email +* Use the `get_pull_request` tool if available to fetch the actual PR information including the correct GitHub username that created the PR +* Use the [text](contributors.json) file to help map commit authors to GitHub usernames +* When encountering an email address in a commit author, check if it exists in the contributors.json file and use the corresponding GitHub login +* Verify all usernames are consistent with GitHub's format (e.g., @jsuarezruiz instead of @javiersuarezruiz) +* Some common username transformations to check for: + - Internal usernames may differ from GitHub usernames + - Email addresses should be converted to GitHub handles + - Employee IDs or numbers in usernames should be included if they are part of the GitHub username (e.g., @HarishKumarSF4517 not @harish.kumar) +* Keep the '@' prefix for all usernames to maintain consistency +* For "Anonymous" type contributors in [text](contributors.json), use their name as shown but try to find their corresponding GitHub username if possible +* For automated systems like dependabot or github-actions, use the standard bot usernames (@dependabot[bot], @github-actions[bot], etc.) + +### 4. Classifying the Commits + +To help when doing your category analizing use lower case of the commit messages +Apply these classification rules: + +* **MAUI Product Fixes**: + - Bug fixes with platform tags like [iOS], [Android], [Windows], [Mac], [MacCatalyst], [android], [x], [xaml], [core], [ios], [android], [windows], [mac], [maccatalyst] + - Feature additions or improvements to MAUI components + - Performance improvements + - API changes and enhancements + - New features or fixes related to Aspire + - Remove for fixing pending TODOs + - Trimmer and AOT related changes + +* **Testing**: + - Has tag [testing], [test], [uitests] or contains terms like "test", "add test", "UI test", "unit test", "UItests", "uitests", if any of these exists the commit is from Testing category + - Changes to test infrastructure, test frameworks, or CI test configurations + - Test coverage improvements + +* **Docs**: + - Has tag [docs] or contains terms like "documentation", "docs", "sample", "example" + - README updates, API documentation, code comments + - No other commits should belong here + +* **Dependency Updates**: + - Updates to package references, dependencies, or SDKs + - Commits from automation bots updating dependencies (e.g., @dotnet-maestro) + - Version bumps of external libraries + - Changes to NuGet packages + +* **Housekeeping**: + - CI pipeline changes, formatting fixes, repo maintenance + - Build system modifications, tooling updates + - Refactoring with no functional changes + - Any commit that doesn't clearly fit other categories + - Merging a branch to another branch + - Has tag [ci] + + +### 5. Organizing for the Response + +* Group commits by category as defined in section 1 +* Within each category, list in descending order by PR number (newest PRs first) +* For PR numbers: + - Ensure they are formatted as '#XXXXX' (e.g., #28804) + - When creating GitHub links, use full URLs: https://github.com/dotnet/maui/pull/XXXXX +* For contributor attribution: + - Use ONLY the GitHub username that appears in the PR, not the commit author + - Always prefix usernames with '@' (e.g., @kubaflo) + - Be especially careful with usernames that have employee IDs or numbers at the end + - For automated actions, use @github-actions or @dotnet-bot as appropriate +* Save the results to a markdown file like docs/release_notes_{releasename}.md + +### 6. Special Cases & Edge Cases + +* **Reverts**: Classify reverted commits to the same category as the original commit +* **Automated PRs**: Place automation-driven changes (like dependency updates) in appropriate categories like Dependency Updates +* **Cross-cutting changes**: When a commit spans multiple categories, prioritize based on the primary focus +* **Breaking changes**: Highlight any breaking changes prominently in the summary +* **New contributors**: Include a separate section acknowledging first-time contributors + +## Response Format + +Structure your release notes in the following categorized format, and save them to a file like docs/release_notes_{releasename}.md: + +```markdown +### MAUI Product Fixes +* [Commit title] by @[correct-github-username] in https://github.com/dotnet/maui/pull/[PR number] +* ... + +### Testing +* [Commit title] by @[correct-github-username] in https://github.com/dotnet/maui/pull/[PR number] +* ... + +### Dependency Updates +* [Commit title] by @[correct-github-username] in https://github.com/dotnet/maui/pull/[PR number] +* ... + +### Docs +* [Commit title] by @[correct-github-username] in https://github.com/dotnet/maui/pull/[PR number] +* ... + +### Housekeeping +* [Commit title] by @[correct-github-username] in https://github.com/dotnet/maui/pull/[PR number] +* ... + +## New Contributors +* @[correct-github-username] made their first contribution in https://github.com/dotnet/maui/pull/[PR number] +* ... + +**Full Changelog**: https://github.com/dotnet/maui/compare/[previous-branch]...[current-branch] +``` + +## Contributors list + +[text](contributors.json) + + +## Example + +Here's a shortened example of properly formatted release notes: + +## What's Changed + +* Internalize/remove MessagingCenter by @jfversluis in https://github.com/dotnet/maui/pull/27842 +* [release/10.0.1xx-preview2] Obsolete TableView by @github-actions in https://github.com/dotnet/maui/pull/28327 + +### MAUI Product Fixes +* Radio button's default template improvements by @kubaflo in https://github.com/dotnet/maui/pull/26719 +* [Windows] - Fixed Window Title Not Shown When Reverting from TitleBar to Default State by @prakashKannanSf3972 in https://github.com/dotnet/maui/pull/27148 +* [Windows] Fixed Margin Not Applied to Shell Flyout Template Items on First Display by @prakashKannanSf3972 in https://github.com/dotnet/maui/pull/27060 +* [iOS] Fix for Left SwipeView Items Conflict with Shell Menu Swipe Gesture by @Tamilarasan-Paranthaman in https://github.com/dotnet/maui/pull/26976 +* [iOS]Fix for Character Spacing Not Updating Correctly in Editor for Dynamically Added Text by @devanathan-vaithiyanathan in https://github.com/dotnet/maui/pull/25347 +* Make ImageSource more async-friendly by @symbiogenesis in https://github.com/dotnet/maui/pull/22098 +* [XC] don't call ProvideValue on compiled bindings by @StephaneDelcroix in https://github.com/dotnet/maui/pull/27509 +* [XC] trim x:Name values by @StephaneDelcroix in https://github.com/dotnet/maui/pull/27452 +* [Mac] TitleBar not always initally set by @tj-devel709 in https://github.com/dotnet/maui/pull/27487 +* [X] don't expand types to Extension for x:Static by @StephaneDelcroix in https://github.com/dotnet/maui/pull/17276 +* Fix Android TextView being truncated under some conditions by @albyrock87 in https://github.com/dotnet/maui/pull/27179 +* Improve debugger display XP by @pictos in https://github.com/dotnet/maui/pull/27489 +* [Windows]Fixed Shell Navigating event issue when switching tabs by @Vignesh-SF3580 in https://github.com/dotnet/maui/pull/27197 +* Revert "Implementation of Customizable Search Button Color for SearchBar Across Platforms (#26759)" by @jfversluis in https://github.com/dotnet/maui/pull/27568 +* [net10.0] Revert "Implementation of Customizable Search Button Color for SearchBar Across Platforms (#26759)" by @github-actions in https://github.com/dotnet/maui/pull/27578 +* Use TCS for BusySetSignalName tests by @PureWeen in https://github.com/dotnet/maui/pull/27583 +* [Windows] - Resolved FlyoutBehavior "Locked" State Reset Issue After Navigation by @prakashKannanSf3972 in https://github.com/dotnet/maui/pull/27379 +* Fixed the vertical orientation issue in the CarouselViewHandler2 on iOS by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27273 +* [Android] Fixed the CarouselView Items overlap issue with PeekAreaInsets by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27499 +* Fixed CollectionView's HeaderTemplate is not rendering in iOS and MacCatalyst platform. by @KarthikRajaKalaimani in https://github.com/dotnet/maui/pull/27466 +* Obsolete iOS Compatibility AccessibilityExtensions by @jfversluis in https://github.com/dotnet/maui/pull/27593 +* Make HybridWebView.InvokeJavaScriptAsync public by @jfversluis in https://github.com/dotnet/maui/pull/27594 +* Replace Android ToSpannableString overload by @jfversluis in https://github.com/dotnet/maui/pull/27597 +* [net10.0] Set `UseRidGraph=false` on Windows by @MartyIX in https://github.com/dotnet/maui/pull/27595 +* Reapply "Implementation of Customizable Search Button Color for Search Across Platforms (#26759)" by @jfversluis in https://github.com/dotnet/maui/pull/27586 +* [Android] Fix for Flyout closing when updating the FlyoutPage.Detail by @Tamilarasan-Paranthaman in https://github.com/dotnet/maui/pull/26425 +* Fix for [Windows]ToolbarItem visibility until Page Disappearing by @SuthiYuvaraj in https://github.com/dotnet/maui/pull/26915 +* [net10.0] Set `UseRidGraph=false` on Windows (2) by @MartyIX in https://github.com/dotnet/maui/pull/27634 +* Fix for MenuFlyoutItem stops working after navigating away from and back to page by @BagavathiPerumal in https://github.com/dotnet/maui/pull/25170 +* Fix Issue13551 to use WaitForElement by @PureWeen in https://github.com/dotnet/maui/pull/27644 +* [Android] Fix Flickering issue when calling Navigation.PopAsync by @devanathan-vaithiyanathan in https://github.com/dotnet/maui/pull/24887 +* Fix GC Race condition with tests by @PureWeen in https://github.com/dotnet/maui/pull/27652 +* Fix 19647 by @StephaneDelcroix in https://github.com/dotnet/maui/pull/20127 +* [net10.0] Make CV2 default for net10 by @rmarinho in https://github.com/dotnet/maui/pull/27567 +* Timeout Android emulator start by @PureWeen in https://github.com/dotnet/maui/pull/27657 +* [net10] Revert Windows RID graph changes by @jfversluis in https://github.com/dotnet/maui/pull/27671 +* BindableLayout should disconnect handlers by @albyrock87 in https://github.com/dotnet/maui/pull/27450 +* Improve shadow rendering on Android, fix shadow clipping on iOS by @albyrock87 in https://github.com/dotnet/maui/pull/26789 +* [X] deprecate fontImageExtension by @StephaneDelcroix in https://github.com/dotnet/maui/pull/23657 +* 26598 - Fix for Tabbar disappears when navigating back from page with hidden TabBar in iOS 18 by @SuthiYuvaraj in https://github.com/dotnet/maui/pull/27582 +* Avoid compiler error when using init properties with BindingSourceGenerator by @rabuckley in https://github.com/dotnet/maui/pull/27655 +* Make iOS WebView delegates virtual by @jfversluis in https://github.com/dotnet/maui/pull/27601 +* Improve TextToSpeech function by adding a speech rate parameter by @Zerod159 in https://github.com/dotnet/maui/pull/24798 +* Adds very basic CSS support for Border by @sthewissen in https://github.com/dotnet/maui/pull/27529 +* [iOS] Added PermissionStatus.Limited for Contacts by @kubaflo in https://github.com/dotnet/maui/pull/27694 +* Make some internal methods public by @jfversluis in https://github.com/dotnet/maui/pull/27598 +* Add support for iOS/Mac specific modals styled as popovers by @piersdeseilligny in https://github.com/dotnet/maui/pull/23984 +* Adds CSS support for shadows and a simpler way of defining shadows in XAML by @sthewissen in https://github.com/dotnet/maui/pull/27180 +* Fix the Collection view empty view not fill the vertical space by @Shalini-Ashokan in https://github.com/dotnet/maui/pull/27464 +* [Windows] Fix for SearchHandler.Focused and Unfocused event never fires by @BagavathiPerumal in https://github.com/dotnet/maui/pull/27577 +* [Android] Fix Cursor Not Closing in File Picker to Prevent Log Spam. by @bhavanesh2001 in https://github.com/dotnet/maui/pull/27718 +* [Android] Fixed the SoftInputMode issues with modal pages by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27553 +* [iOS] Fix Gray Line Appears on the Right Side of GraphicsView with Decimal WidthRequest by @devanathan-vaithiyanathan in https://github.com/dotnet/maui/pull/26368 +* Page cannot scroll to the bottom while using RoundRectangle by @Dhivya-SF4094 in https://github.com/dotnet/maui/pull/27451 +* Support for Setting Switch Off State Color by @devanathan-vaithiyanathan in https://github.com/dotnet/maui/pull/25068 +* [iOS] Fix ShellContent Title Does Not Update at Runtime by @devanathan-vaithiyanathan in https://github.com/dotnet/maui/pull/26062 +* Fixed [iOS] Navigation breaks when modal pages use PageSheet by @NanthiniMahalingam in https://github.com/dotnet/maui/pull/27765 +* BarBackground with Brush in TabbedPage on theme change by @kubaflo in https://github.com/dotnet/maui/pull/24425 +* [iOS] Using long-press navigation on back button with shell pages - fix by @kubaflo in https://github.com/dotnet/maui/pull/24003 +* Fix for DatePicker displays incorrect date selection when navigating to next month. by @BagavathiPerumal in https://github.com/dotnet/maui/pull/26064 +* Fixed Unnecessary SizeChanged Event Triggering by @Dhivya-SF4094 in https://github.com/dotnet/maui/pull/27476 +* [Essentials] Longitude Validation by @kubaflo in https://github.com/dotnet/maui/pull/27784 +* Fixed latitude->longitude typo by @kubaflo in https://github.com/dotnet/maui/pull/27834 +* [iOS] CollectionView with header or footer has incorrect height - fix by @kubaflo in https://github.com/dotnet/maui/pull/27809 +* Fix concurrency issues and leak reliability by @PureWeen in https://github.com/dotnet/maui/pull/27815 +* [iOS] Fixed the Application crash when ToolbarItem is created with invalid IconImageSource name by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27175 +* Revert "Fix concurrency issues and leak reliability" by @rmarinho in https://github.com/dotnet/maui/pull/27870 +* [Android] Fix app crash caused by dynamic template switching in ListView by @BagavathiPerumal in https://github.com/dotnet/maui/pull/24808 +* Don't need to register ApplicationStub by @PureWeen in https://github.com/dotnet/maui/pull/27885 +* Fixed Toolbar IconImageSource not updating with Binding Changes by @NirmalKumarYuvaraj in https://github.com/dotnet/maui/pull/27402 +* [iOS] Fixed a crash in CarouselViewHandler2 on iOS 15. by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27871 +* [Android] Android: Native View not set exception on modal page - fix by @kubaflo in https://github.com/dotnet/maui/pull/27891 +* [iOS/MacCatalyst] Use newer API in FilePicker by @MartyIX in https://github.com/dotnet/maui/pull/27521 +* [Android] Map FlowDirection of shell to PlatformView on Android by @mohsenbgi in https://github.com/dotnet/maui/pull/23473 +* Fix CSS Hot Reload - Handle fingerprint when hot reloading scoped CSS bundles by @spadapet in https://github.com/dotnet/maui/pull/27788 +* [iOS] CV1's footer doesn't increase its size - fix by @kubaflo in https://github.com/dotnet/maui/pull/27979 +* [iOS] CollectionView 1's doesn't adjust its offset when resizing a footer by @kubaflo in https://github.com/dotnet/maui/pull/27963 +* [Android] Properly Resolve File Paths in FilePicker When MANAGE_EXTERNAL_STORAGE is Granted by @bhavanesh2001 in https://github.com/dotnet/maui/pull/27975 +* [net10.0] Set `UseRidGraph=false` on Windows (attempt 2) by @MartyIX in https://github.com/dotnet/maui/pull/27679 +* [Android] Fix crash starting the swipe on SwipeView inside CollectionView by @jsuarezruiz in https://github.com/dotnet/maui/pull/27669 +* Applying visibility change to child controls by @kubaflo in https://github.com/dotnet/maui/pull/20154 +* Fixed CheckBox enabled color is not updated properly by @NanthiniMahalingam in https://github.com/dotnet/maui/pull/26399 +* [android] move `IsDispatchRequiredImplementation()` to Java by @jonathanpeppers in https://github.com/dotnet/maui/pull/27936 +* remove Dispose call on ShellItemRenderer by @pictos in https://github.com/dotnet/maui/pull/27890 +* [iOS] CollectionView with grouped data crashes on iOS when the groups change - fix by @kubaflo in https://github.com/dotnet/maui/pull/27991 +* [BindingSG] Added Binding.Create support for xaml generated sources by @jkurdek in https://github.com/dotnet/maui/pull/27610 +* Make ShadowTypeConverter public & nullable for .NET 10 by @jfversluis in https://github.com/dotnet/maui/pull/27984 +* add DebuggerTypeProxy for Shell by @pictos in https://github.com/dotnet/maui/pull/27989 +* [Windows] Fixed NRE when clearing ListView after navigating back by @SubhikshaSf4851 in https://github.com/dotnet/maui/pull/27274 +* [Windows] Fix for issues caused by setting Shell.FlyoutWidth on WinUI when binding context values are changed by @Tamilarasan-Paranthaman in https://github.com/dotnet/maui/pull/27151 +* [MacCatalyst] Picker focus events by @kubaflo in https://github.com/dotnet/maui/pull/27973 +* [Android] Fixed the ScrollbarVisibility issues by @Ahamed-Ali in https://github.com/dotnet/maui/pull/27613 +* Make more internal methods public by @jsuarezruiz in https://github.com/dotnet/maui/pull/28059 +* Fixed FontImageSource icon color does not change in the TabbedPage when dynamically updated. by @NirmalKumarYuvaraj in https://github.com/dotnet/maui/pull/27742 +* [ci] Remove macios workaround to build net9 by @rmarinho in https://github.com/dotnet/maui/pull/28363 + + +### Tests + +* [Testing] Fix for MacCatalyst flaky tests in CI which fails due window position below the dock layer by @anandhan-rajagopal in https://github.com/dotnet/maui/pull/27279 +* Revert "Run every category separately" by @rmarinho in https://github.com/dotnet/maui/pull/27469 +* [Testing] UITest to measure layout passes on a common scenario by @albyrock87 in https://github.com/dotnet/maui/pull/25671 +* [Testing] Enabling some UITests from Issues folder in Appium-13 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27257 +* [Testing] Fix flaky UITests failing sometimes 3 by @jsuarezruiz in https://github.com/dotnet/maui/pull/27277 +* [testing] Disable BlazorWebview tests by @rmarinho in https://github.com/dotnet/maui/pull/27557 +* Fix UITest screenshot taking on MacCatalyst by @albyrock87 in https://github.com/dotnet/maui/pull/27531 +* [Testing] Fix flaky test 4 by @jsuarezruiz in https://github.com/dotnet/maui/pull/27607 +* [testing] Update tests demands by @rmarinho in https://github.com/dotnet/maui/pull/27560 +* [Testing] Implement Appium swipe action on Catalyst using the Mac Driver by @jsuarezruiz in https://github.com/dotnet/maui/pull/27441 +* [Testing] Implement PressEnter Appium action on Windows by @jsuarezruiz in https://github.com/dotnet/maui/pull/27602 +* [Testing] Implement ContextMenu UITest extension methods by @jsuarezruiz in https://github.com/dotnet/maui/pull/26204 +* [Testing] Enabling more UI Tests by removing platform specific condition - 6 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27581 +* [tests] Run tests on x64 only for devices controls by @rmarinho in https://github.com/dotnet/maui/pull/27714 +* [Testing, CI] Increased threshold value to make Resizetizer unit tests pass on arm64 machines by @anandhan-rajagopal in https://github.com/dotnet/maui/pull/27684 +* [Testing] Enabling more UI Tests by removing platform specific condition - 7 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27639 +* [Testing] Implement TapCoordinates Appium action on macOS by @jsuarezruiz in https://github.com/dotnet/maui/pull/27603 +* [Testing] Enabling more UI Tests by removing platform specific condition - 8 by @nivetha-nagalingam in https://github.com/dotnet/maui/pull/27681 +* [Testing] Enabling more UI Tests by removing platform specific condition - 3 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27501 +* [Testing] Fix DragCoordinates Appium action on Mac by @jsuarezruiz in https://github.com/dotnet/maui/pull/27339 +* [Testing] Enabling WebView UITests from Issues folder in Appium by @NafeelaNazhir in https://github.com/dotnet/maui/pull/27284 +* [Testing] Fix flaky test 5 by @jsuarezruiz in https://github.com/dotnet/maui/pull/27733 +* [Testing] Enabling more UI Tests by removing platform specific condition - 1 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27454 +* Add missing screen shot for Issue25502 on MAC by @PureWeen in https://github.com/dotnet/maui/pull/27813 +* [Testing] Enabling ContextMenu UITests from Xamarin.UITests to Appium by @NafeelaNazhir in https://github.com/dotnet/maui/pull/27403 +* Mark VerifyInitialEntryReturnTypeChange and VerifyGraphicsViewWithoutGrayLine tests as flaky by @jfversluis in https://github.com/dotnet/maui/pull/27776 +* [Testing] Fix for flaky UITests in CI that occasionally fail - 2 by @nivetha-nagalingam in https://github.com/dotnet/maui/pull/27878 +* [Testing] Enabling more UI Tests by removing platform specific condition - 5 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27564 +* Update Appium Versions by @PureWeen in https://github.com/dotnet/maui/pull/27933 +* Revert "Update Appium Versions" by @PureWeen in https://github.com/dotnet/maui/pull/27938 +* [Android] Testcase for Shell FlowDirection issue by @Vignesh-SF3580 in https://github.com/dotnet/maui/pull/27931 +* [Testing] Run tests verifying snapshots on mac now that's possible by @jsuarezruiz in https://github.com/dotnet/maui/pull/27893 +* [Testing] More changes in capabilities to adjust Appium timeouts by @jsuarezruiz in https://github.com/dotnet/maui/pull/27675 +* [Testing] Migration of Compatibility.Core platform-specific unit tests into device tests - 1 by @anandhan-rajagopal in https://github.com/dotnet/maui/pull/27695 +* [Testing] Fix flaky tests 6 by @jsuarezruiz in https://github.com/dotnet/maui/pull/27874 +* [Testing] Enabling more UI Tests by removing platform specific condition - 12 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27804 +* [Testing] Enabling more UI Tests by removing platform specific condition - 13 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27904 +* [Testing] Enabling more UI Tests by removing platform specific condition - 4 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27561 +* [Testing] Enable the Issue417 test on iOS and Catalyst by @kubaflo in https://github.com/dotnet/maui/pull/27987 +* [Testing] Enabling more UI Tests by removing platform specific condition - 2 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27500 +* [Testing] Enabling more UI Tests by removing platform specific condition - 14 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27906 +* Fix Android device tests on .NET 10 by @jfversluis in https://github.com/dotnet/maui/pull/28009 +* [Testing] Enabling ContextMenu UITests from Xamarin.UITests to Appium - 2 by @nivetha-nagalingam in https://github.com/dotnet/maui/pull/27405 +* [Testing] Enabling more UI Tests by removing platform specific condition - 9 by @HarishKumarSF4517 in https://github.com/dotnet/maui/pull/27743 +* [Testing] Enabling more UI Tests by removing platform specific condition - 10 by @nivetha-nagalingam in https://github.com/dotnet/maui/pull/27751 +* [Testing] Fix for flaky UITests in CI that occasionally fail - 3 by @NafeelaNazhir in https://github.com/dotnet/maui/pull/27905 +* [Testing] Fix for flaky UITests in CI that occasionally fail. by @nivetha-nagalingam in https://github.com/dotnet/maui/pull/27453 +* [Testing] Enabling more UI Tests by removing platform specific condition - 11 by @LogishaSelvarajSF4525 in https://github.com/dotnet/maui/pull/27764 +* [Testing] Feature Matrix UITest Cases for Slider Control by @NafeelaNazhir in https://github.com/dotnet/maui/pull/27433 +* [Testing] Fix flaky UITests 7 by @jsuarezruiz in https://github.com/dotnet/maui/pull/28000 +* [Testing] Implement the option to change system theme on Appium by @jsuarezruiz in https://github.com/dotnet/maui/pull/28025 +* [Testing] Resolved Shell TabBar DeviceTests CI failures on macOS by @anandhan-rajagopal in https://github.com/dotnet/maui/pull/28072 +* [release/10.0.1xx-preview2] [net10.0] Move iOS 18.0 simulators by @github-actions in https://github.com/dotnet/maui/pull/28277 +* [release/10.0.1xx-preview2] [ci] Fix platform for UItests for iOS by @github-actions in https://github.com/dotnet/maui/pull/28345 + + +### Dependency Updates + +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27510 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27540 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27570 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27587 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27615 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27643 +* [main] Update dependencies from dotnet/xharness by @dotnet-maestro in https://github.com/dotnet/maui/pull/27662 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27687 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27719 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27725 +* [Windows] Upgrade Windows App SDK from 1.6.4 to 1.6.5 by @MartyIX in https://github.com/dotnet/maui/pull/27729 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27758 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27791 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27810 +* [main] Update dependencies from dotnet/xharness by @dotnet-maestro in https://github.com/dotnet/maui/pull/27835 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27887 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27902 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27937 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/27960 +* [net10.0] Update aspnet as sdk, enable Blazor tests by @rmarinho in https://github.com/dotnet/maui/pull/27796 +* [net10.0] Update dependencies from dotnet/android by @dotnet-maestro in https://github.com/dotnet/maui/pull/28019 +* [release/10.0.1xx-preview2] Update with final preview2 versions by @rmarinho in https://github.com/dotnet/maui/pull/28231 +* [release/10.0.1xx-preview2] Update preview2 ios android sdk by @rmarinho in https://github.com/dotnet/maui/pull/28287 +* [release/10.0.1xx-preview2] Update sdk and runtime by @rmarinho in https://github.com/dotnet/maui/pull/28307 +* [release/10.0.1xx-preview2] Update dependencies from dotnet/sdk by @dotnet-maestro in https://github.com/dotnet/maui/pull/28329 +* [release/10.0.1xx-preview2] Update dependencies from dotnet/sdk by @dotnet-maestro in https://github.com/dotnet/maui/pull/28390 + + +### Housekeeping + +* [ci] Remove references to sdk-insertions by @pjcollins in https://github.com/dotnet/maui/pull/27480 +* [ci] Fix yaml by @rmarinho in https://github.com/dotnet/maui/pull/27497 +* Fix color checking from blocking and add logging by @PureWeen in https://github.com/dotnet/maui/pull/27400 +* [Localization] Simply Logic for Localization Handoff & Handback by @tj-devel709 in https://github.com/dotnet/maui/pull/27508 +* [ci] Run device tests in any machine by @rmarinho in https://github.com/dotnet/maui/pull/27518 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27504 +* [net10.0] Update net10.0 with main by @rmarinho in https://github.com/dotnet/maui/pull/27539 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27547 +* Removes setting up the JDK in pipelines by @jfversluis in https://github.com/dotnet/maui/pull/27396 +* [Localization] Fix blocking typo by @tj-devel709 in https://github.com/dotnet/maui/pull/27566 +* Localized file check-in by OneLocBuild Task: Build definition ID 13330: Build ID 10953111 by @dotnet-bot in https://github.com/dotnet/maui/pull/27569 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27571 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27621 +* [ci] Update variables for signing and not used by @rmarinho in https://github.com/dotnet/maui/pull/27640 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27645 +* Update android.cake cmdline paths by @PureWeen in https://github.com/dotnet/maui/pull/27686 +* Update Versions.props to .NET 9 SR5 Branding by @PureWeen in https://github.com/dotnet/maui/pull/27691 +* Update comments by @APoukar in https://github.com/dotnet/maui/pull/27658 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27693 +* Update bug-report.yml with 9.0.40 by @PureWeen in https://github.com/dotnet/maui/pull/27723 +* [net10.0] Merge main to net10.0 by @rmarinho in https://github.com/dotnet/maui/pull/27720 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27726 +* Move Microsoft.Maui.Packages.slnf to eng folder by @jfversluis in https://github.com/dotnet/maui/pull/27032 +* Move Microsoft.Maui.Samples.slnf to eng folder by @jfversluis in https://github.com/dotnet/maui/pull/27033 +* Make auto applied labels more relevant for Syncfusion partner team by @jfversluis in https://github.com/dotnet/maui/pull/27295 +* Move Microsoft.Maui.Graphics.slnf to subfolder (clean up repo root) by @jfversluis in https://github.com/dotnet/maui/pull/27035 +* [ci] Builds should only take 2h max by @rmarinho in https://github.com/dotnet/maui/pull/27747 +* Add ISO information to Locale API documentation by @jfversluis in https://github.com/dotnet/maui/pull/27746 +* Delete maui.code-workspace (clean up repo root by @jfversluis in https://github.com/dotnet/maui/pull/27767 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27757 +* [Localization] Add Localization tests and other fixes by @tj-devel709 in https://github.com/dotnet/maui/pull/25620 +* [ci] Update sdk, aspnet and runtime by @rmarinho in https://github.com/dotnet/maui/pull/27790 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27816 +* [ci] Fix dnceng builds by @rmarinho in https://github.com/dotnet/maui/pull/27855 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27863 +* [ci] Update slnf location and arcade by @rmarinho in https://github.com/dotnet/maui/pull/27860 +* Localized file check-in by OneLocBuild Task: Build definition ID 13330: Build ID 11029468 by @dotnet-bot in https://github.com/dotnet/maui/pull/27789 +* [ci] Move to Sequoia machines by @rmarinho in https://github.com/dotnet/maui/pull/27787 +* Update DEVELOPMENT.md with net10.0 by @PureWeen in https://github.com/dotnet/maui/pull/27913 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27918 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27942 +* [ci] Remove conditions for devdiv by @rmarinho in https://github.com/dotnet/maui/pull/27958 +* [net10.0] Merge main to net10 by @rmarinho in https://github.com/dotnet/maui/pull/27967 +* [ci] Move more runs to Sequoia by @rmarinho in https://github.com/dotnet/maui/pull/27972 +* LEGO: Pull request from lego/hb_7241b85a-f216-4d55-a9fa-d8030c736df5_20250219211456120 to main by @csigs in https://github.com/dotnet/maui/pull/27915 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/27986 +* Localized file check-in by OneLocBuild Task: Build definition ID 13330: Build ID 11064473 by @dotnet-bot in https://github.com/dotnet/maui/pull/27982 +* Enable generation of API docs in CI for .NET 10 by @jfversluis in https://github.com/dotnet/maui/pull/28004 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/28021 +* [ci] Publish workload VS insertion zips by @pjcollins in https://github.com/dotnet/maui/pull/28016 +* Update DEVELOPMENT.md to clarify .NET SDK version needed by @jfversluis in https://github.com/dotnet/maui/pull/28031 +* [ci] Remove usage on cake script by @rmarinho in https://github.com/dotnet/maui/pull/28037 +* [ci] Update autoformat prs version by @rmarinho in https://github.com/dotnet/maui/pull/28042 +* [ci] Last move sequoia by @rmarinho in https://github.com/dotnet/maui/pull/28029 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/28045 +* [ci] Run provisionator devdiv by @rmarinho in https://github.com/dotnet/maui/pull/28056 +* Revert "[ci] Run provisionator devdiv" by @rmarinho in https://github.com/dotnet/maui/pull/28079 +* [housekeeping] Automated PR to fix formatting errors by @github-actions in https://github.com/dotnet/maui/pull/28068 +* [code style] Prefer file-scope namespaces by @MartyIX in https://github.com/dotnet/maui/pull/28040 +* [net10.0] Merge main to net10.0 by @rmarinho in https://github.com/dotnet/maui/pull/28044 +* [iOS] Ignore for now obsoletes on iOS by @rmarinho in https://github.com/dotnet/maui/pull/28136 + + +## New Contributors +* @Ahamed-Ali made their first contribution in https://github.com/dotnet/maui/pull/27273 +* @KarthikRajaKalaimani made their first contribution in https://github.com/dotnet/maui/pull/27466 +* @rabuckley made their first contribution in https://github.com/dotnet/maui/pull/27655 +* @Zerod159 made their first contribution in https://github.com/dotnet/maui/pull/24798 +* @sthewissen made their first contribution in https://github.com/dotnet/maui/pull/27529 +* @APoukar made their first contribution in https://github.com/dotnet/maui/pull/27658 +* @piersdeseilligny made their first contribution in https://github.com/dotnet/maui/pull/23984 +* @Shalini-Ashokan made their first contribution in https://github.com/dotnet/maui/pull/27464 +* @bhavanesh2001 made their first contribution in https://github.com/dotnet/maui/pull/27718 +* @Dhivya-SF4094 made their first contribution in https://github.com/dotnet/maui/pull/27451 +* @mohsenbgi made their first contribution in https://github.com/dotnet/maui/pull/23473 + +**Full Changelog**: https://github.com/dotnet/maui/compare/{branch}..{previous branch} \ No newline at end of file diff --git a/.vscode/mcp.json b/.vscode/mcp.json new file mode 100644 index 000000000000..0273b732a393 --- /dev/null +++ b/.vscode/mcp.json @@ -0,0 +1,26 @@ +{ + "inputs": [ + { + "type": "promptString", + "id": "github-key", + "password": true, // Encrypted at-rest + "description": "GitHub PAT" + } + ], + "servers": { + "github": { + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "-e", + "GITHUB_PERSONAL_ACCESS_TOKEN", + "ghcr.io/github/github-mcp-server" + ], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github-key}" + } + } + } +} \ No newline at end of file diff --git a/build.cake b/build.cake index 63af41c77706..ac9ef9687a5e 100644 --- a/build.cake +++ b/build.cake @@ -29,6 +29,7 @@ PowerShell: ////////////////////////////////////////////////////////////////////// #tool "nuget:?package=nuget.commandline&version=6.6.1" + ////////////////////////////////////////////////////////////////////// // ARGUMENTS ////////////////////////////////////////////////////////////////////// diff --git a/docs/CgManifest.md b/docs/CgManifest.md new file mode 100644 index 000000000000..3c03653c4ed0 --- /dev/null +++ b/docs/CgManifest.md @@ -0,0 +1,125 @@ +# Component Governance Manifest (cgmanifest.json) + +This document explains how to manage, update, and include the `cgmanifest.json` file in the MAUI project. + +## What is cgmanifest.json? + +The Component Governance Manifest (`cgmanifest.json`) is a file that lists all the third-party components used in the project. It helps with tracking dependencies and their versions for security and compliance purposes. + +## Automatic Generation + +The project includes scripts to automatically generate and update the `cgmanifest.json` file with package versions from the `Versions.props` file. + +### Using Cake Build Script + +Run the `GenerateCgManifest` task: + +```bash +dotnet tool resotre +dotnet cake --target=GenerateCgManifest --workloads=global +``` + +### Using Scripts Directly + +You can also run the PowerShell script directly (works on both Windows and macOS/Linux): + +```bash +# On all platforms (Windows/macOS/Linux) +pwsh -ExecutionPolicy Bypass -File ./eng/scripts/update-cgmanifest.ps1 +``` + +### MSBuild Integration + +The `CgManifest.targets` file provides MSBuild integration. + +#### Default Behavior + +By default, the cgmanifest.json file is **always generated** during build, but it is **not included** in the NuGet package. This ensures the manifest is always up-to-date without affecting package contents. + +#### Manual Generation + +You can explicitly generate the manifest file: + +```bash +dotnet build -t:GenerateCgManifest +``` + +#### Disabling Generation + +If needed, you can temporarily disable the automatic generation: + +```bash +dotnet build -p:UpdateCgManifestBeforeBuild=false +``` + +## Including CG Manifest in CI Builds + +For CI builds where you want to include the cgmanifest.json in the package: + +```bash +dotnet build -p:GenerateCgManifest=true +``` +OR +```bash +dotnet pack -p:GenerateCgManifest=true +``` + +This will: +1. Generate the cgmanifest.json file (happens by default) +2. Include it in the package (for Template projects) + +### Azure DevOps Pipeline + +Add the following step to your YAML pipeline to include the cgmanifest.json file in the package: + +```yaml +- task: DotNetCoreCLI@2 + displayName: 'Pack with CG Manifest' + inputs: + command: 'pack' + packagesToPack: 'src/Templates/src/Microsoft.Maui.Templates.csproj' + packDirectory: '$(Build.ArtifactStagingDirectory)/nuget' + arguments: '-p:GenerateCgManifest=true' +``` + +### GitHub Actions + +For GitHub Actions workflows, add this step: + +```yaml +- name: Pack with CG Manifest + run: dotnet pack src/Templates/src/Microsoft.Maui.Templates.csproj -p:GenerateCgManifest=true -o $GITHUB_WORKSPACE/artifacts/nuget +``` + +## Customizing Package Mappings + +To add or modify package mappings, edit the PowerShell script: `eng/scripts/update-cgmanifest.ps1` (look for `$packageVersionMappings` hashtable). + +## Special Handling for Multiple Versions + +The script has special handling for packages that need multiple versions to be included in the manifest: + +- **CommunityToolkit.Maui**: Both the current version (`CommunityToolkitMauiPackageVersion`) and previous version (`CommunityToolkitMauiPreviousPackageVersion`) from `Versions.props` are included. + +To add similar handling for other packages, modify the script to add special case handling like that implemented for CommunityToolkit.Maui. + +## Manual Updates + +If you need to manually add packages that aren't in `Versions.props`, you can edit the `cgmanifest.json` file directly. The update scripts preserve manually added entries and only update versions for packages it knows about. + +## Verifying the Package + +To verify that the cgmanifest.json file is included in the package: + +```bash +# On macOS/Linux +find ./artifacts/packages -name "Microsoft.Maui.Templates*.nupkg" | xargs -I{} unzip -l {} | grep cgmanifest.json + +# On Windows +foreach ($pkg in (Get-ChildItem -Path ./artifacts/packages -Filter "Microsoft.Maui.Templates*.nupkg")) { + Add-Type -AssemblyName System.IO.Compression.FileSystem + $zip = [System.IO.Compression.ZipFile]::OpenRead($pkg.FullName) + $zip.Entries | Where-Object { $_.Name -eq "cgmanifest.json" -or $_.FullName -like "*cgmanifest.json" } + $zip.Dispose() +} +``` diff --git a/docs/README.md b/docs/README.md index ad3f7930931d..22fc15184845 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,6 +10,7 @@ The table below outlines the different docs in this folder and what they are hel | Documentation | What is it about? | Who is it for? | |----------------------|---------------------|---------------------| +| [CG Manifest](CgManifest.md) | Guide to Component Governance manifest generation and management | Contributors who need to manage third-party dependencies or include CG manifest in packages | | [Code Documentation Guidelines](CodeDocumentationGuidelines.md) | Overview of the guidelines for the inline code documentation | Community members and collaborators looking to understand how to add good inline code comments that fuel our IntelliSense and online API docs | | [Issue management](IssueManagementPolicies.md) | Overview of policies in place to manage issues| Community members and collaborators looking to understand how we handle closed issues, issues that need author feedback, etc. | | [Release Schedule](ReleaseSchedule.md) | Overview of .NET MAUI version releases | Anyone who is interested in .NET MAUI versions and release dates | diff --git a/eng/CgManifest.targets b/eng/CgManifest.targets new file mode 100644 index 000000000000..c23eefa2f1e2 --- /dev/null +++ b/eng/CgManifest.targets @@ -0,0 +1,34 @@ + + + + + + $(MSBuildThisFileDirectory)..\..\src\Templates\src\cgmanifest.json + + true + + true + false + + false + + + + + + + + + + + + + + diff --git a/eng/Publishing.props b/eng/Publishing.props index 7fb3d1d57d87..8fbcd716c64f 100644 --- a/eng/Publishing.props +++ b/eng/Publishing.props @@ -1,21 +1,48 @@ + + + 3 true + + SetVersionsOnArtifacts;$(PublishDependsOnTargets) + + <_InstallersToPublish Include="$(ArtifactsShippingPackagesDir)\**\*.zip" /> + <_MetadataRollbacksToPublish Include="$(ArtifactsShippingPackagesDir)\**\metadata\rollbacks\**\*.json" /> + <_MetadataSdksToPublish Include="$(ArtifactsShippingPackagesDir)\**\metadata\sdks\**\*.json" /> <_UploadPathRoot>maui - - - true - false - - + + + + + true + false + true + + + + true + false + false + + + + true + false + false + + + + + \ No newline at end of file diff --git a/eng/Signing.props b/eng/Signing.props index d4f40599ae49..2b21ff815bf5 100644 --- a/eng/Signing.props +++ b/eng/Signing.props @@ -23,15 +23,14 @@ - - + - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 3ac31dc5d220..0d6ea1a69ed2 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -135,51 +135,51 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime f57e6dc747158ab7ade4e62a75a6750d16b771e8 - + https://github.com/dotnet/xharness - aed708d126f0776c81966db1ca17278edbef8279 + 7b61da39ea1692a607459913167673c6096fd7f1 - + https://github.com/dotnet/xharness - aed708d126f0776c81966db1ca17278edbef8279 + 7b61da39ea1692a607459913167673c6096fd7f1 - + https://github.com/dotnet/xharness - aed708d126f0776c81966db1ca17278edbef8279 + 7b61da39ea1692a607459913167673c6096fd7f1 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 - + https://github.com/dotnet/arcade - 5ba9ca776c1d0bb72b2791591e54cf51fc52dfee + aa61e8c20a869bcc994f8b29eb07d927d2bec6f4 diff --git a/eng/Versions.props b/eng/Versions.props index 9dd78d3bdae1..e34066db0fb2 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -2,9 +2,10 @@ 9 0 - 70 + 80 9.0.100 ci.net9 + ci.inflight @@ -31,7 +32,7 @@ 9.0.105-servicing.25164.42 $(MicrosoftNETSdkPackageVersion) - 9.0.3 + 9.0.4 $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) $(MicrosoftNETCoreAppRefPackageVersion) @@ -58,13 +59,13 @@ 8.0.148 - 9.0.3 - $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100Version) + 9.0.4 + $(MicrosoftNETWorkloadEmscriptenCurrentManifest90100TransportVersion) - 1.6.250228001 + 1.7.250401001 10.0.22621.756 - 1.2.0 - 1.0.2903.40 + 1.3.2 + 1.0.3179.45 9.0.6 9.0.6 @@ -125,22 +126,22 @@ <_HarfBuzzSharpVersion>8.3.0.1 <_SkiaSharpNativeAssetsVersion>0.0.0-commit.e57e2a11dac4ccc72bea52939dede49816842005.1728 7.0.120 - 9.0.0-prerelease.25207.3 - 9.0.0-prerelease.25207.3 - 9.0.0-prerelease.25207.3 + 9.0.0-prerelease.25214.1 + 9.0.0-prerelease.25214.1 + 9.0.0-prerelease.25214.1 0.9.2 2.0.0.4 1.3.0 0.9.0 4.2.3 9.0.0 - 9.0.0-beta.25164.2 - 9.0.0-beta.25164.2 - 9.0.0-beta.25164.2 - 9.0.0-beta.25164.2 + 9.0.0-beta.25208.6 + 9.0.0-beta.25208.6 + 9.0.0-beta.25208.6 + 9.0.0-beta.25208.6 1.1.87-gba258badda - 9.0.0-beta.25164.2 - 9.0.0-beta.25164.2 + 9.0.0-beta.25208.6 + 9.0.0-beta.25208.6 17.6.0 @@ -152,14 +153,21 @@ 2.0.3 5.1.0 6.0.0 + + 1.0.4 + 8.0.8 + 2.1.10 + 11.1.1 + 9.1.0 + 8.3.2 - 2.12.2 + 2.17.1 3.1.1 7.32.0 1.20.3 - 3.8.0 + 4.2.1 17.0.12 diff --git a/eng/Versions.targets b/eng/Versions.targets index 790ed4719c3b..34063f9833bf 100644 --- a/eng/Versions.targets +++ b/eng/Versions.targets @@ -31,17 +31,17 @@ Returns="$(Version)"> - $(NightlyTag) + $(NightlyTag) - - @@ -52,8 +52,8 @@ - <_SkipUpdateBuildNumber Condition="'$(SampleProject)' == 'true' or '$(OutputType)' == 'Exe' or '$(OutputType)' == 'WinExe' or '$(AndroidApplication)' == 'true' or '$(IsTestProject)' == 'true' or '$(IsPackable)' == 'false' or '_SkipUpdateBuildNumber' == 'true' ">true - <_UpdateBuildNumber Condition="$(CI) and '$(BUILD_BUILDNUMBER)' != '$(PackageVersion)' AND '$(_SkipUpdateBuildNumber)' != 'true'">$(PackageVersion) + <_SkipUpdateBuildNumber Condition="'$(SampleProject)' == 'true' or '$(OutputType)' == 'Exe' or '$(OutputType)' == 'WinExe' or '$(AndroidApplication)' == 'true' or '$(MauiTestProject)' == 'true' or '$(IsPackable)' == 'false' or '_SkipUpdateBuildNumber' == 'true' ">true + <_UpdateBuildNumber Condition="'$(CI)' == 'true' and '$(BUILD_BUILDNUMBER)' != '$(PackageVersion)' AND '$(_SkipUpdateBuildNumber)' != 'true'">$(PackageVersion) @@ -62,7 +62,7 @@ <_UpdateBuildNumber Condition="'@(VersionMetadata)' != ''">$(_UpdateBuildNumber)+@(VersionMetadata -> '%(Identity)', '.') - + diff --git a/eng/automation/cspell/cSpell.json b/eng/automation/cspell/cSpell.json index 644233b66eec..5236810d57e7 100644 --- a/eng/automation/cspell/cSpell.json +++ b/eng/automation/cspell/cSpell.json @@ -9,7 +9,8 @@ "netstandard", "Appium", "XCUI", - "Automator" + "Automator", + "cgmanifest" ], "ignoreWords": [], "patterns": [ diff --git a/eng/cake/dotnet.cake b/eng/cake/dotnet.cake index 4081e568323b..2208e35a51af 100644 --- a/eng/cake/dotnet.cake +++ b/eng/cake/dotnet.cake @@ -510,6 +510,48 @@ Task("VS") }); +Task("GenerateCgManifest") + .Description("Generates the cgmanifest.json file with versions from Versions.props") + .Does(() => +{ + Information("Generating cgmanifest.json from Versions.props"); + + // Use pwsh on all platforms + var pwshExecutable = "pwsh"; + + // Check if pwsh is available + try { + if (IsRunningOnWindows()) { + var exitCode = StartProcess("where", new ProcessSettings { + Arguments = "pwsh", + RedirectStandardOutput = true, + RedirectStandardError = true + }); + if (exitCode != 0) { + Information("pwsh not found, falling back to powershell"); + pwshExecutable = "powershell"; + } + } else { + var exitCode = StartProcess("which", new ProcessSettings { + Arguments = "pwsh", + RedirectStandardOutput = true, + RedirectStandardError = true + }); + if (exitCode != 0) { + throw new Exception("PowerShell Core (pwsh) is not installed. Please install it to continue."); + } + } + } catch (Exception ex) when (!IsRunningOnWindows()) { + Error("Error checking for pwsh: " + ex.Message); + throw new Exception("PowerShell Core (pwsh) is required on non-Windows platforms. Please install it and try again."); + } + + // Execute the PowerShell script + StartProcess(pwshExecutable, new ProcessSettings { + Arguments = "-NonInteractive -ExecutionPolicy Bypass -File ./eng/scripts/update-cgmanifest.ps1" + }); +}); + bool RunPackTarget() { // Is the user running the pack target explicitly? diff --git a/eng/devices/android.cake b/eng/devices/android.cake index d08213f51bd8..351c7323104a 100644 --- a/eng/devices/android.cake +++ b/eng/devices/android.cake @@ -597,25 +597,24 @@ void PrepareDevice(bool waitForBoot) { Information("Waiting for the emulator to finish booting..."); - // wait for it to finish booting - var waited = 0; - var total = EmulatorBootTimeoutSeconds; - while (AdbShell("getprop sys.boot_completed", settings).FirstOrDefault() != "1") + // Wait for the emulator to finish booting + var waited = 0; + var total = EmulatorBootTimeoutSeconds; + while (AdbShell("getprop sys.boot_completed", settings).FirstOrDefault() != "1") { - System.Threading.Thread.Sleep(1000); - - Information("Waiting {0}/{1} seconds for the emulator to boot up.", waited, total); - if (waited++ > total) - { - throw new Exception("The emulator did not finish booting in time."); - } - - // something may be wrong with ADB, so restart every 30 seconds just in case - if (waited % 30 == 0 && IsCIBuild()) - { - Information("Trying to restart ADB just in case..."); - AdbKillServer(adbSettings); - } + System.Threading.Thread.Sleep(1000); + + Information("Waiting {0}/{1} seconds for the emulator to boot up.", waited, total); + if (waited++ > total) + { + throw new Exception("The emulator did not finish booting in time."); + } + + if (waited % 60 == 0 && IsCIBuild()) + { + // Ensure ADB keys are configured + EnsureAdbKeys(settings); + } } Information("Waited {0} seconds for the emulator to boot up.", waited); @@ -641,4 +640,165 @@ void PrepareDevice(bool waitForBoot) Information("{0}", string.Join("\n", lines)); Information("Finished setting ADB properties."); +} + +void EnsureAdbKeys(AdbToolSettings settings) +{ + Information("Ensuring ADB keys are correctly configured..."); + + try + { + // Kill ADB server first before modifying keys + Information("Stopping ADB server..."); + AdbKillServer(settings); + System.Threading.Thread.Sleep(1000); + + // Set up file paths + var homeDir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + var adbKeyPath = System.IO.Path.Combine(homeDir, ".android"); + var adbKeyFile = System.IO.Path.Combine(adbKeyPath, "adbkey"); + var adbKeyPubFile = System.IO.Path.Combine(adbKeyPath, "adbkey.pub"); + + // Ensure ADB directory exists with correct permissions + Information("Ensuring ADB key directory exists..."); + if (!System.IO.Directory.Exists(adbKeyPath)) + { + System.IO.Directory.CreateDirectory(adbKeyPath); + Information($"Created ADB directory at {adbKeyPath}"); + } + + // Set proper directory permissions + StartProcess("chmod", $"700 {adbKeyPath}"); + + // Delete existing ADB keys to avoid stale data + Information("Cleaning up old ADB keys..."); + if (System.IO.File.Exists(adbKeyFile)) + { + System.IO.File.Delete(adbKeyFile); + Information("Removed existing private key"); + } + + if (System.IO.File.Exists(adbKeyPubFile)) + { + System.IO.File.Delete(adbKeyPubFile); + Information("Removed existing public key"); + } + + // Generate new ADB keys instead of waiting for automatic generation + Information("Explicitly generating new ADB keys..."); + StartProcess("adb", new ProcessSettings { + Arguments = "keygen " + adbKeyPath, + RedirectStandardOutput = true, + RedirectStandardError = true + }); + + // Check if keys were created + if (!System.IO.File.Exists(adbKeyFile) || !System.IO.File.Exists(adbKeyPubFile)) + { + throw new Exception("Failed to generate ADB keys."); + } + + // Set correct file permissions for ADB keys + Information("Setting correct permissions for ADB keys..."); + StartProcess("chmod", $"600 {adbKeyFile}"); + StartProcess("chmod", $"600 {adbKeyPubFile}"); + + // Set environment variable properly (platform specific) + Information("Setting ADB_VENDOR_KEYS environment variable..."); + + // This actually sets it for the current process + SetEnvironmentVariable("ADB_VENDOR_KEYS", adbKeyPubFile); + + // Set ADB_VENDOR_KEYS environment variable + StartProcess("sh", new ProcessSettings { + Arguments = new ProcessArgumentBuilder() + .Append("-c") + .AppendQuoted($"export ADB_VENDOR_KEYS={adbKeyPubFile}"), + RedirectStandardOutput = true + }); + + // Start ADB server with new keys + Information("Starting ADB server with new keys..."); + AdbStartServer(settings); + System.Threading.Thread.Sleep(2000); // Give ADB time to fully start + + // Push keys to the device with better error handling + Information("Pushing ADB keys to the device..."); + int retries = 0; + bool pushSuccess = false; + + while (retries < 3 && !pushSuccess) + { + var processSettings = new ProcessSettings { + Arguments = new ProcessArgumentBuilder() + .Append("push") + .AppendQuoted(adbKeyPubFile) + .AppendQuoted("/data/misc/adb/adb_keys"), + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + var exitCode = StartProcess("adb", processSettings); + + // Check exit code for success indicators + if (exitCode == 0) + { + Information("ADB key successfully pushed."); + pushSuccess = true; + break; + } + + retries++; + Information($"Push attempt {retries} failed. Retrying in 1 second..."); + System.Threading.Thread.Sleep(1000); + } + + if (!pushSuccess) + { + throw new Exception("Failed to push ADB keys after multiple attempts."); + } + + // Set proper permissions on the device key file + AdbShell("chmod 600 /data/misc/adb/adb_keys", settings); + + // Restart ADB on device to apply changes + Information("Restarting ADB daemon on the device..."); + AdbShell("stop adbd", settings); + System.Threading.Thread.Sleep(2000); + AdbShell("start adbd", settings); + System.Threading.Thread.Sleep(2000); + + // Verify connectivity after all changes + var deviceCheck = StartProcess("adb", new ProcessSettings { + Arguments = "devices", + RedirectStandardOutput = true + }); + + if (deviceCheck == 0) + { + Information("Device connection authorized successfully."); + } + else + { + Warning("Device may not be properly authorized. Check 'adb devices' output."); + } + } + catch (Exception ex) + { + Warning($"Error ensuring ADB keys: {ex.Message}"); + Information("Trying to restart ADB just in case..."); + + try + { + AdbKillServer(settings); + System.Threading.Thread.Sleep(1000); + AdbStartServer(settings); + } + catch (Exception innerEx) + { + Error($"Recovery attempt also failed: {innerEx.Message}"); + } + + throw; // Re-throw the original exception + } } \ No newline at end of file diff --git a/eng/pipelines/arcade/stage-pack.yml b/eng/pipelines/arcade/stage-pack.yml index 93ba36c2fbac..896557b6f77f 100644 --- a/eng/pipelines/arcade/stage-pack.yml +++ b/eng/pipelines/arcade/stage-pack.yml @@ -50,49 +50,32 @@ stages: - checkout: self fetchDepth: 1 clean: true - + steps: - ${{ each step in parameters.prepareSteps }}: - ${{ each pair in step }}: - ${{ pair.key }}: ${{ pair.value }} + ${{ pair.key }}: ${{ pair.value }} - - script: $(_buildScript) - -restore -build - -configuration $(_BuildConfig) - /p:ArchiveTests=true - /p:TreatWarningsAsErrors=false - /p:_SkipUpdateBuildNumber=true - /bl:$(Build.Arcade.LogsPath)build.binlog - $(_OfficialBuildIdArgs) - displayName: 🛠️ Build + # - script: $(_buildScript) + # -restore -build + # -configuration $(_BuildConfig) + # /p:ArchiveTests=true + # /p:TreatWarningsAsErrors=false + # /p:_SkipUpdateBuildNumber=true + # /bl:$(Build.Arcade.LogsPath)build.binlog + # $(_OfficialBuildIdArgs) + # displayName: 🛠️ Build # Run on public pipeline - ${{ if parameters.runAsPublic }}: - - script: $(_buildScript) - -restore -pack - -publish $(_PublishArgs) - -configuration $(_BuildConfig) - /bl:$(Build.Arcade.LogsPath)pack.binlog - $(_OfficialBuildIdArgs) + - script: $(_buildScript) -restore -pack -publish $(_PublishArgs) -configuration $(_BuildConfig) /bl:$(Build.Arcade.LogsPath)pack.binlog $(_OfficialBuildIdArgs) displayName: Pack & Publish # Run on internal pipeline - ${{ if and(not(parameters.runAsPublic) , notin(variables['Build.Reason'], 'PullRequest')) }}: - - script: $(_buildScript) - -restore -pack - -sign $(_SignArgs) - -configuration $(_BuildConfig) - /bl:$(Build.Arcade.LogsPath)pack.binlog - $(_OfficialBuildIdArgs) + - script: $(_buildScript) -restore -pack -sign $(_SignArgs) -configuration $(_BuildConfig) /bl:$(Build.Arcade.LogsPath)pack.binlog $(_OfficialBuildIdArgs) displayName: Pack, Sign - + # only for workloads - - script: $(_buildScript) - -restore -build - -sign $(_SignArgs) - -publish $(_PublishArgs) - -configuration $(_BuildConfig) - /bl:$(Build.Arcade.LogsPath)/build-workloads.binlog - -projects src/Workload/workloads.csproj - $(_OfficialBuildIdArgs) + - script: $(_buildScript) -restore -build -sign $(_SignArgs) -publish $(_PublishArgs) -configuration $(_BuildConfig) /bl:$(Build.Arcade.LogsPath)/build-workloads.binlog -projects src/Workload/workloads.csproj $(_OfficialBuildIdArgs) displayName: Build Workloads, Sign & Publish diff --git a/eng/pipelines/common/ui-tests-steps.yml b/eng/pipelines/common/ui-tests-steps.yml index aeeae13db741..7fca26aeff51 100644 --- a/eng/pipelines/common/ui-tests-steps.yml +++ b/eng/pipelines/common/ui-tests-steps.yml @@ -108,11 +108,11 @@ steps: displayName: "Install node" - pwsh: | - $skipAppiumDoctor = if ($IsMacOS) { "true" } else { "false" } + $skipAppiumDoctor = if ($IsMacOS -or $IsLinux) { "true" } else { "false" } dotnet build ./src/Provisioning/Provisioning.csproj -t:ProvisionAppium -p:SkipAppiumDoctor="$skipAppiumDoctor" -bl:"$(LogDirectory)/provision-appium.binlog" displayName: "Install Appium" continueOnError: false - retryCountOnTaskFailure: 1 + retryCountOnTaskFailure: 2 timeoutInMinutes: 10 env: APPIUM_HOME: $(APPIUM_HOME) diff --git a/eng/pipelines/common/ui-tests.yml b/eng/pipelines/common/ui-tests.yml index 4712098c7e5d..133562500f30 100644 --- a/eng/pipelines/common/ui-tests.yml +++ b/eng/pipelines/common/ui-tests.yml @@ -8,6 +8,7 @@ parameters: androidApiLevels: [ 30 ] iosVersions: [ 'latest' ] provisionatorChannel: 'latest' + timeoutInMinutes: 120 skipProvisioning: true agentPoolAccessToken: '' categoryGroupsToTest: @@ -143,7 +144,7 @@ stages: ${{ each categoryGroup in parameters.categoryGroupsToTest }}: ${{ categoryGroup }}: CATEGORYGROUP: ${{ categoryGroup }} - timeoutInMinutes: 240 # how long to run the job before automatically cancelling + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) @@ -180,7 +181,7 @@ stages: - ${{ each version in parameters.iosVersions }}: - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: - job: CV2_ios_ui_tests_mono_${{ project.name }}_${{ replace(version, '.', '_') }} - timeoutInMinutes: 240 # how long to run the job before automatically cancelling + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) @@ -209,6 +210,44 @@ stages: testConfigurationArgs: "CollectionView2" skipProvisioning: ${{ parameters.skipProvisioning }} + - stage: ios_ui_tests_mono_carv2 + displayName: iOS UITests Mono CarouselView2 + dependsOn: build_ui_tests + jobs: + - ${{ each project in parameters.projects }}: + - ${{ if ne(project.ios, '') }}: + - ${{ each version in parameters.iosVersions }}: + - ${{ if not(containsValue(project.iosVersionsExclude, version)) }}: + - job: CARV2_ios_ui_tests_mono_${{ project.name }}_${{ replace(version, '.', '_') }} + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling + workspace: + clean: all + displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) + pool: ${{ parameters.iosPool }} + variables: + REQUIRED_XCODE: $(DEVICETESTS_REQUIRED_XCODE) + APPIUM_HOME: $(System.DefaultWorkingDirectory)/.appium/ + steps: + - template: ui-tests-steps.yml + parameters: + platform: ios + ${{ if eq(version, 'latest') }}: + version: 16.4 + ${{ if ne(version, 'latest') }}: + version: ${{ version }} + path: ${{ project.ios }} + app: ${{ project.app }} + ${{ if eq(version, 'latest') }}: + device: ios-simulator-64 + ${{ if ne(version, 'latest') }}: + device: ios-simulator-64_${{ version }} + provisionatorChannel: ${{ parameters.provisionatorChannel }} + agentPoolAccessToken: ${{ parameters.agentPoolAccessToken }} + runtimeVariant : "Mono" + testFilter: "CarouselView" + testConfigurationArgs: "CollectionView2" + skipProvisioning: ${{ parameters.skipProvisioning }} + - ${{ if or(parameters.BuildEverything, and(ne(variables['Build.Reason'], 'PullRequest'), eq(variables['System.TeamProject'], 'devdiv'))) }}: - stage: ios_ui_tests_nativeaot displayName: iOS UITests NativeAOT @@ -224,7 +263,7 @@ stages: ${{ each categoryGroup in parameters.categoryGroupsToTest }}: ${{ categoryGroup }}: CATEGORYGROUP: ${{ categoryGroup }} - timeoutInMinutes: 240 # how long to run the job before automatically cancelling + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} (v${{ version }}) @@ -264,7 +303,7 @@ stages: ${{ each categoryGroup in parameters.categoryGroupsToTest }}: ${{ categoryGroup }}: CATEGORYGROUP: ${{ categoryGroup }} - timeoutInMinutes: 240 # how long to run the job before automatically cancelling + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} @@ -296,7 +335,7 @@ stages: ${{ each categoryGroup in parameters.categoryGroupsToTest }}: ${{ categoryGroup }}: CATEGORYGROUP: ${{ categoryGroup }} - timeoutInMinutes: 240 # how long to run the job before automatically cancelling + timeoutInMinutes: ${{ parameters.timeoutInMinutes }} # how long to run the job before automatically cancelling workspace: clean: all displayName: ${{ coalesce(project.desc, project.name) }} diff --git a/eng/pipelines/common/variables.yml b/eng/pipelines/common/variables.yml index 0bd6c5d16577..892e57a3808f 100644 --- a/eng/pipelines/common/variables.yml +++ b/eng/pipelines/common/variables.yml @@ -21,7 +21,7 @@ variables: - name: signingCondition value: $[or( eq(variables['Sign'], 'true'), - in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net10.0', 'refs/heads/main'), + in(variables['Build.SourceBranch'], 'refs/heads/net9.0', 'refs/heads/net10.0', 'refs/heads/main', 'refs/heads/inflight/current' ), startsWith(variables['Build.SourceBranch'], 'refs/tags/'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/') )] diff --git a/eng/pipelines/maui-release-internal.yml b/eng/pipelines/maui-release-internal.yml index 6bf3ab993b68..9b682b73a990 100644 --- a/eng/pipelines/maui-release-internal.yml +++ b/eng/pipelines/maui-release-internal.yml @@ -17,6 +17,36 @@ parameters: type: string default: skip +- name: pushWorkloadSet + displayName: Push workload set channel stage + type: boolean + default: true + +- name: pushNugetOrg + displayName: Push to NuGet.org stage + type: boolean + default: true + +- name: pushPackages + displayName: "Controls the script, allows for dry run" + type: boolean + default: false + +- name: nugetIncludeFilters + displayName: "[OPTIONAL] Semi-colon (';') separated list of nugets packages to include" + type: string + default: skip + +- name: nugetExcludeFilters + displayName: "[OPTIONAL] Semi-colon (';') separated list of nugets packages to exclude" + type: string + default: skip + +- name: feedUrl + displayName: "[OPTIONAL] NuGet URL to push to defaults to nuget.org" + type: string + default: "https://api.nuget.org/v3/index.json" + - name: VM_IMAGE_HOST type: object default: @@ -28,6 +58,7 @@ variables: - template: /eng/common/templates/variables/pool-providers.yml@self - group: DotNetBuilds storage account read tokens - group: AzureDevOps-Artifact-Feeds-Pats +- group: DotNet-Maui-Release resources: repositories: @@ -62,6 +93,7 @@ extends: - stage: publish_maestro displayName: Publish to Workload Set channel dependsOn: [] + condition: eq(${{ parameters.pushWorkloadSet }}, true) jobs: - job: publish_maestro displayName: Publish to Workload Set channel @@ -122,4 +154,137 @@ extends: Write-Host "##vso[task.setvariable variable=WorkloadSetsFeedName;]$workloadSetsFeed" Write-Host "Adding build ID '$barId' to channel '$workloadSetsChannel' and feed '$workloadSetsFeed'" & $darc add-build-to-channel --ci --channel "$workloadSetsChannel" --id "$barId" --skip-assets-publishing --azdev-pat $(System.AccessToken) --verbose - + + - stage: stage_push_packs + displayName: Release packs + dependsOn: [] + condition: eq(${{ parameters.pushNugetOrg }}, true) + jobs: + # Waits for two hours for approval and will fail on timeout. The job can be re-ran to prompt another approval workflow after the initial timeout + - job: push_packs_approval + displayName: Wait to push packs + timeoutInMinutes: 240 + pool: server + steps: + - task: ManualValidation@0 + timeoutInMinutes: 120 + inputs: + instructions: 'Press "Resume" to push workload packs to NuGet.org.' + onTimeout: reject + + - job: push_packs + displayName: Push packs to NuGet.org + timeoutInMinutes: 90 + dependsOn: push_packs_approval + condition: eq(dependencies.push_packs_approval.result, 'Succeeded') + workspace: + clean: all + steps: + - checkout: self + clean: true + + - ${{ if eq(parameters.commitHash, 'skip') }}: + - script: echo parameters.commitHash was not set, skipping... + displayName: skip push + + - ${{ else }}: + - script: | + echo ##vso[task.setvariable variable=COMMIT]${{ parameters.commitHash }} + displayName: set COMMIT + + - task: AzureCLI@2 + displayName: Get build for commit + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + Write-Host "Getting BAR ID for commit: $(COMMIT)" + . $(Build.SourcesDirectory)\eng\common\tools.ps1 + $darc = Get-Darc + $buildJson = & $darc get-build --ci --repo "${{ parameters.ghRepo }}" --commit "$(COMMIT)" --output-format json --azdev-pat $(System.AccessToken) + Write-Host "`n$buildJson`n" + $barId = $buildJson | ConvertFrom-Json | Select-Object -ExpandProperty "id" -First 1 + Write-Host "Got the Bar ID: $barId for commit $(COMMIT) on repo ${{ parameters.ghRepo }}" + if ($barId -eq $null) { + Write-Error "Could not find a build for commit $(COMMIT) on repo ${{ parameters.ghRepo }}" + exit 1 + } + Write-Host "Getting drop for Bar ID: $barId" + & $darc gather-drop --ci --id $barId -o "$(Build.StagingDirectory)\nupkgs" --azdev-pat $(System.AccessToken) --verbose + + - pwsh: Get-ChildItem -Name -Recurse -Path $(Build.StagingDirectory) + displayName: list downloaded artifacts + + - powershell: >- + $(Build.SourcesDirectory)\eng\scripts\push_nuget_org.ps1 -ApiKey "$(pat--nuget--xamarinc--push--wildcard)" -FeedUrl "${{ parameters.feedUrl }}" -NuGetSearchPath "$(Build.StagingDirectory)\nupkgs\shipping\packages\*" -NuGetIncludeFilters "${{ parameters.nugetIncludeFilters }}" -NuGetExcludeFilters "*Manifest*.nupkg;${{ parameters.nugetExcludeFilters }}" + displayName: Push workload packs to NuGet.org + env: + PUSH_PACKAGES: ${{ parameters.pushPackages }} + + - stage: stage_push_manifests + displayName: Release manifests + dependsOn: [] + condition: eq(${{ parameters.pushNugetOrg }}, true) + jobs: + # Waits for two hours for approval and will fail on timeout. The job can be re-ran to prompt another approval workflow after the initial timeout + - job: push_manifests_approval + displayName: Wait to push manifests + timeoutInMinutes: 240 + pool: server + steps: + - task: ManualValidation@0 + timeoutInMinutes: 120 + inputs: + instructions: 'Press "Resume" to push workload manifests to NuGet.org.' + onTimeout: reject + + - job: push_manifests + displayName: Push manifests to NuGet.org + timeoutInMinutes: 90 + dependsOn: push_manifests_approval + condition: eq(dependencies.push_manifests_approval.result, 'Succeeded') + workspace: + clean: all + steps: + - checkout: self + clean: true + + - ${{ if eq(parameters.commitHash, 'skip') }}: + - script: echo parameters.commitHash was not set, skipping... + displayName: skip push + + - ${{ else }}: + - script: | + echo ##vso[task.setvariable variable=COMMIT]${{ parameters.commitHash }} + displayName: set COMMIT + + - task: AzureCLI@2 + displayName: Get build for commit + inputs: + azureSubscription: "Darc: Maestro Production" + scriptType: pscore + scriptLocation: inlineScript + inlineScript: | + Write-Host "Getting BAR ID for commit: $(COMMIT)" + . $(Build.SourcesDirectory)\eng\common\tools.ps1 + $darc = Get-Darc + $buildJson = & $darc get-build --ci --repo "${{ parameters.ghRepo }}" --commit "$(COMMIT)" --output-format json --azdev-pat $(System.AccessToken) + Write-Host "`n$buildJson`n" + $barId = $buildJson | ConvertFrom-Json | Select-Object -ExpandProperty "id" -First 1 + Write-Host "Got the Bar ID: $barId for commit $(COMMIT) on repo ${{ parameters.ghRepo }}" + if ($barId -eq $null) { + Write-Error "Could not find a build for commit $(COMMIT) on repo ${{ parameters.ghRepo }}" + exit 1 + } + Write-Host "Getting drop for Bar ID: $barId" + & $darc gather-drop --ci --id $barId -o "$(Build.StagingDirectory)\nupkgs" --azdev-pat $(System.AccessToken) --verbose + + - pwsh: Get-ChildItem -Name -Recurse -Path $(Build.StagingDirectory) + displayName: list downloaded artifacts + + - powershell: >- + $(Build.SourcesDirectory)\eng\scripts\push_nuget_org.ps1 -ApiKey "$(pat--nuget--xamarinc--push--wildcard)" -FeedUrl "${{ parameters.feedUrl }}" -NuGetSearchPath "$(Build.StagingDirectory)\nupkgs\shipping\packages\*" -NuGetIncludeFilters "*Manifest*.nupkg;${{ parameters.nugetIncludeFilters }}" -NuGetExcludeFilters "${{ parameters.nugetExcludeFilters }}" + displayName: Push workload manifests to NuGet.org + env: + PUSH_PACKAGES: ${{ parameters.pushPackages }} diff --git a/eng/pipelines/maui-release.yml b/eng/pipelines/maui-release.yml index c011b4a69746..fba671ac333d 100644 --- a/eng/pipelines/maui-release.yml +++ b/eng/pipelines/maui-release.yml @@ -27,6 +27,7 @@ schedules: branches: include: - main + - inflight/current variables: - template: /eng/pipelines/common/variables.yml@self @@ -60,9 +61,8 @@ parameters: resources: repositories: - repository: yaml-templates - type: github - name: xamarin/yaml-templates - endpoint: xamarin + type: git + name: DevDiv/Xamarin.yaml-templates ref: refs/heads/main - repository: 1ESPipelineTemplates type: git diff --git a/eng/scripts/push_nuget_org.ps1 b/eng/scripts/push_nuget_org.ps1 new file mode 100644 index 000000000000..328c45fe395d --- /dev/null +++ b/eng/scripts/push_nuget_org.ps1 @@ -0,0 +1,127 @@ +param ( + [Parameter(Mandatory)] + [String] + $ApiKey, + + [Parameter(Mandatory)] + [String] + $NuGetSearchPath, + + [String] + $NuGetIncludeFilters, + + [String] + $NuGetExcludeFilters, + + [String] + $FeedUrl, + + [String] + $NuGetOrgApiKey2, + + [String] + $NuGetOrgApiKey3 +) + +function CheckQuotaExceeded { + param ( + [String] $pushOutput + ) + return ($pushOutput -like "*Quota exceeded*" -or $pushOutput -like "*Rate limit is exceeded*") +} + +function TryPushNuGetWithRetry { + param ( + [System.IO.FileInfo] $nupkg, + [String] $feedUrl, + [String] $apiKey, + [Int32] $maxAttempts + ) + + $nupkgFile = $nupkg.FullName + for ($i = 1; $i -le $maxAttempts; $i++) { + try { + Write-Host "Pushing $nupkgFile to $feedUrl (attempt $i of $maxAttempts)" + $output = & dotnet nuget push --source $feedUrl --api-key $apiKey --skip-duplicate $nupkgFile + $exitCode = $LASTEXITCODE + if ($exitCode -eq 0) { + return "`tSuccessfully pushed $nupkgFile to $FeedUrl. Output:`n`t$output" + } else { + throw "Process failed with exit code '$exitCode'. Output:`n`t$output" + } + } catch { + if ($i -eq $maxAttempts -or $(CheckQuotaExceeded -pushOutput $_.Exception.Message) -eq $true) { + return "`t$($_.Exception.Message)" + } + } + } +} + +# If no feed was provided, then push to NuGet.org +$nugetOrgFeedUrl = "https://api.nuget.org/v3/index.json" +if (!$FeedUrl) { + $FeedUrl = $nugetOrgFeedUrl +} + +# Get the Filter from the list of included packages +if ([string]::IsNullOrEmpty($NuGetIncludeFilters) -or "$NuGetIncludeFilters" -eq "skip") { + $includeFilters = @() +} else { + $includeFilters = "$NuGetIncludeFilters" -split ";" | Where-Object { $_ } | % { $_.Trim() } +} +if ([string]::IsNullOrEmpty($NuGetExcludeFilters) -or "$NuGetExcludeFilters" -eq "skip") { + $excludeFilters = @() +} else { + $excludeFilters = "$NuGetExcludeFilters" -split ";" | Where-Object { $_ } | % { $_.Trim() } +} + +$nupkgs = (Get-ChildItem -Path "$NuGetSearchPath" -Filter *.nupkg -Recurse -Include $includeFilters -Exclude $excludeFilters) +Write-Output "Publishing the following packages:" +foreach ($nupkg in $nupkgs) { + Write-Output $nupkg.FullName +} + +$nugetApiKeys = [System.Collections.Generic.List[string]]::new() +$initialKeys = @($ApiKey, $NuGetOrgApiKey2, $NuGetOrgApiKey3) | Where-Object { -not [string]::IsNullOrEmpty($_) } +foreach ($key in $initialKeys) { + $nugetApiKeys.Add($key) +} +$nugetApiKeysExceedingQuota = [System.Collections.Generic.List[string]]::new() +$nugetApiKeyIndex = 1 + +foreach ($nupkg in $nupkgs) { + if ( $env:PUSH_PACKAGES -ne "True" ) { + Write-Host "`tdry run, not pushing $($nupkg.FullName)" + continue + } + + if ($FeedUrl -eq $nugetOrgFeedUrl) { + if ($nugetApiKeys.Count -eq 0) { + throw "Unable to push to NuGet.org, all API keys have exceeded quota or none were provided." + } + foreach ($key in $nugetApiKeys) { + if (!$key) { + continue + } + $pushTryOutput = TryPushNuGetWithRetry -nupkg $nupkg -feedUrl $FeedUrl -apiKey $key -maxAttempts 3 + Write-Host $pushTryOutput + if ($pushTryOutput -like "*Successfully pushed*") { + break + } + if ($(CheckQuotaExceeded -pushOutput $pushTryOutput) -eq $true) { + Write-Host "`tQuota exceeded, future push attempts will not try to use key $nugetApiKeyIndex." + $nugetApiKeysExceedingQuota.Add($key) + $nugetApiKeyIndex++ + } else { + break + } + } + foreach ($keyToRemove in $nugetApiKeysExceedingQuota) { + $nugetApiKeys.Remove($keyToRemove) + } + $nugetApiKeysExceedingQuota.Clear() + } else { + $pushTryOutput = TryPushNuGetWithRetry -nupkg $nupkg -feedUrl $FeedUrl -apiKey $ApiKey -maxAttempts 3 + Write-Host $pushTryOutput + } +} diff --git a/eng/scripts/update-cgmanifest.ps1 b/eng/scripts/update-cgmanifest.ps1 new file mode 100644 index 000000000000..4073be0a822d --- /dev/null +++ b/eng/scripts/update-cgmanifest.ps1 @@ -0,0 +1,145 @@ +#!/usr/bin/env pwsh + +<# +.SYNOPSIS + Updates the cgmanifest.json file with package versions from Versions.props +.DESCRIPTION + This script reads the Versions.props file to extract NuGet package versions + and updates the cgmanifest.json file with these versions. +.NOTES + This ensures that the Component Governance manifest is kept in sync with the actual package versions used in the project. +#> + +$ErrorActionPreference = 'Stop' + +# Get the paths to the files +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "../..") +$versionsPropsPath = Join-Path $repoRoot "eng/Versions.props" +$cgManifestPath = Join-Path $repoRoot "src/Templates/src/cgmanifest.json" + +# Read the Versions.props file +Write-Host "Reading versions from: $versionsPropsPath" +[xml]$versionsProps = Get-Content $versionsPropsPath -Raw + +# Check if cgmanifest.json exists +if (Test-Path $cgManifestPath) { + Write-Host "Reading existing cgmanifest.json: $cgManifestPath" + $cgManifest = Get-Content $cgManifestPath -Raw | ConvertFrom-Json +} +else { + Write-Host "Creating a new cgmanifest.json file" + $cgManifest = @{ + '$schema' = 'https://json.schemastore.org/component-detection-manifest.json' + version = 1 + registrations = @() + } | ConvertTo-Json -Depth 10 | ConvertFrom-Json +} + +# Create a mapping of package names to version property names in Versions.props +$packageVersionMappings = @{ + # Microsoft.NET.Test.Sdk and test-related packages + 'Microsoft.NET.Test.Sdk' = 'MicrosoftNETTestSdkPackageVersion' + 'xunit' = 'XunitPackageVersion' + 'xunit.runner.visualstudio' = 'XunitRunnerVisualStudioPackageVersion' + 'xunit.analyzer' = 'XUnitAnalyzersPackageVersion' + 'coverlet.collector' = 'CoverletCollectorPackageVersion' + + # Microsoft Extensions packages + 'Microsoft.Extensions.Logging.Debug' = 'MicrosoftExtensionsLoggingDebugVersion' + 'Microsoft.Extensions.Configuration' = 'MicrosoftExtensionsConfigurationVersion' + 'Microsoft.Extensions.DependencyInjection' = 'MicrosoftExtensionsDependencyInjectionVersion' + + # Other packages + 'Microsoft.WindowsAppSDK' = 'MicrosoftWindowsAppSDKPackageVersion' + 'Microsoft.Graphics.Win2D' = 'MicrosoftGraphicsWin2DPackageVersion' + 'Microsoft.Windows.SDK.BuildTools' = 'MicrosoftWindowsSDKBuildToolsPackageVersion' + + # Additional packages specified by the user + 'Syncfusion.Maui.Toolkit' = 'SyncfusionMauiToolkitPackageVersion' + 'Microsoft.Data.Sqlite.Core' = 'MicrosoftDataSqliteCorePackageVersion' + 'SQLitePCLRaw.bundle_green' = 'SQLitePCLRawBundleGreenPackageVersion' + 'CommunityToolkit.Mvvm' = 'CommunityToolkitMvvmPackageVersion' +} + +# Initialize new registrations list +$newRegistrations = New-Object System.Collections.ArrayList + +# Function to create a new package entry +function New-PackageEntry { + param( + [string]$PackageName, + [string]$PackageVersion + ) + + return @{ + component = @{ + type = 'nuget' + nuget = @{ + name = $PackageName + version = $PackageVersion + } + } + } +} + +# Handle CommunityToolkit.Maui versions first +Write-Host "Setting up CommunityToolkit.Maui entries..." + +# Get current version +$currentVersion = $null +foreach ($propertyGroup in $versionsProps.Project.PropertyGroup) { + if ($null -ne $propertyGroup.CommunityToolkitMauiPackageVersion) { + $currentVersion = $propertyGroup.CommunityToolkitMauiPackageVersion.ToString().Trim() + if (-not [string]::IsNullOrEmpty($currentVersion)) { + Write-Host "Found current CommunityToolkit.Maui version: $currentVersion" + [void]$newRegistrations.Add((New-PackageEntry -PackageName 'CommunityToolkit.Maui' -PackageVersion $currentVersion)) + break + } + } +} + +# Get previous version +$previousVersion = $null +foreach ($propertyGroup in $versionsProps.Project.PropertyGroup) { + if ($null -ne $propertyGroup.CommunityToolkitMauiPreviousPackageVersion) { + $previousVersion = $propertyGroup.CommunityToolkitMauiPreviousPackageVersion.ToString().Trim() + if (-not [string]::IsNullOrEmpty($previousVersion)) { + Write-Host "Found previous CommunityToolkit.Maui version: $previousVersion" + [void]$newRegistrations.Add((New-PackageEntry -PackageName 'CommunityToolkit.Maui' -PackageVersion $previousVersion)) + break + } + } +} + +# Process other packages +foreach ($package in $packageVersionMappings.GetEnumerator()) { + $packageName = $package.Key + $versionPropertyName = $package.Value + $version = $null + + # Look for the version in PropertyGroups + foreach ($propertyGroup in $versionsProps.Project.PropertyGroup) { + if ($propertyGroup.$versionPropertyName) { + $version = $propertyGroup.$versionPropertyName.ToString().Trim() + if (-not [string]::IsNullOrEmpty($version)) { + Write-Host "Found $packageName version: $version" + [void]$newRegistrations.Add((New-PackageEntry -PackageName $packageName -PackageVersion $version)) + break + } + } + } + + if ([string]::IsNullOrEmpty($version)) { + Write-Warning "Could not find version for $packageName (property: $versionPropertyName)" + } +} + +# Update the manifest +$cgManifest.registrations = $newRegistrations + +# Save the updated manifest +$cgManifest | ConvertTo-Json -Depth 10 | Out-File $cgManifestPath -Encoding utf8 +Write-Host "Updated cgmanifest.json saved to: $cgManifestPath" + +# Print summary +Write-Host "Successfully added $($newRegistrations.Count) package registrations to cgmanifest.json" diff --git a/global.json b/global.json index 679feeee8d3e..4a2c7f91c8f3 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "tools": { - "dotnet": "9.0.104" + "dotnet": "9.0.105" }, "msbuild-sdks": { "MSBuild.Sdk.Extras": "3.0.44", "Microsoft.Build.NoTargets": "3.7.0", - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.25164.2" + "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.25208.6" }, "sdk": { "allowPrerelease": false diff --git a/maui.code-workspace b/maui.code-workspace new file mode 100644 index 000000000000..ccd94e18a897 --- /dev/null +++ b/maui.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "dotnet.defaultSolution": "Microsoft.Maui-vscode.sln" + } +} \ No newline at end of file diff --git a/src/Compatibility/Core/src/iOS/Renderers/FormsCheckBox.cs b/src/Compatibility/Core/src/iOS/Renderers/FormsCheckBox.cs index b2234516b7f9..d78f5926ecdb 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/FormsCheckBox.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/FormsCheckBox.cs @@ -176,60 +176,65 @@ internal virtual void DrawCheckMark(UIBezierPath path) internal virtual UIImage CreateCheckBox(UIImage check) { - UIGraphics.BeginImageContextWithOptions(new CGSize(_defaultSize, _defaultSize), false, 0); - var context = UIGraphics.GetCurrentContext(); - context.SaveState(); + var renderer = new UIGraphicsImageRenderer(new CGSize(_defaultSize, _defaultSize), new UIGraphicsImageRendererFormat() + { + Opaque = false, + Scale = 0, + }); - var checkedColor = CheckBoxTintUIColor; - checkedColor.SetFill(); - checkedColor.SetStroke(); + return renderer.CreateImage((context) => + { + context.CGContext.SaveState(); - var vPadding = _lineWidth / 2; - var hPadding = _lineWidth / 2; - var diameter = _defaultSize - _lineWidth; + var checkedColor = CheckBoxTintUIColor; + checkedColor.SetFill(); + checkedColor.SetStroke(); - var backgroundRect = new CGRect(hPadding, vPadding, diameter, diameter); - var boxPath = CreateBoxPath(backgroundRect); - boxPath.LineWidth = _lineWidth; - boxPath.Stroke(); + var vPadding = _lineWidth / 2; + var hPadding = _lineWidth / 2; + var diameter = _defaultSize - _lineWidth; - if (check != null) - { - boxPath.Fill(); - check.Draw(new CGPoint(0, 0), CGBlendMode.DestinationOut, 1); - } + var backgroundRect = new CGRect(hPadding, vPadding, diameter, diameter); + var boxPath = CreateBoxPath(backgroundRect); + + boxPath.LineWidth = _lineWidth; + boxPath.Stroke(); - context.RestoreState(); - var img = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); + if (check is not null) + { + boxPath.Fill(); + check.Draw(new CGPoint(0, 0), CGBlendMode.DestinationOut, 1); + } - return img; + context.CGContext.RestoreState(); + }); } internal UIImage CreateCheckMark() { - UIGraphics.BeginImageContextWithOptions(new CGSize(_defaultSize, _defaultSize), false, 0); - var context = UIGraphics.GetCurrentContext(); - context.SaveState(); - - var vPadding = _lineWidth / 2; - var hPadding = _lineWidth / 2; - var diameter = _defaultSize - _lineWidth; - - var checkPath = CreateCheckPath(); - - context.TranslateCTM(hPadding + (nfloat)(0.05 * diameter), vPadding + (nfloat)(0.1 * diameter)); - context.ScaleCTM(diameter, diameter); - DrawCheckMark(checkPath); - UIColor.White.SetStroke(); - checkPath.Stroke(); - - context.RestoreState(); - var img = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); + var renderer = new UIGraphicsImageRenderer(new CGSize(_defaultSize, _defaultSize), new UIGraphicsImageRendererFormat() + { + Opaque = false, + Scale = 0, + }); - return img; + return renderer.CreateImage((context) => + { + context.CGContext.SaveState(); + + var vPadding = _lineWidth / 2; + var hPadding = _lineWidth / 2; + var diameter = _defaultSize - _lineWidth; + + var checkPath = CreateCheckPath(); + context.CGContext.TranslateCTM(hPadding + (nfloat)(0.05 * diameter), vPadding + (nfloat)(0.1 * diameter)); + context.CGContext.ScaleCTM(diameter, diameter); + DrawCheckMark(checkPath); + UIColor.White.SetStroke(); + checkPath.Stroke(); + context.CGContext.RestoreState(); + }); } protected override void Dispose(bool disposing) diff --git a/src/Compatibility/Core/src/iOS/Renderers/ImageRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/ImageRenderer.cs index 975fd4bd13c2..6dd72d8d8a81 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/ImageRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/ImageRenderer.cs @@ -255,16 +255,22 @@ public Task LoadImageAsync( var attString = new NSAttributedString(fontsource.Glyph, font: font, foregroundColor: iconcolor.ToPlatform()); var imagesize = ((NSString)fontsource.Glyph).GetSizeUsingAttributes(attString.GetUIKitAttributes(0, out _)); - UIGraphics.BeginImageContextWithOptions(imagesize, false, 0f); - var ctx = new NSStringDrawingContext(); - var boundingRect = attString.GetBoundingRect(imagesize, (NSStringDrawingOptions)0, ctx); - attString.DrawString(new RectangleF( - imagesize.Width / 2 - boundingRect.Size.Width / 2, - imagesize.Height / 2 - boundingRect.Size.Height / 2, - imagesize.Width, - imagesize.Height)); - image = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); + var renderer = new UIGraphicsImageRenderer(imagesize, new UIGraphicsImageRendererFormat() + { + Opaque = false, + Scale = 0, + }); + + image = renderer.CreateImage((context) => + { + var ctx = new NSStringDrawingContext(); + var boundingRect = attString.GetBoundingRect(imagesize, (NSStringDrawingOptions)0, ctx); + attString.DrawString(new RectangleF( + imagesize.Width / 2 - boundingRect.Size.Width / 2, + imagesize.Height / 2 - boundingRect.Size.Height / 2, + imagesize.Width, + imagesize.Height)); + }); if (image != null && iconcolor != _defaultColor) image = image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal); diff --git a/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs b/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs index 9ee778516ba9..e268af3166de 100644 --- a/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs +++ b/src/Compatibility/Core/src/iOS/Renderers/SwipeViewRenderer.cs @@ -724,12 +724,16 @@ UIImage MaxResizeSwipeItemIconImage(UIImage sourceImage, nfloat maxWidth, nfloat var width = maxResizeFactor * sourceSize.Width; var height = maxResizeFactor * sourceSize.Height; - UIGraphics.BeginImageContextWithOptions(new CGSize((nfloat)width, (nfloat)height), false, 0); - sourceImage.Draw(new CGRect(0, 0, (nfloat)width, (nfloat)height)); - var resultImage = UIGraphics.GetImageFromCurrentImageContext(); - UIGraphics.EndImageContext(); + var renderer = new UIGraphicsImageRenderer(new CGSize((nfloat)width, (nfloat)height), new UIGraphicsImageRendererFormat() + { + Opaque = false, + Scale = 0, + }); - return resultImage; + return renderer.CreateImage((context) => + { + sourceImage.Draw(new CGRect(0, 0, (nfloat)width, (nfloat)height)); + }); } void HandleTouchInteractions(GestureStatus status, CGPoint point) diff --git a/src/Controls/Maps/src/AppHostBuilderExtensions.cs b/src/Controls/Maps/src/AppHostBuilderExtensions.cs index ab52e85cbbe5..31dfcc262545 100644 --- a/src/Controls/Maps/src/AppHostBuilderExtensions.cs +++ b/src/Controls/Maps/src/AppHostBuilderExtensions.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using Microsoft.Maui.Controls.Maps; using Microsoft.Maui.Handlers; using Microsoft.Maui.Hosting; @@ -40,12 +38,12 @@ public static MauiAppBuilder UseMauiMaps(this MauiAppBuilder builder) .OnCreate((a, b) => { - Microsoft.Maui.Maps.Handlers.MapHandler.Bundle = b; + MapHandler.Bundle = b; if (GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(a) == ConnectionResult.Success) { try { - MapsInitializer.Initialize(a); + MapsInitializer.Initialize(a, MapsInitializer.Renderer.Latest, null); } catch (Exception e) { diff --git a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml index 6641e3aed4ea..f5a50bde66c5 100644 --- a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml +++ b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml @@ -132,13 +132,6 @@ - - - - - -