mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 00:30:49 +00:00
Merge pull request #34641 from ClickHouse/version-and-release
refactor version_helper, create release script
This commit is contained in:
commit
4f84406136
@ -1,12 +1,16 @@
|
||||
// autogenerated by ./StorageSystemContributors.sh
|
||||
// autogenerated by tests/ci/version_helper.py
|
||||
const char * auto_contributors[] {
|
||||
"0xflotus",
|
||||
"13DaGGeR",
|
||||
"20018712",
|
||||
"243f6a88 85a308d3",
|
||||
"243f6a8885a308d313198a2e037",
|
||||
"3ldar-nasyrov",
|
||||
"7",
|
||||
"821008736@qq.com",
|
||||
"ANDREI STAROVEROV",
|
||||
"Aaron Katz",
|
||||
"Adri Fernandez",
|
||||
"Ahmed Dardery",
|
||||
"Aimiyoo",
|
||||
"Akazz",
|
||||
@ -19,15 +23,15 @@ const char * auto_contributors[] {
|
||||
"Aleksandrov Vladimir",
|
||||
"Aleksei Levushkin",
|
||||
"Aleksei Semiglazov",
|
||||
"Aleksey Akulovich",
|
||||
"Aleksey",
|
||||
"Aleksey Akulovich",
|
||||
"Alex",
|
||||
"Alex Bocharov",
|
||||
"Alex Cao",
|
||||
"Alex Karo",
|
||||
"Alex Krash",
|
||||
"Alex Ryndin",
|
||||
"Alex Zatelepin",
|
||||
"Alex",
|
||||
"Alexander Avdonkin",
|
||||
"Alexander Bezpiatov",
|
||||
"Alexander Burmak",
|
||||
@ -55,20 +59,21 @@ const char * auto_contributors[] {
|
||||
"Alexandr Kondratev",
|
||||
"Alexandr Krasheninnikov",
|
||||
"Alexandr Orlov",
|
||||
"Alexandra Latysheva",
|
||||
"Alexandra",
|
||||
"Alexandra Latysheva",
|
||||
"Alexandre Snarskii",
|
||||
"Alexei Averchenko",
|
||||
"Alexey",
|
||||
"Alexey Arno",
|
||||
"Alexey Boykov",
|
||||
"Alexey Dushechkin",
|
||||
"Alexey Elymanov",
|
||||
"Alexey Gusev",
|
||||
"Alexey Ilyukhov",
|
||||
"Alexey Milovidov",
|
||||
"Alexey Tronov",
|
||||
"Alexey Vasiliev",
|
||||
"Alexey Zatelepin",
|
||||
"Alexey",
|
||||
"Alexsey Shestakov",
|
||||
"Ali Demirci",
|
||||
"Aliaksandr Pliutau",
|
||||
@ -84,14 +89,17 @@ const char * auto_contributors[] {
|
||||
"Anastasiya Tsarkova",
|
||||
"Anatoly Pugachev",
|
||||
"Andr0901",
|
||||
"Andre Marianiello",
|
||||
"Andreas Hunkeler",
|
||||
"AndreevDm",
|
||||
"Andrei Bodrov",
|
||||
"Andrei Ch",
|
||||
"Andrei Chulkov",
|
||||
"Andrei Nekrashevich",
|
||||
"Andrew",
|
||||
"Andrew Grigorev",
|
||||
"Andrew Onyshchuk",
|
||||
"Andrey",
|
||||
"Andrey Chulkov",
|
||||
"Andrey Dudin",
|
||||
"Andrey Kadochnikov",
|
||||
@ -103,12 +111,13 @@ const char * auto_contributors[] {
|
||||
"Andrey Torsunov",
|
||||
"Andrey Urusov",
|
||||
"Andrey Z",
|
||||
"Andrey",
|
||||
"Andrii Buriachevskyi",
|
||||
"Andy Liang",
|
||||
"Andy Yang",
|
||||
"Anmol Arora",
|
||||
"Anna Shakhova",
|
||||
"Anna",
|
||||
"Anna Shakhova",
|
||||
"Anselmo D. Adams",
|
||||
"Anthony N. Simon",
|
||||
"Anton Ivashkin",
|
||||
"Anton Kobzev",
|
||||
@ -121,6 +130,7 @@ const char * auto_contributors[] {
|
||||
"Anton Tikhonov",
|
||||
"Anton Yuzhaninov",
|
||||
"Anton Zhabolenko",
|
||||
"Antonio Andelic",
|
||||
"Ariel Robaldo",
|
||||
"Arsen Hakobyan",
|
||||
"Arslan G",
|
||||
@ -136,9 +146,9 @@ const char * auto_contributors[] {
|
||||
"Arthur Petukhovsky",
|
||||
"Arthur Tokarchuk",
|
||||
"Arthur Wong",
|
||||
"Artur",
|
||||
"Artur Beglaryan",
|
||||
"Artur Filatenkov",
|
||||
"Artur",
|
||||
"AsiaKorushkina",
|
||||
"Atri Sharma",
|
||||
"Avogar",
|
||||
@ -149,6 +159,7 @@ const char * auto_contributors[] {
|
||||
"BanyRule",
|
||||
"Baudouin Giard",
|
||||
"BayoNet",
|
||||
"Ben",
|
||||
"Benjamin Naecker",
|
||||
"Bertrand Junqua",
|
||||
"Bharat Nallan",
|
||||
@ -156,12 +167,13 @@ const char * auto_contributors[] {
|
||||
"Bill",
|
||||
"BiteTheDDDDt",
|
||||
"BlahGeek",
|
||||
"Bogdan Voronin",
|
||||
"Bogdan",
|
||||
"Bogdan Voronin",
|
||||
"BohuTANG",
|
||||
"Bolinov",
|
||||
"BoloniniD",
|
||||
"Boris Granveaud",
|
||||
"Boris Kuschel",
|
||||
"Bowen Masco",
|
||||
"Braulio Valdivielso",
|
||||
"Brett Hoerner",
|
||||
@ -173,6 +185,8 @@ const char * auto_contributors[] {
|
||||
"Chen Yufei",
|
||||
"Chienlung Cheung",
|
||||
"Christian",
|
||||
"Christoph Wurm",
|
||||
"Chun-Sheng, Li",
|
||||
"Ciprian Hacman",
|
||||
"Clement Rodriguez",
|
||||
"ClickHouse Admin",
|
||||
@ -181,12 +195,15 @@ const char * auto_contributors[] {
|
||||
"Colum",
|
||||
"Constantin S. Pan",
|
||||
"Constantine Peresypkin",
|
||||
"CoolT2",
|
||||
"CurtizJ",
|
||||
"DF5HSE",
|
||||
"DIAOZHAFENG",
|
||||
"Daniel Bershatsky",
|
||||
"Daniel Dao",
|
||||
"Daniel Qin",
|
||||
"Danila Kutenin",
|
||||
"Dao",
|
||||
"Dao Minh Thuc",
|
||||
"Daria Mozhaeva",
|
||||
"Dario",
|
||||
@ -198,13 +215,16 @@ const char * auto_contributors[] {
|
||||
"Denis Zhuravlev",
|
||||
"Denny Crane",
|
||||
"Derek Perkins",
|
||||
"DimaAmega",
|
||||
"Ding Xiang Fei",
|
||||
"Dmitriev Mikhail",
|
||||
"Dmitrii Kovalkov",
|
||||
"Dmitrii Mokhnatkin",
|
||||
"Dmitrii Raev",
|
||||
"Dmitriy",
|
||||
"Dmitriy Dorofeev",
|
||||
"Dmitriy Lushnikov",
|
||||
"Dmitriy",
|
||||
"Dmitry",
|
||||
"Dmitry Belyavtsev",
|
||||
"Dmitry Bilunov",
|
||||
"Dmitry Galuza",
|
||||
@ -217,7 +237,6 @@ const char * auto_contributors[] {
|
||||
"Dmitry Rubashkin",
|
||||
"Dmitry S..ky / skype: dvska-at-skype",
|
||||
"Dmitry Ukolov",
|
||||
"Dmitry",
|
||||
"Doge",
|
||||
"Dongdong Yang",
|
||||
"DoomzD",
|
||||
@ -232,8 +251,8 @@ const char * auto_contributors[] {
|
||||
"Elizaveta Mironyuk",
|
||||
"Elykov Alexandr",
|
||||
"Emmanuel Donin de Rosière",
|
||||
"Eric Daniel",
|
||||
"Eric",
|
||||
"Eric Daniel",
|
||||
"Erixonich",
|
||||
"Ernest Poletaev",
|
||||
"Eugene Klimov",
|
||||
@ -243,9 +262,9 @@ const char * auto_contributors[] {
|
||||
"Evgeniia Sudarikova",
|
||||
"Evgeniy Gatov",
|
||||
"Evgeniy Udodov",
|
||||
"Evgeny",
|
||||
"Evgeny Konkov",
|
||||
"Evgeny Markov",
|
||||
"Evgeny",
|
||||
"Ewout",
|
||||
"FArthur-cmd",
|
||||
"Fabian Stäber",
|
||||
@ -254,10 +273,12 @@ const char * auto_contributors[] {
|
||||
"Fan()",
|
||||
"FawnD2",
|
||||
"Federico Ceratto",
|
||||
"Federico Rodriguez",
|
||||
"FeehanG",
|
||||
"FgoDt",
|
||||
"Filatenkov Artur",
|
||||
"Filipe Caixeta",
|
||||
"Filippov Denis",
|
||||
"Flowyi",
|
||||
"Francisco Barón",
|
||||
"Frank Chen",
|
||||
@ -269,8 +290,10 @@ const char * auto_contributors[] {
|
||||
"Gagan Arneja",
|
||||
"Gao Qiang",
|
||||
"Gary Dotzler",
|
||||
"George G",
|
||||
"Gaurav Kumar",
|
||||
"Geoff Genz",
|
||||
"George",
|
||||
"George G",
|
||||
"George3d6",
|
||||
"Georgy Ginzburg",
|
||||
"Gervasio Varela",
|
||||
@ -278,28 +301,35 @@ const char * auto_contributors[] {
|
||||
"Gleb Novikov",
|
||||
"Gleb-Tretyakov",
|
||||
"Gregory",
|
||||
"Grigory",
|
||||
"Grigory Buteyko",
|
||||
"Grigory Pervakov",
|
||||
"Grigory",
|
||||
"Guillaume Tassery",
|
||||
"Guo Wei (William)",
|
||||
"Haavard Kvaalen",
|
||||
"Habibullah Oladepo",
|
||||
"Hamoon",
|
||||
"Harry-Lee",
|
||||
"HarryLeeIBM",
|
||||
"Hasitha Kanchana",
|
||||
"Hasnat",
|
||||
"Heena Bansal",
|
||||
"HeenaBansal2009",
|
||||
"Hiroaki Nakamura",
|
||||
"HuFuwang",
|
||||
"Hui Wang",
|
||||
"ILya Limarenko",
|
||||
"Igor",
|
||||
"Igor Hatarist",
|
||||
"Igor Mineev",
|
||||
"Igor Nikonov",
|
||||
"Igor Strykhar",
|
||||
"Igor",
|
||||
"Igr Mineev",
|
||||
"Igr",
|
||||
"Igr Mineev",
|
||||
"Ikko Ashimine",
|
||||
"Ildar Musin",
|
||||
"Ildus Kurbangaliev",
|
||||
"Ilya",
|
||||
"Ilya Breev",
|
||||
"Ilya Golshtein",
|
||||
"Ilya Khomutov",
|
||||
@ -310,10 +340,11 @@ const char * auto_contributors[] {
|
||||
"Ilya Shipitsin",
|
||||
"Ilya Skrypitsa",
|
||||
"Ilya Yatsishin",
|
||||
"Ilya",
|
||||
"IlyaTsoi",
|
||||
"ImgBotApp",
|
||||
"Islam Israfilov (Islam93)",
|
||||
"Islam Israfilov",
|
||||
"Islam Israfilov (Islam93)",
|
||||
"Ivan",
|
||||
"Ivan A. Torgashov",
|
||||
"Ivan Babrou",
|
||||
"Ivan Blinkov",
|
||||
@ -325,27 +356,29 @@ const char * auto_contributors[] {
|
||||
"Ivan Remen",
|
||||
"Ivan Starkov",
|
||||
"Ivan Zhukov",
|
||||
"Ivan",
|
||||
"Jack Song",
|
||||
"JackyWoo",
|
||||
"Jacob Hayes",
|
||||
"Jake Liu",
|
||||
"Jakub Kuklis",
|
||||
"JaosnHsieh",
|
||||
"Jason Keirstead",
|
||||
"Jason",
|
||||
"Jason Keirstead",
|
||||
"Javi Santana",
|
||||
"Javi santana bot",
|
||||
"JaySon-Huang",
|
||||
"Jean Baptiste Favre",
|
||||
"Jeffrey Dang",
|
||||
"Jiading Guo",
|
||||
"Jiang Tao",
|
||||
"Jochen Schalanda",
|
||||
"John",
|
||||
"John Hummel",
|
||||
"John Skopis",
|
||||
"John",
|
||||
"Jonatas Freitas",
|
||||
"João Figueiredo",
|
||||
"Julian Zhou",
|
||||
"Justin Hilliard",
|
||||
"Kang Liu",
|
||||
"Karl Pietrzak",
|
||||
"Keiji Yoshida",
|
||||
@ -375,7 +408,9 @@ const char * auto_contributors[] {
|
||||
"Ky Li",
|
||||
"LB",
|
||||
"Latysheva Alexandra",
|
||||
"Lemore",
|
||||
"Leonardo Cecchi",
|
||||
"Leonid Krylov",
|
||||
"Leopold Schabel",
|
||||
"Lev Borodin",
|
||||
"Lewinma",
|
||||
@ -391,9 +426,9 @@ const char * auto_contributors[] {
|
||||
"M0r64n",
|
||||
"MagiaGroz",
|
||||
"Maks Skorokhod",
|
||||
"Maksim",
|
||||
"Maksim Fedotov",
|
||||
"Maksim Kita",
|
||||
"Maksim",
|
||||
"Malte",
|
||||
"Marat IDRISOV",
|
||||
"Marek Vavrusa",
|
||||
@ -412,10 +447,11 @@ const char * auto_contributors[] {
|
||||
"Masha",
|
||||
"Matthew Peveler",
|
||||
"Matwey V. Kornilov",
|
||||
"Max",
|
||||
"Max Akhmedov",
|
||||
"Max Bruce",
|
||||
"Max Vetrov",
|
||||
"Max",
|
||||
"MaxTheHuman",
|
||||
"MaxWk",
|
||||
"Maxim Akhmedov",
|
||||
"Maxim Babenko",
|
||||
@ -430,6 +466,7 @@ const char * auto_contributors[] {
|
||||
"Maxim Ulanovskiy",
|
||||
"MaximAL",
|
||||
"Mc.Spring",
|
||||
"Meena-Renganathan",
|
||||
"MeiK",
|
||||
"Memo",
|
||||
"Metehan Çetinkaya",
|
||||
@ -439,18 +476,21 @@ const char * auto_contributors[] {
|
||||
"Michael Monashev",
|
||||
"Michael Razuvaev",
|
||||
"Michael Smitasin",
|
||||
"Michail Safronov",
|
||||
"Michal Lisowski",
|
||||
"MicrochipQ",
|
||||
"Miguel Fernández",
|
||||
"Mihail Fandyushin",
|
||||
"Mikahil Nacharov",
|
||||
"Mike",
|
||||
"Mike F",
|
||||
"Mike Kot",
|
||||
"Mike",
|
||||
"Mikhail",
|
||||
"Mikhail Andreev",
|
||||
"Mikhail Cheshkov",
|
||||
"Mikhail Fandyushin",
|
||||
"Mikhail Filimonov",
|
||||
"Mikhail Fursov",
|
||||
"Mikhail Gaidamaka",
|
||||
"Mikhail Korotov",
|
||||
"Mikhail Malafeev",
|
||||
@ -458,18 +498,19 @@ const char * auto_contributors[] {
|
||||
"Mikhail Salosin",
|
||||
"Mikhail Surin",
|
||||
"Mikhail f. Shiryaev",
|
||||
"Mikhail",
|
||||
"MikuSugar",
|
||||
"Milad Arabi",
|
||||
"Misko Lee",
|
||||
"Mohamad Fadhil",
|
||||
"Mohammad Hossein Sekhavat",
|
||||
"Mojtaba Yaghoobzadeh",
|
||||
"Mostafa Dahab",
|
||||
"MovElb",
|
||||
"Mr.General",
|
||||
"Murat Kabilov",
|
||||
"MyroTk",
|
||||
"Mátyás Jani",
|
||||
"N. Kolotov",
|
||||
"NIKITA MIKHAILOV",
|
||||
"Narek Galstyan",
|
||||
"Natasha Murashkina",
|
||||
@ -477,15 +518,17 @@ const char * auto_contributors[] {
|
||||
"Neeke Gao",
|
||||
"Neng Liu",
|
||||
"NengLiu",
|
||||
"Nickita Taranov",
|
||||
"Nickita",
|
||||
"Nickita Taranov",
|
||||
"Nickolay Yastrebov",
|
||||
"Nico Mandery",
|
||||
"Nico Piderman",
|
||||
"Nicolae Vartolomei",
|
||||
"Niek",
|
||||
"Nik",
|
||||
"Nikhil Nadig",
|
||||
"Nikhil Raman",
|
||||
"Nikita",
|
||||
"Nikita Lapkov",
|
||||
"Nikita Mikhailov",
|
||||
"Nikita Mikhalev",
|
||||
@ -495,13 +538,13 @@ const char * auto_contributors[] {
|
||||
"Nikita Vasilev",
|
||||
"Nikolai Kochetov",
|
||||
"Nikolai Sorokin",
|
||||
"Nikolay",
|
||||
"Nikolay Degterinsky",
|
||||
"Nikolay Kirsh",
|
||||
"Nikolay Semyachkin",
|
||||
"Nikolay Shcheglov",
|
||||
"Nikolay Vasiliev",
|
||||
"Nikolay Volosatov",
|
||||
"Nikolay",
|
||||
"Niu Zhaojie",
|
||||
"Odin Hultgren Van Der Horst",
|
||||
"Okada Haruki",
|
||||
@ -517,11 +560,13 @@ const char * auto_contributors[] {
|
||||
"OnePiece",
|
||||
"Onehr7",
|
||||
"Orivej Desh",
|
||||
"Orkhan Zeynalli",
|
||||
"Oskar Wojciski",
|
||||
"OuO",
|
||||
"PHO",
|
||||
"Paramtamtam",
|
||||
"Patrick Zippenfenig",
|
||||
"Pavel",
|
||||
"Pavel Cheremushkin",
|
||||
"Pavel Kartaviy",
|
||||
"Pavel Kartavyy",
|
||||
@ -531,7 +576,6 @@ const char * auto_contributors[] {
|
||||
"Pavel Medvedev",
|
||||
"Pavel Patrin",
|
||||
"Pavel Yakunin",
|
||||
"Pavel",
|
||||
"Pavlo Bashynskiy",
|
||||
"Pawel Rog",
|
||||
"Peignon Melvyn",
|
||||
@ -545,6 +589,7 @@ const char * auto_contributors[] {
|
||||
"Pysaoke",
|
||||
"Quid37",
|
||||
"Rafael David Tinoco",
|
||||
"Rajkumar",
|
||||
"Ramazan Polat",
|
||||
"Ravengg",
|
||||
"Raúl Marín",
|
||||
@ -556,8 +601,10 @@ const char * auto_contributors[] {
|
||||
"Ri",
|
||||
"Rich Raposa",
|
||||
"Robert Hodges",
|
||||
"RogerYK",
|
||||
"Rohit Agarwal",
|
||||
"Romain Neutron",
|
||||
"Roman",
|
||||
"Roman Bug",
|
||||
"Roman Chyrva",
|
||||
"Roman Lipovsky",
|
||||
@ -566,13 +613,15 @@ const char * auto_contributors[] {
|
||||
"Roman Peshkurov",
|
||||
"Roman Tsisyk",
|
||||
"Roman Zhukov",
|
||||
"Roman",
|
||||
"Ruslan Savchenko",
|
||||
"Ruslan",
|
||||
"Ruslan Savchenko",
|
||||
"Russ Frank",
|
||||
"Ruzal Ibragimov",
|
||||
"Ryad ZENINE",
|
||||
"S.M.A. Djawadi",
|
||||
"Saad Ur Rahman",
|
||||
"Sabyanin Maxim",
|
||||
"Safronov Michail",
|
||||
"SaltTan",
|
||||
"Sami Kerola",
|
||||
"Samuel Chou",
|
||||
@ -583,6 +632,7 @@ const char * auto_contributors[] {
|
||||
"Sergei Bocharov",
|
||||
"Sergei Semin",
|
||||
"Sergei Shtykov",
|
||||
"Sergei Trifonov",
|
||||
"Sergei Tsetlin (rekub)",
|
||||
"Sergey Demurin",
|
||||
"Sergey Elantsev",
|
||||
@ -614,26 +664,28 @@ const char * auto_contributors[] {
|
||||
"Stas Kelvich",
|
||||
"Stas Pavlovichev",
|
||||
"Stefan Thies",
|
||||
"Stepan Herold",
|
||||
"Stepan",
|
||||
"Stepan Herold",
|
||||
"Steve-金勇",
|
||||
"Stig Bakken",
|
||||
"Storozhuk Kostiantyn",
|
||||
"Stupnikov Andrey",
|
||||
"SuperBot",
|
||||
"SuperDJY",
|
||||
"Sébastien Launay",
|
||||
"Suzy Wang",
|
||||
"Sébastien",
|
||||
"Sébastien Launay",
|
||||
"TABLUM.IO",
|
||||
"TAC",
|
||||
"TCeason",
|
||||
"Tagir Kuskarov",
|
||||
"Tai White",
|
||||
"Taleh Zaliyev",
|
||||
"Tangaev",
|
||||
"Tatiana Kirillova",
|
||||
"Tatiana",
|
||||
"Teja Srivastasa",
|
||||
"Tatiana Kirillova",
|
||||
"Teja",
|
||||
"Teja Srivastasa",
|
||||
"Tema Novikov",
|
||||
"Tentoshka",
|
||||
"The-Alchemist",
|
||||
@ -655,10 +707,10 @@ const char * auto_contributors[] {
|
||||
"UnamedRus",
|
||||
"V",
|
||||
"VDimir",
|
||||
"Vadim",
|
||||
"Vadim Plakhtinskiy",
|
||||
"Vadim Skipin",
|
||||
"Vadim Volodin",
|
||||
"Vadim",
|
||||
"VadimPE",
|
||||
"Val",
|
||||
"Valera Ryaboshapko",
|
||||
@ -672,8 +724,8 @@ const char * auto_contributors[] {
|
||||
"Veniamin Gvozdikov",
|
||||
"Veselkov Konstantin",
|
||||
"Viachaslau Boben",
|
||||
"Victor Tarnavsky",
|
||||
"Victor",
|
||||
"Victor Tarnavsky",
|
||||
"Viktor Taranenko",
|
||||
"Vitalii S",
|
||||
"Vitaliy Fedorchenko",
|
||||
@ -681,13 +733,15 @@ const char * auto_contributors[] {
|
||||
"Vitaliy Kozlovskiy",
|
||||
"Vitaliy Lyudvichenko",
|
||||
"Vitaliy Zakaznikov",
|
||||
"Vitaly",
|
||||
"Vitaly Artemyev",
|
||||
"Vitaly Baranov",
|
||||
"Vitaly Orlov",
|
||||
"Vitaly Samigullin",
|
||||
"Vitaly Stoyan",
|
||||
"Vitaly",
|
||||
"Vivien Maisonneuve",
|
||||
"Vlad Arkhipov",
|
||||
"Vladimir",
|
||||
"Vladimir Bunchuk",
|
||||
"Vladimir C",
|
||||
"Vladimir Ch",
|
||||
@ -699,7 +753,6 @@ const char * auto_contributors[] {
|
||||
"Vladimir Kopysov",
|
||||
"Vladimir Kozbin",
|
||||
"Vladimir Smirnov",
|
||||
"Vladimir",
|
||||
"Vladislav Rassokhin",
|
||||
"Vladislav Smirnov",
|
||||
"Vojtech Splichal",
|
||||
@ -707,6 +760,7 @@ const char * auto_contributors[] {
|
||||
"Vsevolod Orlov",
|
||||
"Vxider",
|
||||
"Vyacheslav Alipov",
|
||||
"W",
|
||||
"Wang Fenjin",
|
||||
"WangZengrui",
|
||||
"Weiqing Xu",
|
||||
@ -714,8 +768,10 @@ const char * auto_contributors[] {
|
||||
"Winter Zhang",
|
||||
"Xianda Ke",
|
||||
"Xiang Zhou",
|
||||
"Xin Wang",
|
||||
"Y Lu",
|
||||
"Yangkuan Liu",
|
||||
"Yatian Xu",
|
||||
"Yatsishin Ilya",
|
||||
"Yağızcan Değirmenci",
|
||||
"Yegor Andreenko",
|
||||
@ -724,13 +780,14 @@ const char * auto_contributors[] {
|
||||
"Yingfan Chen",
|
||||
"Yiğit Konur",
|
||||
"Yohann Jardin",
|
||||
"Youenn Lebras",
|
||||
"Yuntao Wu",
|
||||
"Yuri Dyachenko",
|
||||
"Yurii Vlasenko",
|
||||
"Yuriy",
|
||||
"Yuriy Baranov",
|
||||
"Yuriy Chernyshov",
|
||||
"Yuriy Korzhenevskiy",
|
||||
"Yuriy",
|
||||
"Yury Karpovich",
|
||||
"Yury Stankevich",
|
||||
"ZhiYong Wang",
|
||||
@ -756,6 +813,7 @@ const char * auto_contributors[] {
|
||||
"alex.lvxin",
|
||||
"alexander kozhikhov",
|
||||
"alexey-milovidov",
|
||||
"alexeypavlenko",
|
||||
"alfredlu",
|
||||
"amesaru",
|
||||
"amoschen",
|
||||
@ -810,10 +868,12 @@ const char * auto_contributors[] {
|
||||
"cms",
|
||||
"cmsxbc",
|
||||
"cn-ds",
|
||||
"cnmade",
|
||||
"comunodi",
|
||||
"congbaoyangrou",
|
||||
"coraxster",
|
||||
"d.v.semenov",
|
||||
"dalei2019",
|
||||
"damozhaeva",
|
||||
"dankondr",
|
||||
"daoready",
|
||||
@ -849,6 +909,7 @@ const char * auto_contributors[] {
|
||||
"ezhaka",
|
||||
"f1yegor",
|
||||
"fancno",
|
||||
"fanzhou",
|
||||
"fastio",
|
||||
"favstovol",
|
||||
"feihengye",
|
||||
@ -863,8 +924,8 @@ const char * auto_contributors[] {
|
||||
"flow",
|
||||
"flynn",
|
||||
"foxxmary",
|
||||
"frank chen",
|
||||
"frank",
|
||||
"frank chen",
|
||||
"franklee",
|
||||
"fredchenbj",
|
||||
"freedomDR",
|
||||
@ -877,8 +938,11 @@ const char * auto_contributors[] {
|
||||
"giordyb",
|
||||
"glockbender",
|
||||
"glushkovds",
|
||||
"grantovsky",
|
||||
"gulige",
|
||||
"guoleiyi",
|
||||
"gyuton",
|
||||
"hanqf-git",
|
||||
"hao.he",
|
||||
"hchen9",
|
||||
"hcz",
|
||||
@ -890,6 +954,7 @@ const char * auto_contributors[] {
|
||||
"huangzhaowei",
|
||||
"hustnn",
|
||||
"huzhichengdd",
|
||||
"ianton-ru",
|
||||
"ice1x",
|
||||
"idfer",
|
||||
"igomac",
|
||||
@ -907,8 +972,8 @@ const char * auto_contributors[] {
|
||||
"jasine",
|
||||
"jasperzhu",
|
||||
"javartisan",
|
||||
"javi santana",
|
||||
"javi",
|
||||
"javi santana",
|
||||
"jennyma",
|
||||
"jetgm",
|
||||
"jianmei zhang",
|
||||
@ -937,6 +1002,8 @@ const char * auto_contributors[] {
|
||||
"levie",
|
||||
"levushkin aleksej",
|
||||
"levysh",
|
||||
"lgbo",
|
||||
"lgbo-ustc",
|
||||
"lhuang0928",
|
||||
"lhuang09287750",
|
||||
"liang.huang",
|
||||
@ -947,6 +1014,7 @@ const char * auto_contributors[] {
|
||||
"listar",
|
||||
"litao91",
|
||||
"liu-bov",
|
||||
"liuneng1994",
|
||||
"liuyangkuan",
|
||||
"liuyimin",
|
||||
"liyang",
|
||||
@ -983,11 +1051,15 @@ const char * auto_contributors[] {
|
||||
"mikael",
|
||||
"mikepop7",
|
||||
"millb",
|
||||
"minhthucdao",
|
||||
"mlkui",
|
||||
"mnkonkova",
|
||||
"mo-avatar",
|
||||
"morty",
|
||||
"moscas",
|
||||
"mreddy017",
|
||||
"msaf1980",
|
||||
"msirm",
|
||||
"muzzlerator",
|
||||
"mwish",
|
||||
"myrrc",
|
||||
@ -1007,6 +1079,7 @@ const char * auto_contributors[] {
|
||||
"ocadaruma",
|
||||
"ogorbacheva",
|
||||
"olegkv",
|
||||
"olevino",
|
||||
"olgarev",
|
||||
"orantius",
|
||||
"p0ny",
|
||||
@ -1014,6 +1087,7 @@ const char * auto_contributors[] {
|
||||
"pawelsz-rb",
|
||||
"pdv-ru",
|
||||
"peshkurov",
|
||||
"peter279k",
|
||||
"philip.han",
|
||||
"pingyu",
|
||||
"potya",
|
||||
@ -1040,8 +1114,10 @@ const char * auto_contributors[] {
|
||||
"roverxu",
|
||||
"ruct",
|
||||
"ryzuo",
|
||||
"s-kat",
|
||||
"santaux",
|
||||
"satanson",
|
||||
"save-my-heart",
|
||||
"sdk2",
|
||||
"serebrserg",
|
||||
"sev7e0",
|
||||
@ -1068,8 +1144,10 @@ const char * auto_contributors[] {
|
||||
"taiyang-li",
|
||||
"tao jiang",
|
||||
"tavplubix",
|
||||
"tekeri",
|
||||
"templarzq",
|
||||
"terrylin",
|
||||
"tesw yew isal",
|
||||
"tianzhou",
|
||||
"tiger.yan",
|
||||
"tison",
|
||||
@ -1080,6 +1158,8 @@ const char * auto_contributors[] {
|
||||
"unegare",
|
||||
"unknown",
|
||||
"urgordeadbeef",
|
||||
"usurai",
|
||||
"vahid-sohrabloo",
|
||||
"vdimir",
|
||||
"velom",
|
||||
"vesslanjin",
|
||||
@ -1121,8 +1201,11 @@ const char * auto_contributors[] {
|
||||
"zhangxiao018",
|
||||
"zhangxiao871",
|
||||
"zhen ni",
|
||||
"zhifeng",
|
||||
"zhongyuankai",
|
||||
"zhoubintao",
|
||||
"zhukai",
|
||||
"zkun",
|
||||
"zlx19950903",
|
||||
"zvonand",
|
||||
"zvrr",
|
||||
@ -1150,6 +1233,7 @@ const char * auto_contributors[] {
|
||||
"曲正鹏",
|
||||
"木木夕120",
|
||||
"未来星___费",
|
||||
"李扬",
|
||||
"极客青年",
|
||||
"枢木",
|
||||
"董海镔",
|
||||
@ -1159,5 +1243,6 @@ const char * auto_contributors[] {
|
||||
"靳阳",
|
||||
"黄朝晖",
|
||||
"黄璞",
|
||||
"박동철",
|
||||
"박현우",
|
||||
nullptr};
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
echo "THIS IS HEAVILY DEPRECATED, USE tests/ci/version_helper.py:update_contributors()"
|
||||
set -x
|
||||
|
||||
# doesn't actually cd to directory, but return absolute path
|
||||
|
@ -175,7 +175,7 @@ def get_release_or_pr(
|
||||
# for pushes to master - major version, but not for performance builds
|
||||
# they havily relies on a fixed path for build package and nobody going
|
||||
# to deploy them somewhere, so it's ok.
|
||||
return ".".join(version.as_tuple()[:2])
|
||||
return f"{version.major}.{version.minor}"
|
||||
# PR number for anything else
|
||||
return str(pr_info.number)
|
||||
|
||||
@ -218,7 +218,7 @@ def main():
|
||||
|
||||
s3_helper = S3Helper("https://s3.amazonaws.com")
|
||||
|
||||
version = get_version_from_repo(REPO_COPY)
|
||||
version = get_version_from_repo()
|
||||
release_or_pr = get_release_or_pr(pr_info, build_config, version)
|
||||
|
||||
s3_path_prefix = "/".join((release_or_pr, pr_info.sha, build_name))
|
||||
@ -255,13 +255,13 @@ def main():
|
||||
docker_image = get_image_with_version(IMAGES_PATH, image_name)
|
||||
image_version = docker_image.version
|
||||
|
||||
logging.info("Got version from repo %s", version.get_version_string())
|
||||
logging.info("Got version from repo %s", version.string)
|
||||
|
||||
version_type = "testing"
|
||||
if "release" in pr_info.labels or "release-lts" in pr_info.labels:
|
||||
version_type = "stable"
|
||||
|
||||
update_version_local(REPO_COPY, pr_info.sha, version, version_type)
|
||||
update_version_local(REPO_COPY, version, version_type)
|
||||
|
||||
logging.info("Updated local files with version")
|
||||
|
||||
@ -290,7 +290,7 @@ def main():
|
||||
build_config,
|
||||
os.path.join(REPO_COPY, "docker/packager"),
|
||||
build_output_path,
|
||||
version.get_version_string(),
|
||||
version.string,
|
||||
image_version,
|
||||
ccache_path,
|
||||
pr_info,
|
||||
|
112
tests/ci/git_helper.py
Normal file
112
tests/ci/git_helper.py
Normal file
@ -0,0 +1,112 @@
|
||||
#!/usr/bin/env python
|
||||
import argparse
|
||||
import os.path as p
|
||||
import re
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
|
||||
TAG_REGEXP = r"^v\d{2}[.][1-9]\d*[.][1-9]\d*[.][1-9]\d*-(testing|prestable|stable|lts)$"
|
||||
SHA_REGEXP = r"^([0-9]|[a-f]){40}$"
|
||||
|
||||
|
||||
# Py 3.8 removeprefix and removesuffix
|
||||
def removeprefix(string: str, prefix: str):
|
||||
if string.startswith(prefix):
|
||||
return string[len(prefix) :] # noqa: ignore E203, false positive
|
||||
return string
|
||||
|
||||
|
||||
def removesuffix(string: str, suffix: str):
|
||||
if string.endswith(suffix):
|
||||
return string[: -len(suffix)]
|
||||
return string
|
||||
|
||||
|
||||
def commit(name: str):
|
||||
r = re.compile(SHA_REGEXP)
|
||||
if not r.match(name):
|
||||
raise argparse.ArgumentTypeError(
|
||||
"commit hash should contain exactly 40 hex characters"
|
||||
)
|
||||
return name
|
||||
|
||||
|
||||
class Runner:
|
||||
"""lightweight check_output wrapper with stripping last NEW_LINE"""
|
||||
|
||||
def __init__(self, cwd: str = p.dirname(p.realpath(__file__))):
|
||||
self.cwd = cwd
|
||||
|
||||
def run(self, cmd: str, cwd: Optional[str] = None) -> str:
|
||||
if cwd is None:
|
||||
cwd = self.cwd
|
||||
return subprocess.check_output(
|
||||
cmd, shell=True, cwd=cwd, encoding="utf-8"
|
||||
).strip()
|
||||
|
||||
|
||||
class Git:
|
||||
"""A small wrapper around subprocess to invoke git commands"""
|
||||
|
||||
def __init__(self):
|
||||
runner = Runner()
|
||||
rel_root = runner.run("git rev-parse --show-cdup")
|
||||
self.root = p.realpath(p.join(runner.cwd, rel_root))
|
||||
self._tag_pattern = re.compile(TAG_REGEXP)
|
||||
runner.cwd = self.root
|
||||
self.run = runner.run
|
||||
self.new_branch = ""
|
||||
self.branch = ""
|
||||
self.sha = ""
|
||||
self.sha_short = ""
|
||||
self.description = ""
|
||||
self.commits_since_tag = 0
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
"""Is used to refresh all attributes after updates, e.g. checkout or commit"""
|
||||
self.branch = self.run("git branch --show-current")
|
||||
self.sha = self.run("git rev-parse HEAD")
|
||||
self.sha_short = self.sha[:11]
|
||||
# The following command shows the most recent tag in a graph
|
||||
# Format should match TAG_REGEXP
|
||||
self.latest_tag = self.run("git describe --tags --abbrev=0")
|
||||
# Format should be: {latest_tag}-{commits_since_tag}-g{sha_short}
|
||||
self.description = self.run("git describe --tags --long")
|
||||
self.commits_since_tag = int(
|
||||
self.run(f"git rev-list {self.latest_tag}..HEAD --count")
|
||||
)
|
||||
|
||||
def _check_tag(self, value: str):
|
||||
if value == "":
|
||||
return
|
||||
if not self._tag_pattern.match(value):
|
||||
raise Exception(f"last tag {value} doesn't match the pattern")
|
||||
|
||||
@property
|
||||
def latest_tag(self) -> str:
|
||||
return self._latest_tag
|
||||
|
||||
@latest_tag.setter
|
||||
def latest_tag(self, value: str):
|
||||
self._check_tag(value)
|
||||
self._latest_tag = value
|
||||
|
||||
@property
|
||||
def new_tag(self) -> str:
|
||||
return self._new_tag
|
||||
|
||||
@new_tag.setter
|
||||
def new_tag(self, value: str):
|
||||
self._check_tag(value)
|
||||
self._new_tag = value
|
||||
|
||||
@property
|
||||
def tweak(self) -> int:
|
||||
if not self.latest_tag.endswith("-testing"):
|
||||
# When we are on the tag, we still need to have tweak=1 to not
|
||||
# break cmake with versions like 12.13.14.0
|
||||
return self.commits_since_tag or 1
|
||||
|
||||
version = self.latest_tag.split("-", maxsplit=1)[0]
|
||||
return int(version.split(".")[-1]) + self.commits_since_tag
|
@ -149,8 +149,8 @@ if __name__ == "__main__":
|
||||
build_name = get_build_name_for_check(CHECK_NAME)
|
||||
|
||||
if pr_info.number == 0:
|
||||
version = get_version_from_repo(REPO_COPY)
|
||||
release_or_pr = ".".join(version.as_tuple()[:2])
|
||||
version = get_version_from_repo()
|
||||
release_or_pr = f"{version.major}.{version.minor}"
|
||||
else:
|
||||
# PR number for anything else
|
||||
release_or_pr = str(pr_info.number)
|
||||
|
@ -8,19 +8,7 @@ from typing import Tuple
|
||||
|
||||
from artifactory import ArtifactorySaaSPath # type: ignore
|
||||
from build_download_helper import dowload_build_with_progress
|
||||
|
||||
|
||||
# Py 3.8 removeprefix and removesuffix
|
||||
def removeprefix(string: str, prefix: str):
|
||||
if string.startswith(prefix):
|
||||
return string[len(prefix) :] # noqa: ignore E203, false positive
|
||||
return string
|
||||
|
||||
|
||||
def removesuffix(string: str, suffix: str):
|
||||
if string.endswith(suffix):
|
||||
return string[: -len(suffix)]
|
||||
return string
|
||||
from git_helper import TAG_REGEXP, commit, removeprefix, removesuffix
|
||||
|
||||
|
||||
# Necessary ENV variables
|
||||
@ -124,7 +112,7 @@ class S3:
|
||||
|
||||
class Release:
|
||||
def __init__(self, name: str):
|
||||
r = re.compile(r"^v\d{2}[.]\d+[.]\d+[.]\d+-(testing|prestable|stable|lts)$")
|
||||
r = re.compile(TAG_REGEXP)
|
||||
# Automatically remove refs/tags/ if full refname passed here
|
||||
name = removeprefix(name, "refs/tags/")
|
||||
if not r.match(name):
|
||||
@ -212,15 +200,6 @@ class Artifactory:
|
||||
return self.__path_helper("_tgz", package_file)
|
||||
|
||||
|
||||
def commit(name: str):
|
||||
r = re.compile(r"^([0-9]|[a-f]){40}$")
|
||||
if not r.match(name):
|
||||
raise argparse.ArgumentTypeError(
|
||||
"commit hash should contain exactly 40 hex characters"
|
||||
)
|
||||
return name
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
|
328
tests/ci/release.py
Executable file
328
tests/ci/release.py
Executable file
@ -0,0 +1,328 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
|
||||
from contextlib import contextmanager
|
||||
from typing import Optional
|
||||
import argparse
|
||||
import logging
|
||||
|
||||
from git_helper import commit
|
||||
from version_helper import (
|
||||
FILE_WITH_VERSION_PATH,
|
||||
ClickHouseVersion,
|
||||
VersionType,
|
||||
git,
|
||||
get_abs_path,
|
||||
get_version_from_repo,
|
||||
update_cmake_version,
|
||||
)
|
||||
|
||||
|
||||
class Release:
|
||||
BIG = ("major", "minor")
|
||||
SMALL = ("patch",)
|
||||
|
||||
def __init__(self, version: ClickHouseVersion):
|
||||
self._version = version
|
||||
self._git = version._git
|
||||
self._release_commit = ""
|
||||
|
||||
def run(self, cmd: str, cwd: Optional[str] = None) -> str:
|
||||
logging.info("Running in directory %s, command:\n %s", cwd or "$CWD", cmd)
|
||||
return self._git.run(cmd, cwd)
|
||||
|
||||
@property
|
||||
def version(self) -> ClickHouseVersion:
|
||||
return self._version
|
||||
|
||||
@version.setter
|
||||
def version(self, version: ClickHouseVersion):
|
||||
if not isinstance(version, ClickHouseVersion):
|
||||
raise ValueError(f"version must be ClickHouseVersion, not {type(version)}")
|
||||
self._version = version
|
||||
|
||||
@property
|
||||
def release_commit(self) -> str:
|
||||
return self._release_commit
|
||||
|
||||
@release_commit.setter
|
||||
def release_commit(self, release_commit: str):
|
||||
self._release_commit = commit(release_commit)
|
||||
|
||||
def check_no_tags_after(self):
|
||||
tags_after_commit = self.run(f"git tag --contains={self.release_commit}")
|
||||
if tags_after_commit:
|
||||
raise Exception(
|
||||
f"Commit {self.release_commit} belongs to following tags:\n"
|
||||
f"{tags_after_commit}\nChoose another commit"
|
||||
)
|
||||
|
||||
def check_branch(self, release_type: str):
|
||||
if release_type in self.BIG:
|
||||
# Commit to spin up the release must belong to a main branch
|
||||
output = self.run(f"git branch --contains={self.release_commit} master")
|
||||
if "master" not in output:
|
||||
raise Exception(
|
||||
f"commit {self.release_commit} must belong to 'master' for "
|
||||
f"{release_type} release"
|
||||
)
|
||||
if release_type in self.SMALL:
|
||||
branch = f"{self.version.major}.{self.version.minor}"
|
||||
if self._git.branch != branch:
|
||||
raise Exception(f"branch must be '{branch}' for {release_type} release")
|
||||
|
||||
def update(self):
|
||||
self._git.update()
|
||||
self.version = get_version_from_repo()
|
||||
|
||||
@contextmanager
|
||||
def _new_branch(self, name: str, start_point: str = ""):
|
||||
self.run(f"git branch {name} {start_point}")
|
||||
try:
|
||||
yield
|
||||
except BaseException:
|
||||
logging.warning("Rolling back created branch %s", name)
|
||||
self.run(f"git branch -D {name}")
|
||||
raise
|
||||
|
||||
@contextmanager
|
||||
def _checkout(self, ref: str, with_rollback: bool = False):
|
||||
orig_ref = self._git.branch or self._git.sha
|
||||
need_rollback = False
|
||||
if ref not in (self._git.branch, self._git.sha):
|
||||
need_rollback = True
|
||||
self.run(f"git checkout {ref}")
|
||||
try:
|
||||
yield
|
||||
except BaseException:
|
||||
logging.warning("Rolling back checked out %s for %s", ref, orig_ref)
|
||||
self.run(f"git reset --hard; git checkout {orig_ref}")
|
||||
raise
|
||||
else:
|
||||
if with_rollback and need_rollback:
|
||||
self.run(f"git checkout {orig_ref}")
|
||||
|
||||
@contextmanager
|
||||
def prestable(self, args: argparse.Namespace):
|
||||
self.check_no_tags_after()
|
||||
# Create release branch
|
||||
# TODO: this place is wrong. If we are in stale branch, it will produce
|
||||
# a wrong version
|
||||
self.update()
|
||||
release_branch = f"{self.version.major}.{self.version.minor}"
|
||||
with self._new_branch(release_branch, self.release_commit):
|
||||
with self._checkout(release_branch, True):
|
||||
self.update()
|
||||
self.version.with_description(VersionType.PRESTABLE)
|
||||
with self._create_gh_release(args):
|
||||
with self._bump_prestable_version(release_branch, args):
|
||||
# At this point everything will rollback automatically
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def testing(self, args: argparse.Namespace):
|
||||
# Create branch for a version bump
|
||||
self.update()
|
||||
# TODO: this place is wrong. If we are in stale branch, it will produce
|
||||
# a wrong version
|
||||
self.version = self.version.update(args.release_type)
|
||||
helper_branch = f"{self.version.major}.{self.version.minor}-prepare"
|
||||
with self._new_branch(helper_branch, self.release_commit):
|
||||
with self._checkout(helper_branch, True):
|
||||
self.update()
|
||||
self.version = self.version.update(args.release_type)
|
||||
with self._bump_testing_version(helper_branch, args):
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def _bump_testing_version(self, helper_branch: str, args: argparse.Namespace):
|
||||
update_cmake_version(self.version)
|
||||
cmake_path = get_abs_path(FILE_WITH_VERSION_PATH)
|
||||
self.run(
|
||||
f"git commit -m 'Update version to {self.version.string}' '{cmake_path}'"
|
||||
)
|
||||
with self._push(helper_branch, args):
|
||||
body_file = get_abs_path(".github/PULL_REQUEST_TEMPLATE.md")
|
||||
self.run(
|
||||
f"gh pr create --repo {args.repo} --title 'Update version after "
|
||||
f"release' --head {helper_branch} --body-file '{body_file}'"
|
||||
)
|
||||
# Here the prestable part is done
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def _bump_prestable_version(self, release_branch: str, args: argparse.Namespace):
|
||||
new_version = self.version.patch_update()
|
||||
update_cmake_version(new_version)
|
||||
cmake_path = get_abs_path(FILE_WITH_VERSION_PATH)
|
||||
self.run(
|
||||
f"git commit -m 'Update version to {new_version.string}' '{cmake_path}'"
|
||||
)
|
||||
with self._push(release_branch, args):
|
||||
self.run(
|
||||
f"gh pr create --repo {args.repo} --title 'Release pull request for "
|
||||
f"branch {release_branch}' --head {release_branch} --body 'This "
|
||||
"PullRequest is a part of ClickHouse release cycle. It is used by CI "
|
||||
"system only. Do not perform any changes with it.' --label release"
|
||||
)
|
||||
# Here the prestable part is done
|
||||
yield
|
||||
|
||||
@contextmanager
|
||||
def _create_gh_release(self, args: argparse.Namespace):
|
||||
with self._create_tag(args):
|
||||
# Preserve tag if version is changed
|
||||
tag = self.version.describe
|
||||
self.run(
|
||||
f"gh release create --prerelease --draft --repo {args.repo} '{tag}'"
|
||||
)
|
||||
try:
|
||||
yield
|
||||
except BaseException:
|
||||
logging.warning("Rolling back release publishing")
|
||||
self.run(f"gh release delete --yes --repo {args.repo} '{tag}'")
|
||||
raise
|
||||
|
||||
@contextmanager
|
||||
def _create_tag(self, args: argparse.Namespace):
|
||||
tag = self.version.describe
|
||||
self.run(f"git tag -a -m 'Release {tag}' '{tag}'")
|
||||
try:
|
||||
with self._push(f"'{tag}'", args):
|
||||
yield
|
||||
except BaseException:
|
||||
logging.warning("Rolling back tag %s", tag)
|
||||
self.run(f"git tag -d '{tag}'")
|
||||
raise
|
||||
|
||||
@contextmanager
|
||||
def _push(self, ref: str, args: argparse.Namespace):
|
||||
self.run(f"git push git@github.com:{args.repo}.git {ref}")
|
||||
try:
|
||||
yield
|
||||
except BaseException:
|
||||
logging.warning("Rolling back pushed ref %s", ref)
|
||||
self.run(f"git push -d git@github.com:{args.repo}.git {ref}")
|
||||
raise
|
||||
|
||||
def do(self, args: argparse.Namespace):
|
||||
self.release_commit = args.commit
|
||||
|
||||
if not args.no_check_dirty:
|
||||
logging.info("Checking if repo is clean")
|
||||
self.run("git diff HEAD --exit-code")
|
||||
|
||||
if not args.no_check_branch:
|
||||
self.check_branch(args.release_type)
|
||||
|
||||
if args.release_type in self.BIG:
|
||||
if args.no_prestable:
|
||||
logging.info("Skipping prestable stage")
|
||||
else:
|
||||
with self.prestable(args):
|
||||
logging.info("Prestable part of the releasing is done")
|
||||
|
||||
with self.testing(args):
|
||||
logging.info("Testing part of the releasing is done")
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
description="Script to release a new ClickHouse version, requires `git` and "
|
||||
"`gh` (github-cli) commands",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--repo",
|
||||
default="ClickHouse/ClickHouse",
|
||||
help="repository to create the release",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--type",
|
||||
default="minor",
|
||||
# choices=Release.BIG+Release.SMALL, # add support later
|
||||
choices=Release.BIG + Release.SMALL,
|
||||
dest="release_type",
|
||||
help="a release type, new branch is created only for 'major' and 'minor'",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-prestable",
|
||||
action="store_true",
|
||||
help=f"for release types in {Release.BIG} skip creating prestable release and "
|
||||
"release branch",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--commit",
|
||||
default=git.sha,
|
||||
type=commit,
|
||||
help="commit create a release, default to HEAD",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-check-dirty",
|
||||
action="store_true",
|
||||
help="skip check repository for uncommited changes",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-check-branch",
|
||||
action="store_true",
|
||||
help="by default, 'major' and 'minor' types work only for master, and 'patch' "
|
||||
"works only for a release branches, that name should be the same as "
|
||||
"'$MAJOR.$MINOR' version, e.g. 22.2",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-publish-release",
|
||||
action="store_true",
|
||||
help="by default, 'major' and 'minor' types work only for master, and 'patch' ",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def prestable():
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
args = parse_args()
|
||||
release = Release(get_version_from_repo())
|
||||
|
||||
release.do(args)
|
||||
|
||||
# if not args.no_publish_release:
|
||||
# # Publish release on github for the current HEAD (master, if checked)
|
||||
# git.run(f"gh release create --draft {git.new_tag} --target {git.sha}")
|
||||
|
||||
## Commit updated versions to HEAD and push to remote
|
||||
# write_versions(versions_file, new_versions)
|
||||
# git.run(f"git checkout -b {git.new_branch}-helper")
|
||||
# git.run(
|
||||
# f"git commit -m 'Auto version update to [{new_versions['VERSION_STRING']}] "
|
||||
# f"[{new_versions['VERSION_REVISION']}]' {versions_file}"
|
||||
# )
|
||||
# git.run(f"git push -u origin {git.new_branch}-helper")
|
||||
# git.run(
|
||||
# f"gh pr create --title 'Update version after release {git.new_branch}' "
|
||||
# f"--body-file '{git.root}/.github/PULL_REQUEST_TEMPLATE.md'"
|
||||
# )
|
||||
|
||||
## Create a new branch from the previous commit and push there with creating
|
||||
## a PR
|
||||
# git.run(f"git checkout -b {git.new_branch} HEAD~")
|
||||
# write_versions(versions_file, versions)
|
||||
# git.run(
|
||||
# f"git commit -m 'Auto version update to [{versions['VERSION_STRING']}] "
|
||||
# f"[{versions['VERSION_REVISION']}]' {versions_file}"
|
||||
# )
|
||||
# git.run(f"git push -u origin {git.new_branch}")
|
||||
# git.run(
|
||||
# "gh pr create --title 'Release pull request for branch "
|
||||
# f"{versions['VERSION_MAJOR']}.{versions['VERSION_MINOR']}' --body "
|
||||
# "'This PullRequest is part of ClickHouse release cycle. It is used by CI "
|
||||
# "system only. Do not perform any changes with it.' --label release"
|
||||
# )
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
368
tests/ci/version_helper.py
Normal file → Executable file
368
tests/ci/version_helper.py
Normal file → Executable file
@ -1,128 +1,191 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import datetime
|
||||
import logging
|
||||
import os.path as p
|
||||
import subprocess
|
||||
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
|
||||
from typing import Dict, Tuple, Union
|
||||
|
||||
from git_helper import Git, removeprefix
|
||||
|
||||
FILE_WITH_VERSION_PATH = "cmake/autogenerated_versions.txt"
|
||||
CHANGELOG_IN_PATH = "debian/changelog.in"
|
||||
CHANGELOG_PATH = "debian/changelog"
|
||||
CONTRIBUTORS_SCRIPT_DIR = "src/Storages/System/"
|
||||
GENERATED_CONTRIBUTORS = "src/Storages/System/StorageSystemContributors.generated.cpp"
|
||||
|
||||
# It has {{ for plain "{"
|
||||
CONTRIBUTORS_TEMPLATE = """// autogenerated by {executer}
|
||||
const char * auto_contributors[] {{
|
||||
{contributors}
|
||||
nullptr}};
|
||||
"""
|
||||
|
||||
VERSIONS = Dict[str, Union[int, str]]
|
||||
|
||||
VERSIONS_TEMPLATE = """# This variables autochanged by release_lib.sh:
|
||||
|
||||
# NOTE: has nothing common with DBMS_TCP_PROTOCOL_VERSION,
|
||||
# only DBMS_TCP_PROTOCOL_VERSION should be incremented on protocol changes.
|
||||
SET(VERSION_REVISION {revision})
|
||||
SET(VERSION_MAJOR {major})
|
||||
SET(VERSION_MINOR {minor})
|
||||
SET(VERSION_PATCH {patch})
|
||||
SET(VERSION_GITHASH {githash})
|
||||
SET(VERSION_DESCRIBE {describe})
|
||||
SET(VERSION_STRING {string})
|
||||
# end of autochange
|
||||
"""
|
||||
|
||||
git = Git()
|
||||
|
||||
|
||||
class ClickHouseVersion():
|
||||
def __init__(self, major, minor, patch, tweak, revision):
|
||||
self.major = major
|
||||
self.minor = minor
|
||||
self.patch = patch
|
||||
self.tweak = tweak
|
||||
self.revision = revision
|
||||
class ClickHouseVersion:
|
||||
"""Immutable version class. On update returns a new instance"""
|
||||
|
||||
def minor_update(self):
|
||||
def __init__(
|
||||
self,
|
||||
major: Union[int, str],
|
||||
minor: Union[int, str],
|
||||
patch: Union[int, str],
|
||||
revision: Union[int, str],
|
||||
git: Git,
|
||||
):
|
||||
self._major = int(major)
|
||||
self._minor = int(minor)
|
||||
self._patch = int(patch)
|
||||
self._revision = int(revision)
|
||||
self._git = git
|
||||
self._describe = ""
|
||||
|
||||
def update(self, part: str) -> "ClickHouseVersion":
|
||||
"""If part is valid, returns a new version"""
|
||||
method = getattr(self, f"{part}_update")
|
||||
return method()
|
||||
|
||||
def major_update(self) -> "ClickHouseVersion":
|
||||
return ClickHouseVersion(self.major + 1, 1, 1, self.revision + 1, self._git)
|
||||
|
||||
def minor_update(self) -> "ClickHouseVersion":
|
||||
return ClickHouseVersion(
|
||||
self.major,
|
||||
self.minor + 1,
|
||||
1,
|
||||
1,
|
||||
self.revision + 1)
|
||||
self.major, self.minor + 1, 1, self.revision + 1, self._git
|
||||
)
|
||||
|
||||
def patch_update(self):
|
||||
def patch_update(self) -> "ClickHouseVersion":
|
||||
return ClickHouseVersion(
|
||||
self.major,
|
||||
self.minor,
|
||||
self.patch + 1,
|
||||
1,
|
||||
self.revision)
|
||||
self.major, self.minor, self.patch + 1, self.revision, self._git
|
||||
)
|
||||
|
||||
def tweak_update(self):
|
||||
return ClickHouseVersion(
|
||||
self.major,
|
||||
self.minor,
|
||||
self.patch,
|
||||
self.tweak + 1,
|
||||
self.revision)
|
||||
@property
|
||||
def major(self) -> int:
|
||||
return self._major
|
||||
|
||||
def get_version_string(self):
|
||||
return '.'.join([
|
||||
str(self.major),
|
||||
str(self.minor),
|
||||
str(self.patch),
|
||||
str(self.tweak)
|
||||
])
|
||||
@property
|
||||
def minor(self) -> int:
|
||||
return self._minor
|
||||
|
||||
def as_tuple(self):
|
||||
@property
|
||||
def patch(self) -> int:
|
||||
return self._patch
|
||||
|
||||
@property
|
||||
def tweak(self) -> int:
|
||||
return self._git.tweak
|
||||
|
||||
@property
|
||||
def revision(self) -> int:
|
||||
return self._revision
|
||||
|
||||
@property
|
||||
def githash(self) -> str:
|
||||
return self._git.sha
|
||||
|
||||
@property
|
||||
def describe(self):
|
||||
return self._describe
|
||||
|
||||
@property
|
||||
def string(self):
|
||||
return ".".join(
|
||||
(str(self.major), str(self.minor), str(self.patch), str(self.tweak))
|
||||
)
|
||||
|
||||
def as_dict(self) -> VERSIONS:
|
||||
return {
|
||||
"revision": self.revision,
|
||||
"major": self.major,
|
||||
"minor": self.minor,
|
||||
"patch": self.patch,
|
||||
"tweak": self.tweak,
|
||||
"githash": self.githash,
|
||||
"describe": self.describe,
|
||||
"string": self.string,
|
||||
}
|
||||
|
||||
def as_tuple(self) -> Tuple[int, int, int, int]:
|
||||
return (self.major, self.minor, self.patch, self.tweak)
|
||||
|
||||
def with_description(self, version_type):
|
||||
if version_type not in VersionType.VALID:
|
||||
raise ValueError(f"version type {version_type} not in {VersionType.VALID}")
|
||||
self._describe = f"v{self.string}-{version_type}"
|
||||
|
||||
class VersionType():
|
||||
|
||||
class VersionType:
|
||||
LTS = "lts"
|
||||
PRESTABLE = "prestable"
|
||||
STABLE = "stable"
|
||||
TESTING = "testing"
|
||||
VALID = (TESTING, PRESTABLE, STABLE, LTS)
|
||||
|
||||
|
||||
def build_version_description(version, version_type):
|
||||
return "v" + version.get_version_string() + "-" + version_type
|
||||
def get_abs_path(path: str) -> str:
|
||||
return p.abspath(p.join(git.root, path))
|
||||
|
||||
|
||||
def _get_version_from_line(line):
|
||||
_, ver_with_bracket = line.strip().split(' ')
|
||||
return ver_with_bracket[:-1]
|
||||
def read_versions(versions_path: str = FILE_WITH_VERSION_PATH) -> VERSIONS:
|
||||
versions = {}
|
||||
path_to_file = get_abs_path(versions_path)
|
||||
with open(path_to_file, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if not line.startswith("SET("):
|
||||
continue
|
||||
|
||||
def get_tweak_from_git_describe(repo_path):
|
||||
# something like v21.12.1.8816-testing-358-g81942b8128
|
||||
# or v21.11.4.14-stable-31-gd6aab025e0
|
||||
output = subprocess.check_output(f"cd {repo_path} && git describe --long", shell=True).decode('utf-8')
|
||||
commits_number = int(output.split('-')[-2])
|
||||
# for testing releases we have to also add fourth number of
|
||||
# the previous tag
|
||||
if 'testing' in output:
|
||||
previous_version = output.split('-')[0]
|
||||
previous_version_commits = int(previous_version.split('.')[3])
|
||||
commits_number += previous_version_commits
|
||||
value = 0 # type: Union[int, str]
|
||||
name, value = line[4:-1].split(maxsplit=1)
|
||||
name = removeprefix(name, "VERSION_").lower()
|
||||
try:
|
||||
value = int(value)
|
||||
except ValueError:
|
||||
pass
|
||||
versions[name] = value
|
||||
|
||||
return commits_number
|
||||
return versions
|
||||
|
||||
|
||||
def get_version_from_repo(repo_path):
|
||||
path_to_file = os.path.join(repo_path, FILE_WITH_VERSION_PATH)
|
||||
major = 0
|
||||
minor = 0
|
||||
patch = 0
|
||||
tweak = get_tweak_from_git_describe(repo_path)
|
||||
version_revision = 0
|
||||
with open(path_to_file, 'r') as ver_file:
|
||||
for line in ver_file:
|
||||
if "VERSION_MAJOR" in line and "math" not in line and "SET" in line:
|
||||
major = _get_version_from_line(line)
|
||||
elif "VERSION_MINOR" in line and "math" not in line and "SET" in line:
|
||||
minor = _get_version_from_line(line)
|
||||
elif "VERSION_PATCH" in line and "math" not in line and "SET" in line:
|
||||
patch = _get_version_from_line(line)
|
||||
elif "VERSION_REVISION" in line and "math" not in line:
|
||||
version_revision = _get_version_from_line(line)
|
||||
return ClickHouseVersion(major, minor, patch, tweak, version_revision)
|
||||
|
||||
|
||||
def _update_cmake_version(repo_path, version, sha, version_type):
|
||||
cmd = """sed -i --follow-symlinks -e "s/SET(VERSION_REVISION [^) ]*/SET(VERSION_REVISION {revision}/g;" \
|
||||
-e "s/SET(VERSION_DESCRIBE [^) ]*/SET(VERSION_DESCRIBE {version_desc}/g;" \
|
||||
-e "s/SET(VERSION_GITHASH [^) ]*/SET(VERSION_GITHASH {sha}/g;" \
|
||||
-e "s/SET(VERSION_MAJOR [^) ]*/SET(VERSION_MAJOR {major}/g;" \
|
||||
-e "s/SET(VERSION_MINOR [^) ]*/SET(VERSION_MINOR {minor}/g;" \
|
||||
-e "s/SET(VERSION_PATCH [^) ]*/SET(VERSION_PATCH {patch}/g;" \
|
||||
-e "s/SET(VERSION_STRING [^) ]*/SET(VERSION_STRING {version_string}/g;" \
|
||||
{path}""".format(
|
||||
revision=version.revision,
|
||||
version_desc=build_version_description(version, version_type),
|
||||
sha=sha,
|
||||
major=version.major,
|
||||
minor=version.minor,
|
||||
patch=version.patch,
|
||||
version_string=version.get_version_string(),
|
||||
path=os.path.join(repo_path, FILE_WITH_VERSION_PATH),
|
||||
def get_version_from_repo(
|
||||
versions_path: str = FILE_WITH_VERSION_PATH,
|
||||
) -> ClickHouseVersion:
|
||||
versions = read_versions(versions_path)
|
||||
return ClickHouseVersion(
|
||||
versions["major"],
|
||||
versions["minor"],
|
||||
versions["patch"],
|
||||
versions["revision"],
|
||||
git,
|
||||
)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
|
||||
def _update_changelog(repo_path, version):
|
||||
def update_cmake_version(
|
||||
version: ClickHouseVersion,
|
||||
versions_path: str = FILE_WITH_VERSION_PATH,
|
||||
):
|
||||
path_to_file = get_abs_path(versions_path)
|
||||
with open(path_to_file, "w", encoding="utf-8") as f:
|
||||
f.write(VERSIONS_TEMPLATE.format_map(version.as_dict()))
|
||||
|
||||
|
||||
def _update_changelog(repo_path: str, version: ClickHouseVersion):
|
||||
cmd = """sed \
|
||||
-e "s/[@]VERSION_STRING[@]/{version_str}/g" \
|
||||
-e "s/[@]DATE[@]/{date}/g" \
|
||||
@ -130,24 +193,117 @@ def _update_changelog(repo_path, version):
|
||||
-e "s/[@]EMAIL[@]/clickhouse-release@yandex-team.ru/g" \
|
||||
< {in_path} > {changelog_path}
|
||||
""".format(
|
||||
version_str=version.get_version_string(),
|
||||
version_str=version.string,
|
||||
date=datetime.datetime.now().strftime("%a, %d %b %Y %H:%M:%S") + " +0300",
|
||||
in_path=os.path.join(repo_path, CHANGELOG_IN_PATH),
|
||||
changelog_path=os.path.join(repo_path, CHANGELOG_PATH)
|
||||
in_path=p.join(repo_path, CHANGELOG_IN_PATH),
|
||||
changelog_path=p.join(repo_path, CHANGELOG_PATH),
|
||||
)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
def _update_contributors(repo_path):
|
||||
cmd = "cd {} && ./StorageSystemContributors.sh".format(os.path.join(repo_path, CONTRIBUTORS_SCRIPT_DIR))
|
||||
|
||||
def update_contributors(
|
||||
relative_contributors_path: str = GENERATED_CONTRIBUTORS, force: bool = False
|
||||
):
|
||||
# Check if we have shallow checkout by comparing number of lines
|
||||
# '--is-shallow-repository' is in git since 2.15, 2017-10-30
|
||||
if git.run("git rev-parse --is-shallow-repository") == "true" and not force:
|
||||
logging.warning("The repository is shallow, refusing to update contributors")
|
||||
return
|
||||
|
||||
contributors = git.run("git shortlog HEAD --summary")
|
||||
contributors = sorted(
|
||||
[c.split(maxsplit=1)[-1].replace('"', r"\"") for c in contributors.split("\n")],
|
||||
)
|
||||
contributors = [f' "{c}",' for c in contributors]
|
||||
|
||||
executer = p.relpath(p.realpath(__file__), git.root)
|
||||
content = CONTRIBUTORS_TEMPLATE.format(
|
||||
executer=executer, contributors="\n".join(contributors)
|
||||
)
|
||||
contributors_path = get_abs_path(relative_contributors_path)
|
||||
with open(contributors_path, "w", encoding="utf-8") as cfd:
|
||||
cfd.write(content)
|
||||
|
||||
|
||||
def _update_dockerfile(repo_path: str, version: ClickHouseVersion):
|
||||
version_str_for_docker = ".".join(
|
||||
[str(version.major), str(version.minor), str(version.patch), "*"]
|
||||
)
|
||||
cmd = "ls -1 {path}/docker/*/Dockerfile | xargs sed -i -r -e 's/ARG version=.+$/ARG version='{ver}'/'".format(
|
||||
path=repo_path, ver=version_str_for_docker
|
||||
)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
def _update_dockerfile(repo_path, version):
|
||||
version_str_for_docker = '.'.join([str(version.major), str(version.minor), str(version.patch), '*'])
|
||||
cmd = "ls -1 {path}/docker/*/Dockerfile | xargs sed -i -r -e 's/ARG version=.+$/ARG version='{ver}'/'".format(path=repo_path, ver=version_str_for_docker)
|
||||
subprocess.check_call(cmd, shell=True)
|
||||
|
||||
def update_version_local(repo_path, sha, version, version_type="testing"):
|
||||
_update_contributors(repo_path)
|
||||
_update_cmake_version(repo_path, version, sha, version_type)
|
||||
def update_version_local(repo_path, version, version_type="testing"):
|
||||
update_contributors()
|
||||
version.with_description(version_type)
|
||||
update_cmake_version(version, version_type)
|
||||
_update_changelog(repo_path, version)
|
||||
_update_dockerfile(repo_path, version)
|
||||
|
||||
|
||||
def main():
|
||||
"""The simplest thing it does - reads versions from cmake and produce the
|
||||
environment variables that may be sourced in bash scripts"""
|
||||
parser = ArgumentParser(
|
||||
formatter_class=ArgumentDefaultsHelpFormatter,
|
||||
description="The script reads versions from cmake and produce ENV variables",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version-path",
|
||||
"-p",
|
||||
default=FILE_WITH_VERSION_PATH,
|
||||
help="relative path to the cmake file with versions",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--version-type",
|
||||
"-t",
|
||||
choices=VersionType.VALID,
|
||||
help="optional parameter to generate DESCRIBE",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--export",
|
||||
"-e",
|
||||
action="store_true",
|
||||
help="if the ENV variables should be exported",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--update",
|
||||
"-u",
|
||||
choices=("major", "minor", "patch"),
|
||||
help="the version part to update, tweak is always calculated from commits",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--update-contributors",
|
||||
"-c",
|
||||
action="store_true",
|
||||
help=f"update {GENERATED_CONTRIBUTORS} file and exit, "
|
||||
"doesn't work on shallow repo",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.update_contributors:
|
||||
update_contributors()
|
||||
return
|
||||
|
||||
version = get_version_from_repo(args.version_path)
|
||||
|
||||
if args.update:
|
||||
version = version.update(args.update)
|
||||
|
||||
if args.version_type:
|
||||
version.with_description(args.version_type)
|
||||
|
||||
if args.update:
|
||||
update_cmake_version(version)
|
||||
|
||||
for k, v in version.as_dict().items():
|
||||
name = f"CLICKHOUSE_VERSION_{k.upper()}"
|
||||
print(f"{name}='{v}'")
|
||||
if args.export:
|
||||
print(f"export {name}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user