From 144197daaf3077c64035bbba49136a9f48857f57 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Tue, 28 May 2019 13:29:09 -0400 Subject: [PATCH] play store publisher --- appveyor.yml | 29 +++++ bitwarden-mobile.sln | 42 ++++++++ store/google/Publisher/Program.cs | 118 +++++++++++++++++++++ store/google/Publisher/Publisher.csproj | 13 +++ store/google/Publisher/play_creds.json.enc | Bin 0 -> 2384 bytes 5 files changed, 202 insertions(+) create mode 100644 appveyor.yml create mode 100644 store/google/Publisher/Program.cs create mode 100644 store/google/Publisher/Publisher.csproj create mode 100644 store/google/Publisher/play_creds.json.enc diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..0841a3c86 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,29 @@ +#init: +# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +#on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +#install: +# - choco install cloc --no-progress +# - "cloc --vcs git --exclude-dir Resources,store,test,UWP,Properties --include-lang C#,JavaScript,TypeScript,PowerShell" +# - appveyor DownloadFile https://dist.nuget.org/win-x86-commandline/latest/nuget.exe +# - appveyor DownloadFile https://aka.ms/vs/15/release/vs_community.exe +# - vs_community.exe update --wait --quiet --norestart --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community" +# - ps: .\src\Android\update-android.ps1 +before_build: + - nuget restore + - IF DEFINED keystore_dec_secret nuget install secure-file -ExcludeVersion + - IF DEFINED google_services_dec_secret secure-file\tools\secure-file -decrypt src\Android\google-services.json.enc -secret %google_services_dec_secret% +after_build: + - ps: IF($env:keystore_dec_secret) { .\src\Android\ci-build-apks.ps1 } +on_success: + - IF DEFINED play_dec_secret secure-file\tools\secure-file -decrypt store\google\Publisher\play_creds.json.enc -secret %play_dec_secret% + - IF DEFINED play_dec_secret dotnet store\google\Publisher\bin\Release\netcoreapp2.0\Publisher.dll %APPVEYOR_BUILD_FOLDER%\store\google\Publisher\play_creds.json %APPVEYOR_BUILD_FOLDER%\com.x8bit.bitwarden-%APPVEYOR_BUILD_NUMBER%.apk alpha +artifacts: + - path: com.x8bit.bitwarden-%APPVEYOR_BUILD_NUMBER%.apk + - path: com.x8bit.bitwarden-fdroid-%APPVEYOR_BUILD_NUMBER%.apk +branches: + except: + - l10n_master +skip_tags: true +configuration: Release +image: Visual Studio 2017 diff --git a/bitwarden-mobile.sln b/bitwarden-mobile.sln index 5691f2367..f64a1115b 100644 --- a/bitwarden-mobile.sln +++ b/bitwarden-mobile.sln @@ -17,8 +17,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D10CA4A9-F86 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{8904C536-C67D-420F-9971-51B26574C3AA}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "store", "store", "{92470CBD-9047-4C3C-8EA3-D972D6622D84}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "google", "google", "{2E399654-26A2-46F6-B9CA-1B496A3F370A}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "iOS.Core", "src\iOS.Core\iOS.Core.csproj", "{E71F3053-056C-4381-9638-048ED73BDFF6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{76690DFB-B7F4-4781-83E4-113FDC450AFE}" + ProjectSection(SolutionItems) = preProject + .gitignore = .gitignore + appveyor.yml = appveyor.yml + CONTRIBUTING.md = CONTRIBUTING.md + crowdin.yml = crowdin.yml + README.md = README.md + SECURITY.md = SECURITY.md + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Publisher", "store\google\Publisher\Publisher.csproj", "{256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Ad-Hoc|Any CPU = Ad-Hoc|Any CPU @@ -215,6 +231,30 @@ Global {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhone.Build.0 = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {E71F3053-056C-4381-9638-048ED73BDFF6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhone.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhone.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|Any CPU.Build.0 = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhone.ActiveCfg = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhone.Build.0 = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -225,7 +265,9 @@ Global {EE44C6A1-2A85-45FE-8D9B-BF1D5F88809C} = {D10CA4A9-F866-40E1-B658-F69051236C71} {4B8A8C41-9820-4341-974C-41E65B7F4366} = {D10CA4A9-F866-40E1-B658-F69051236C71} {9C8DA5A8-904D-466F-B9B0-1A4AB5A9AFC3} = {8904C536-C67D-420F-9971-51B26574C3AA} + {2E399654-26A2-46F6-B9CA-1B496A3F370A} = {92470CBD-9047-4C3C-8EA3-D972D6622D84} {E71F3053-056C-4381-9638-048ED73BDFF6} = {D10CA4A9-F866-40E1-B658-F69051236C71} + {256F9E44-0AF5-4D97-A2F9-DA26080C0A5D} = {2E399654-26A2-46F6-B9CA-1B496A3F370A} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7D436EA3-8B7E-45D2-8D14-0730BD2E0410} diff --git a/store/google/Publisher/Program.cs b/store/google/Publisher/Program.cs new file mode 100644 index 000000000..98d59b5a5 --- /dev/null +++ b/store/google/Publisher/Program.cs @@ -0,0 +1,118 @@ +using Google.Apis.AndroidPublisher.v2; +using Google.Apis.AndroidPublisher.v2.Data; +using Google.Apis.Auth.OAuth2; +using Google.Apis.Services; +using System; +using System.Collections.Generic; +using System.IO; +using System.Threading.Tasks; + +namespace Bit.Publisher +{ + public class Program + { + private const string Package = "com.x8bit.bitwarden"; + + private static string _apkFilePath; + private static string _credsFilePath; + private static string _track; + + static void Main(string[] args) + { + if(args.Length < 3) + { + throw new ArgumentException("Not enough arguments."); + } + + try + { + _credsFilePath = args[0]; + _apkFilePath = args[1]; + + var track = args[2].Substring(0, 1).ToLower(); + if(track == "a") + { + _track = "alpha"; + } + else if(track == "b") + { + _track = "beta"; + } + else if(track == "p") + { + _track = "production"; + } + else if(track == "r") + { + _track = "rollout"; + } + else if(track == "i") + { + _track = "internal"; + } + + new Program().Run().Wait(); + } + catch(AggregateException ex) + { + foreach(var e in ex.InnerExceptions) + { + Console.WriteLine("ERROR: " + e.Message); + } + + throw; + } + } + + private async Task Run() + { + GoogleCredential creds; + using(var stream = new FileStream(_credsFilePath, FileMode.Open)) + { + creds = GoogleCredential.FromStream(stream).CreateScoped( + AndroidPublisherService.Scope.Androidpublisher); + } + + var service = new AndroidPublisherService(new BaseClientService.Initializer + { + HttpClientInitializer = creds + }); + + var editRequest = service.Edits.Insert(null, Package); + var edit = await editRequest.ExecuteAsync(); + + Console.WriteLine("Created edit with id {0}.", edit.Id); + + Apk apk = null; + using(var stream = new FileStream(_apkFilePath, FileMode.Open)) + { + var uploadMedia = service.Edits.Apks.Upload(Package, edit.Id, stream, + "application/vnd.android.package-archive"); + + var progress = await uploadMedia.UploadAsync(); + if(progress.Status == Google.Apis.Upload.UploadStatus.Completed) + { + apk = uploadMedia.ResponseBody; + } + else + { + throw new Exception("Upload failed."); + } + } + + Console.WriteLine("Version code {0} has been uploaded.", apk.VersionCode); + + var trackRequest = service.Edits.Tracks.Update(new Track + { + VersionCodes = new List { apk.VersionCode } + }, Package, edit.Id, _track); + + var updatedTrack = await trackRequest.ExecuteAsync(); + Console.WriteLine("Track {0} has been updated.", updatedTrack.TrackValue); + + var commitRequest = service.Edits.Commit(Package, edit.Id); + var commitEdit = await commitRequest.ExecuteAsync(); + Console.WriteLine("App edit with id {0} has been comitted.", commitEdit.Id); + } + } +} diff --git a/store/google/Publisher/Publisher.csproj b/store/google/Publisher/Publisher.csproj new file mode 100644 index 000000000..a785e539f --- /dev/null +++ b/store/google/Publisher/Publisher.csproj @@ -0,0 +1,13 @@ + + + + Exe + netcoreapp2.0 + Bit.Publisher + + + + + + + diff --git a/store/google/Publisher/play_creds.json.enc b/store/google/Publisher/play_creds.json.enc new file mode 100644 index 0000000000000000000000000000000000000000..bb0a750e951eece0c2029756cd8213664e0efbd9 GIT binary patch literal 2384 zcmV-W39t6`*8ZzEU9d8TI{uiwp>M?ra&2>^$>8NiZAoP4H>f+~bf#G>&$qq~oB7zd z1GI}~+N&b90>HLef+lw!Nji~u0At-SvW-B!dm@XHXIJ`IJl9sGrva#;P-(aVc$B9> z@xYTwm@|-?$^Q1xc#zjP{4r5J()R9?VDAqH+^W%odElArODyao$)E!RziqXc;uFp* z_&x;HSTmQt&+N?^K_Oc%6DP<5ph)#jc`mju0HEQ!j7L<^j7Ys6VwTKTF3K(XtL%Sb z&Y4qCvj&*$2es?`tDfz>dzn0(qwNjf76KdMCfBavQ?vimB)UW5Spf6cE!vDziGB+j zR=M>#Vl`|?2h8~^9zT7JM`#_mYOrbyBY;-V(MlQj+b@{akV|*VtHn&5=T9>9a`-Ey z(Ryu}Yo(HUo!+I*nHX}%VMnbu`FiE!82Cj#+up5rczN`7X{jUL_3fk2S}=gaFXzP6 z2jwtuvn=F%ERSA;Vm+He#r@EQiJ5QG@51#pJs?iiA6*-gkXCdlv%;KNU8V^BvaxZ^ z02Eh2zPg-_d3IlT+?S-@*Dk$@0+_6*Gysc9dR9%$1>ku@n$esUl4}VYzh?a6n82`h z2ea!QNVY03h}K5}NP z)~U1xv&{7fP>5tW6gASKaGgyUueA)&*W#^UYowX3fs)O`iu3tvs9xwA#G+ag6lL%b zx~Pl@Tojt%c`R2cCVcts5au{TSFN4E&HkgbMofZ??s#`)(XeQs>W`y3SPKW^T2hIe zh50Ruo4ieA@~SFy6;(>zc^S{(z@X*jJ19JU0_85%rLZ%Z!q8J@AqITqOKA%yWnu+? z&4-&RPxfAWWOAT~zNZXpQ=LRb#0;I6O0K5He6)=Jf%>5=b@V|FHTFWFcLzSgkx0XD zTHI*z>oMoNPdkckc3UUKR+fs}D>*wg4ohq%eOH{My4=n@@pCt5np>EEMS18ta0h*B zV_$Cb7#P>11zV@T)B!HSTy&%_u3U(wi^?=O#_`l*WQEF6mQC;SeX~(Yd091H9}}lQ ze~XS{`a=Fz$``3vd(MEwDt^)8jo9&=>uw=aKfh670cgQZrK`MJt9Qa{ig^#%E@;{F2OZd_32Gv9B*afeyr{IpZTKkI zAU~Q2#^LkD^Vb_FX0T@9m)4oYNYIf8TGHgM;$+ys+OhjW>q>qAk~qYM0CP!^j20-| z5VbPGNi$2DA6pBUgD z=9T!lP`vyJJ^s!cVo3#!hxaG)GMOxVzGg#x#PGq(5(;fyx&YqLJd=Ei$q63S+UaUk zV`yi;b7DHfT&`(O3B$0nGZ>N$;ZJ_Kb1_Wn?4uSRMScYH;kAhN0A(jRAI8-O=Fiv) zq~^Z2ZVTMlf@tl`wpF*)8xGPFS^K@k!Tj_#kVeFaeGQPB_Pst_}US*oK z?i2O_@Z>K~!eqg90G7a^Up;K>C)PJ@-^nEV2JF2E%B#9-F&FzzLo)MYDI2AowEnn;jnJ#Ju z7#Z6x!}0nNb>i0@wc)-swvp>U^Ns9@99zYj9+!xaTy&*o{wsy)U-nD&4E8Wo0` zwBo`~$bDF51B;Ji8u=b?r=V6z*_*;D$^K&6mPNiaqu3LhSSoh_ir*2@_l;q#z6~Gm zmrx9pwqVlZnd{_y{$8?q<3YXpK?N0MUf!5K~Hp>Y(FhyF*i&pqWv2By8cOz$rL+?20f?*&c&MPEHvu%bWDX)N=o zxWn>lhYk;)i)G{AbgI;X>(s`~njRFc9rbREX=J=0*5WCylfK7}_Ti@x52`}e)Ir9= zMMGw_s&7pA<+4wLJAofIGh`rF7Rcr9(Z6BvRW+Q%nI5JyTjN=XnzkaQXC&2@SfGdPn?L}fu&AiIrlei-E$xr zAc$Nlrlx$kZSg~Ec#jHLV_ez}8aL=Rn(e@)P@+2#A6}v(?JZbvEES90?qD~dIt6D8 zNnMDP!&Rn{Yd0A6twhJ8p?fq&$%S{=Ut~GdmHnXzV6&1dsQl*Amx_E;^b4i`hd*3# CLb?|K literal 0 HcmV?d00001