Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scripts de build e servidores de CI para Mobile...

Scripts de build e servidores de CI para Mobile e Web

Palestra realizada no 2º DevDay da comunidade de TI de Jaraguá do Sul.

Ione Souza Junior

May 19, 2018
Tweet

More Decks by Ione Souza Junior

Other Decks in Technology

Transcript

  1. Scripts de build e servidores de CI para Mobile e

    Web Você nunca mais vai querer executar qualquer tarefa de forma manual Ione Souza Junior
  2. O que veremos na apresentação? → Um estudo de caso

    sobre como foi realizado a entrega de um app para diversos clientes → Discutir as dificuldades encontradas → Mostrar as soluções adotadas (mobile e web)
  3. Parte 1 - O aplicativo → Era uma vez um

    ERP... → Um app foi desenvolvido integrado ao sistema → App foi publicado, os clientes começaram a usar o app, até que...
  4. Parte 1 - O aplicativo → Alguns clientes se demonstraram

    um pouco vaidosos → Eles queriam um app próprio, publicado com seu nome e sua logo
  5. O que realmente precisava ser feito? → Alterar drawables Android

    → Alterar resources iOS → Alterar AndroidManifest.xml → Alterar Info.plist → Alterar Entitlements.plist
  6. O que realmente precisava ser feito? → Alterar constantes -

    classe C# → Alterar styles - resource dictionary
  7. Padronizações - parte I → Criamos uma pasta para armazenar

    as imagens específicas de cada cliente
  8. Padronizações - parte I Solução └─── Core └─── Droid └───

    iOS └─── Build │ └─── script.sh │ └─── Clientes │ └─── Cliente1 │ │ └─── Droid │ │ │ └─── arquivo1.png │ │ │ └─── arquivo2.png │ │ │ │ │ └─── iOS │ │ └─── arquivo1.png │ │ └─── arquivo2.png │ │ │ └─── Cliente2 │ └─── ...
  9. O que realmente precisava ser feito? → ✅ Alterar drawables

    Android → ✅ Alterar resources iOS → Alterar AndroidManifest.xml → Alterar Info.plist → Alterar Entitlements.plist
  10. Continuação do script - AndroidManifest.xml <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"

    android:versionName="1.4" package="com.ionixjunior.app" android:versionCode="4" > <uses-sdk android:minSdkVersion="15" android:targetSdkVersion="26" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA" /> <application android:label="Ionix App"></application> </manifest>
  11. Continuação do script - AndroidManifest.xml #!/bin/bash SOLUTION_DIR=/diretorio/projeto MANIFEST=$SOLUTION_DIR/Droid/Properties/AndroidManifest.xml VERSION_NAME=1.5 APP_NAME=Ionix

    App Corp PACKAGE=com.ionix.corp sed -i '' 's/versionName="[0-9.]*"/versionName="'$VERSION_NAME'"/' $MANIFEST sed -i '' 's/android:label="[a-zA-Zà-úÀ-Ú0-9 ]*"/android:label="'"$APP_NAME"'"/' $MANIFEST
  12. Continuação do script - AndroidManifest.xml #!/bin/bash SOLUTION_DIR=/diretorio/projeto MANIFEST=$SOLUTION_DIR/Droid/Properties/AndroidManifest.xml VERSION_NAME=1.5 APP_NAME=Ionix

    App Corp PACKAGE=com.ionix.corp sed -i '' 's/versionName="[0-9.]*"/versionName="'$VERSION_NAME'"/' $MANIFEST sed -i '' 's/android:label="[a-zA-Zà-úÀ-Ú0-9 ]*"/android:label="'"$APP_NAME"'"/' $MANIFEST sed -i '' 's/package="[a-zA-Z.]*"/package="'$PACKAGE'"/' $MANIFEST !
  13. O que realmente precisava ser feito? → ✅ Alterar drawables

    Android → ✅ Alterar resources iOS → ✅ Alterar AndroidManifest.xml → Alterar Info.plist → Alterar Entitlements.plist
  14. Continuação do script - Info.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist

    PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version="1.0"> <dict> <key>CFBundleIdentifier</key> <string>com.ionixjunior.app</string> <key>CFBundleName</key> <string>Ionix App</string> <key>CFBundleShortVersionString</key> <string>1.4</string> </dict> </plist>
  15. Continuação do script - Info.plist #!/bin/bash SOLUTION_DIR=/diretorio/projeto INFO_PLIST=$SOLUTION_DIR/iOS/Info.plist VERSION_NAME=1.5 APP_NAME=Ionix

    App Corp PACKAGE=com.ionix.corp plutil -replace CFBundleIdentifier -string $PACKAGE $INFO_PLIST plutil -replace CFBundleName -string $APP_NAME $INFO_PLIST
  16. Continuação do script - Info.plist #!/bin/bash SOLUTION_DIR=/diretorio/projeto INFO_PLIST=$SOLUTION_DIR/iOS/Info.plist VERSION_NAME=1.5 APP_NAME=Ionix

    App Corp PACKAGE=com.ionix.corp plutil -replace CFBundleIdentifier -string $PACKAGE $INFO_PLIST plutil -replace CFBundleName -string $APP_NAME $INFO_PLIST plutil -replace CFBundleShortVersionString -string $VERSION_NAME $INFO_PLIST
  17. O que realmente precisava ser feito? → ✅ Alterar drawables

    Android → ✅ Alterar resources iOS → ✅ Alterar AndroidManifest.xml → ✅ Alterar Info.plist → Alterar Entitlements.plist
  18. Continuação do script - Entitlements.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist

    PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd" > <plist version="1.0"> <dict> <key>aps-environment</key> <string>development</string> </dict> </plist>
  19. O que realmente precisava ser feito? → ✅ Alterar drawables

    Android → ✅ Alterar resources iOS → ✅ Alterar AndroidManifest.xml → ✅ Alterar Info.plist → ✅ Alterar Entitlements.plist Mas ainda não acabou...
  20. O que realmente precisava ser feito? → Alterar constantes -

    classe C# → Alterar styles - resource dictionary
  21. Continuação do script - constantes public static class AppConfig {

    public const string ApiUrl = "https://homol.app.com"; }
  22. O que realmente precisava ser feito? → ✅ Alterar constantes

    - classe C# → Alterar styles - resource dictionary
  23. Continuação do script - styles - resource dictionary <?xml version="1.0"

    encoding="utf-8"?> <Application xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Core.App" > <Application.Resources> <ResourceDictionary> <Color x:Key="PrimaryColor">#3F51B5</Color> <Color x:Key="SecondaryColor">#F90000</Color> </ResourceDictionary> </Application.Resources> </Application>
  24. Continuação do script - styles - resource dictionary #!/bin/bash SOLUTION_DIR=/diretorio/projeto

    APP_XAML=$SOLUTION_DIR/Core/App.xaml PRIMARY_COLOR=Green SECONDARY_COLOR=#0000FF sed -i '' 's/"PrimaryColor">[a-zA-Z0-9#]*</"PrimaryColor">'$PRIMARY_COLOR'</' $APP_XAML sed -i '' 's/"SecondaryColor">[a-zA-Z0-9#]*</"SecondaryColor">'$SECONDARY_COLOR'</' $APP_XAML
  25. O que realmente precisava ser feito? → ✅ Alterar constantes

    - classe C# → ✅ Alterar styles - resource dictionary !
  26. Padronizações - parte II → Criamos um arquivo para armazenar

    as variáveis do build # ./Build/app.ini CLIENTE = Cliente1 API_URL = https://prod.app.com VERSION_NAME = 1.5 APP_NAME = Ionix App Corp PACKAGE = com.ionix.corp
  27. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=
  28. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$()
  29. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI) # Vai mostrar o conteúdo de todo o arquivo...
  30. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = ") # CLIENTE = Cliente1
  31. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk) #
  32. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk '{print $0}') # CLIENTE = Cliente1
  33. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk '{print $1}') # CLIENTE
  34. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk '{print $2}') # =
  35. Padronizações - parte II → No script principal, carregamos estas

    variáveis... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk '{print $3}') # Cliente1
  36. Padronizações - parte II → Outro exemplo... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini

    APP_NAME=$(cat $APP_INI | grep "APP_NAME = " | awk '{print $3}') # Ionix Está faltando coisa aí...
  37. Padronizações - parte II → Vamos revisar... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini

    APP_NAME=$(cat $APP_INI | grep "APP_NAME = " | awk '{print $0}') # APP_NAME = Ionix App Corp
  38. Padronizações - parte II → Vamos revisar... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini

    APP_NAME=$(cat $APP_INI | grep "APP_NAME = " | awk '{print $3 " " $4 " " $5}') # Ionix App Corp
  39. Padronizações - parte II → Como deixar isso dinâmico?? ...

    awk '{print $3 " " $4 " " $5}' # Ionix App Corp
  40. Padronizações - parte II → Como deixar isso dinâmico?? ...

    awk '{ {out=$3} }' # APP_NAME = Ionix App Corp # out = Ionix
  41. Padronizações - parte II → Como deixar isso dinâmico?? ...

    awk '{ {out=$3}; for (i=4; i <= NF; i++) { } }' # APP_NAME = Ionix App Corp # out = Ionix # NF = number of fields = 5
  42. Padronizações - parte II → Como deixar isso dinâmico?? ...

    awk '{ {out=$3}; for (i=4; i <= NF; i++) { out=out" "$i } }' # APP_NAME = Ionix App Corp # out = Ionix # out = Ionix App # out = Ionix App Corp
  43. Padronizações - parte II → Como deixar isso dinâmico?? ...

    awk '{{out=$3; for(i=4; i<=NF; i++) { out=out" "$i }; print out}}' # Ionix App Corp !
  44. Padronizações - parte II → Outro exemplo... #!/bin/bash SOLUTION_DIR=/diretorio/projeto APP_INI=$SOLUTION_DIR/Build/app.ini

    MANIFEST = $SOLUTION_DIR/Droid/Properties/AndroidManifest.xml INFO_PLIST = $SOLUTION_DIR/iOS/Info.plist ENTITLEMENTS_PLIST = $SOLUTION_DIR/iOS/Entitlements.plist APP_CONFIG = $SOLUTION_DIR/Core/AppConfig.cs CLIENTE = $(cat $APP_INI | grep "CLIENTE = " | awk '{print $3}') API_URL = $(cat $APP_INI | grep "API_URL = " | awk '{print $3}') VERSION_NAME = $(cat $APP_INI | grep "VERSION_NAME = " | awk '{print $3}') APP_NAME = $(cat $APP_INI | grep "APP_NAME = " | awk '{{out=$3; for(i=4;i<=NF;i++){out=out" "$i}; print out}}') PACKAGE = $(cat $APP_INI | grep "PACKAGE = " | awk '{print $3}')
  45. Visual Studio App Center → Muito fácil de usar →

    Ideal para quem está iniciando no mundo DevOps → Poucos cliques e os problemas estão resolvidos
  46. Visual Studio App Center → Build → UI Test →

    Distribuir para grupos de testes e lojas → Diagnóstico de erros → Analytics → Push
  47. Como nosso script lê as variáveis do App Center? →

    Customizações precisaram ser feitas...
  48. Padronizações - parte III → O app.ini não deve ser

    versionado → Então podemos verificar se ele existe no script...
  49. Padronizações - parte III #!/bin/bash # Script depois :) SOLUTION_DIR=$1

    APP_INI=$SOLUTION_DIR/Build/app.ini if [ -e "$APP_INI" ] then CLIENTE=$(cat $APP_INI | grep "CLIENTE = " | awk '{print $3}') else # Não precisa fazer nada, as variáveis já foram setadas :) fi
  50. Padronizações - parte III → Ainda falta deixar dinâmico o

    $SOLUTION_DIR... → O App Center também tem suas próprias variáveis de ambiente
  51. Padronizações - parte III #!/bin/bash # Script depois :) if

    [ -n "$1" ] then SOLUTION_DIR=$1 else SOLUTION_DIR=$APPCENTER_SOURCE_DIRECTORY fi
  52. Padronizações - parte III → O App Center não vai

    achar esse script sozinho → É necessário criar o script post-clone / pre- build / post-build
  53. Padronizações - parte III Solução └─── Build └─── Droid │

    └─── appcenter-post-clone.sh │ └─── appcenter-pre-build.sh │ └─── appcenter-post-build.sh └─── iOS └─── appcenter-post-clone.sh └─── appcenter-pre-build.sh └─── appcenter-post-build.sh
  54. Parte 2 - O web server → Backend em PHP

    → Gitlab.com -> CI e CD ❤
  55. O que automatizamos no build do web server? → Ferramentas

    de QA (PHPMD, PHPCS, PHPCPD, PHPUnit) → Documentação da API → Deploy
  56. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml image:

    php:7.1 cache: paths: - vendor/ - node_modules/ stages: - qa - test - doc - deploy #...
  57. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    phpmd: stage: qa only: - develop script: - apt-get update -yqq - apt-get install -yqq git - php composer.phar install --dev --no-plugins --no-scripts - vendor/bin/phpmd module/ text phpmd_ruleset.xml #...
  58. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    phpcpd: stage: qa only: - develop script: - apt-get update -yqq - apt-get install -yqq git - php composer.phar install --dev --no-plugins --no-scripts - vendor/bin/phpcpd --min-tokens=30 /module #...
  59. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    phpcs: stage: qa only: - develop script: - apt-get update -yqq - apt-get install -yqq git - php composer.phar install --dev --no-plugins --no-scripts - vendor/bin/phpcs --standard=phpcs_ruleset.xml module/ #...
  60. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    modulo-application: stage: test only: - develop script: - apt-get update -yqq - apt-get install -yqq libsqlite3-dev git - pecl install xdebug - docker-php-ext-enable xdebug - docker-php-ext-install pdo_sqlite - php composer.phar install --no-plugins --no-scripts - vendor/bin/doctrine-module orm:schema-tool:drop --force - vendor/bin/doctrine-module orm:schema-tool:create - vendor/bin/phpunit -c phpunit.xml.dist --testsuite Application #...
  61. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    modulo-integracao: stage: test only: - develop script: - apt-get update -yqq - apt-get install -yqq libsqlite3-dev git - pecl install xdebug - docker-php-ext-enable xdebug - docker-php-ext-install pdo_sqlite - php composer.phar install --no-plugins --no-scripts - vendor/bin/doctrine-module orm:schema-tool:drop --force - vendor/bin/doctrine-module orm:schema-tool:create - vendor/bin/phpunit -c phpunit.xml.dist --testsuite Integracao #...
  62. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    modulo-mobile: stage: test only: - develop script: - apt-get update -yqq - apt-get install -yqq libsqlite3-dev git - pecl install xdebug - docker-php-ext-enable xdebug - docker-php-ext-install pdo_sqlite - php composer.phar install --no-plugins --no-scripts - vendor/bin/doctrine-module orm:schema-tool:drop --force - vendor/bin/doctrine-module orm:schema-tool:create - vendor/bin/phpunit -c phpunit.xml.dist --testsuite Mobile #...
  63. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    modulo-cli: stage: test only: - develop script: - apt-get update -yqq - apt-get install -yqq libsqlite3-dev git - pecl install xdebug - docker-php-ext-enable xdebug - docker-php-ext-install pdo_sqlite - php composer.phar install --no-plugins --no-scripts - vendor/bin/doctrine-module orm:schema-tool:drop --force - vendor/bin/doctrine-module orm:schema-tool:create - vendor/bin/phpunit -c phpunit.xml.dist --testsuite Cli #...
  64. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    integracao: stage: doc only: - develop - master script: - curl -sL https://deb.nodesource.com/setup_6.x | bash - - apt-get install -y nodejs - npm install - nodejs node_modules/apidoc/bin/apidoc -i module/ -o build/integracao
  65. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    homologacao: stage: deploy artifacts: paths: - build/projeto/ environment: name: homologacao only: - develop script: # Transfere os arquivos para o servidor de homologação # São apenas comandos (ssh, scp, rsync...) :) #...
  66. Configurar isso no Gitlab.com é muito fácil # .gitlab-ci.yml #...

    producao: stage: deploy when: manual artifacts: paths: - build/projeto/ environment: name: producao only: - master script: # Transfere os arquivos para o servidor de produção # São apenas comandos (ssh, scp, rsync...) :) #...
  67. Quer conhecer mais sobre ferramentas de QA? → https://phpqa.io →

    https://speakerdeck.com/ionixjunior => Mantendo seu software sob controle
  68. Na palestra de hoje vimos que... → É possível compilar

    um app de forma dinâmica → É possível fazer integração e deploy contínuo, tanto no mobile quanto no web server → Você vai se encher de repetir as mesmas tarefas → Precisamos fazer a máquina trabalhar mais → Automatização é tudo