Git e Gestão de Dependências

Basis Tecnologia da Informação S.A. - 2019

GIT

Agenda

  • Fundamentos

  • Comandos básicos

  • Resolução de conflitos

  • Customização

Fundamentos

  • Não centralizado

  • Operações locais

  • Integridade

  • Só adiciona conteúdo

  • Estados: commited, modified, staged

Fundamentos

Sistemas de controle de versão centralizados

scv centralizado

Fundamentos

Sistemas de controle de versão centralizados

scv nao centralizado

Fundamentos

FileStatusLifecycle

Comandos básicos

  • Iniciando os trabalhos

    • local

    • remoto

Comandos básicos

  • Iniciando os trabalhos

    • local

$ git init

Comandos básicos

  • Iniciando os trabalhos

    • remoto

$ git clone [url]

Monitorando arquivos

$ git status
$ git add
$ gitignore
$ gitdiff
$ git commit
$ git commit --amend

Regras de nomenclatura

Basis Foundation

Remotos

$ git remote
$ git fetch
$ git pull
$ git push

Remotos

Basis Foundation

Tagging

$ git tag

Branching

$ git branch
$ git checkout
$ git merge

Fluxo de exemplo

  1. Já existe um código em produção

  2. Criar uma branch para nova funcionalidade

  3. Voltar a branch de produção para corrigir um erro

  4. Fazer o merge da correção na master

  5. Voltar para a branch da nova funcionalidade

  6. Fazer o merge da nova funcionalidade na master

Fluxo de exemplo

  1. Já existe um código em produção

commit1

Fluxo de exemplo

  1. Criar uma branch para nova funcionalidade

commit2

Fluxo de exemplo

2.1. Adicionar commits para a nova funcionalidade

commit3

Fluxo de exemplo

  1. Voltar a branch de produção para corrigir um erro

commit4

Fluxo de exemplo

  1. Fazer o merge da correção na master

commit5

Fluxo de exemplo

  1. Voltar para a branch da nova funcionalidade

commit6

Fluxo de exemplo

  1. Fazer o merge da nova funcionalidade na master

merge

Fluxo de exemplo

  1. Fazer o merge da nova funcionalidade na master

merge2

Customização

  • Criando atalhos

$ git config --global alias.st status
$ git config --global alias.last 'log -1 HEAD'

Gestão de Dependências

Agenda

  • Semantic Versioning

  • NPM

  • Composer

  • Maven

Semantic Versioning

  • Padronização do versionamento

  • Independente de Tecnologia

  • Número de versão composto de 3 partes: MAJOR.MINOR.PATCH

Funcionamento do SemVer

Quando incrementar cada parte do número de versão

  • MAJOR: em caso de mudanças que provocam uma quebra de compatibilidade da API

  • MINOR: quando novas funcionalidades são adicionadas, sem quebrar a retro-compatibilidade

  • PATCH: Na correção de Bugs que não implicam em quebra de compatibilidade da API.

NPM

Visão Geral

NPM é um gerernciador de dependências para projetos javaScript.

Ferramentas para build

  • Grunt

  • Gulp

  • Webpack

Instalação

$ sudo apt install curl
$ curl -sL https://deb.nodesource.com/setup_10.x | sudo bash -
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo bash -
$ sudo apt install nodejs
$ node -v
$ npm -v

Atualização

$ npm install npm@latest -g

O que é o package.json?

Basicamente o arquivo package.json é responsável por listar e gerenciar as dependências do projeto.

Seções do package.json

  • name

  • version

  • description

  • scripts

  • config

  • dependencies

Exemplo

{
  "author": "Jonathan Monteiro",
  "license": "MIT",
  "name": "myProject",
  "version": "1.0.0",
  "description": "Test",
  "main": "index.js",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^7.2.0",
    "@angular/cdk": "^7.2.0",
    "@angular/common": "^7.2.0",
    "@angular/compiler": "^7.2.0",
    "@angular/core": "^7.2.0",
    "@angular/forms": "^7.2.0",
    "@angular/http": "^7.2.0",
    "@angular/platform-browser": "^7.2.0",
    "@angular/platform-browser-dynamic": "^7.2.0",
    "@angular/router": "^7.2.0",
    "@nuvem/angular-base": "^7.2.2",
    "@nuvem/primeng-components": "^7.2.4-beta-3"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^0.6.8",
    "typescript": "3.1.6",
    "@types/jasmine": "2.8.8",
    "@types/node": "8.9.5",
    "jasmine-core": "2.99.1",
    "jasmine-spec-reporter": "4.2.1",
    "karma": "1.7.1",
    "karma-chrome-launcher": "2.2.0",
    "karma-coverage-istanbul-reporter": "2.0.1",
    "karma-jasmine": "1.1.2",
    "karma-jasmine-html-reporter": "0.2.2"
  },
  "engines": {
    "npm": ">=5.0"
  }
}

Instalando Dependências

$ npm install <dependencia>@<versao>
$ npm install -g <dependencia>@<versao>
$ npm install --save
$ npm i --save-dev

A pós a execução dos comandos de instalação as dependências serão gravadas na pasta node_modules

Definição de versões

ConstraintInternally

1.2.3

=1.2.3.0-lasted

>1.2

>1.2.0.0-lasted

>=1.2

>=1.2.0.0-dev

>=1.2-stable

>=1.2.0.0-lasted

<1.3

<1.3.0.0-dev

Definição de versões

ConstraintInternally

⇐1.3

⇐1.3.0.0-lasted

1 - 2

>=1.0.0.0-dev <3.0.0.0-dev

~1.3

>=1.3.0.0-dev <2.0.0.0-dev

1.4.*

>=1.4.0.0-dev <1.5.0.0-dev

^1.4

equivalente a >=1.4 e <2.0

O que é o package-lock.json

A finalidade deste arquivo é garantir que as dependências permaneçam as mesmas em todas as máquinas nas quais o projeto está instalado. Ele é gerado automaticamente para todas as operações em que o npm modifica a pasta node_modules ou o arquivo package.json.

Documentação

Composer

Visão Geral

Antes de falar do composer primeiramente vamos falar um pouco sobre PSR

O que é o PSR?

PSR é um acrônimo para PHP Standart Recomedation, ou seja, é uma recomendação para padrões PHP definidas pelo PHP-FIG. Cada PSR é responsável por resolver um problema em específico

Exemplos

  • PSR-1 Define estílo basico de códificação

  • PSR-2 Define estilo rigoroso de códificação

  • PSR-3 Interface para logger

  • PSR-4 Autoloading

PSR-4

Na referência mencionada a cima podemos ver que o PSR-4 prevê a resolução de autoloading de dependências, ou seja, o carregamento dinâmico de classes, interfaces ou traits.

PSR-4

Em projetos legados PHP é muito comum a inclusão de dependências com as seguintes instruções:

include 'dependecia.php';
include_once 'dependecia.php';
require 'dependecia.php';
require_once 'dependecia.php';

PSR-4

Também podemos encontrar importações mais sofisticadas com a utilização do spl_autoload_register como no exemplo a abaixo:

spl_autoload_register(function ($class_name) {
        $arCaminho = array(
                dirname(__FILE__) . '/'
        );
        foreach ($arCaminho as $caminho) {
                $arquivo = $caminho . str_replace('\\', '/', $class_name) . '.php';
                if (file_exists($arquivo)) {
                        include_once ($arquivo);
                        break;
                }
        }
}, true);

spl_autoload_register

O spl_autoload_register nos permite utilizar namespaces para cada classe, interface ou trait, ou seja, temos somente um ponto de inclusão nos projetos.

Sobre o composer

Esta estratégia é exatamente o que gerenciadores de dependências como o Composer preveem, mas de maneira bem mais sofisticada e eficiente.

O que é o Composer?

  • O Composer é um gerenciador dependências para PHP.

  • Foi lançado por Nils Adermann e Jordi Boggiano 1º de março de 2012.

Instalação

$ sudo apt-get update

$ sudo apt-get install curl

$ sudo curl -s https://getcomposer.org/installer | php

$ sudo mv composer.phar /usr/local/bin/composer

Configuração

O composer.json é o arquivo de configuração do composer nele podemos encontrar uma estrutura semelhante a apresentada abaixo:

{
        "name" : "my_project",
        "license" : "MIT",
        "type" : "project",
        "autoload" : {
                "psr-4" : {
                        "" : "src/"
                }
        },
        "autoload-dev" : {
                "psr-4" : {
                        "Tests\\" : "tests/"
                }
        },
    "require": {
        "cjf/cas-php-client": "1.0"
    },
    "repositories": [{
       "type": "package",
        "package": {
            "name": "cjf/cas-php-client",
            "version": "1.0",
            "source": {
                "url": "https://gogs.basis.com.br/CJF/cas-php-client.git",
                "type": "git",
                "reference": "master"
            }
        }
    }],
    "require-dev" : {
        "symfony/phpunit-bridge" : "^3.0"
    }
    "scripts" : {
        "symfony-scripts" : [
            "Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
            ],
            "post-install-cmd" : "@symfony-scripts",
            "post-update-cmd" : "@symfony-scripts"
    }
}

Instalando Dependências

As dependências do composer podem ser instaladas de duas maneiras

$ composer require <pacote>/<dependencia>

$ composer require league/oauth2-client
$ composer install

Instalando Dependências

A diferença básica entre cada comando apresentado é que o comando composer require instala uma biblioteca específica informada pelo usuário, enquanto o comando composer install instala uma ou mais bibiotecas definidas no arquivo composer.json localizado no root do projeto, após a instalação o arquivo composer.lock será criado.

Definição de versões

ConstraintInternally

1.2.3

=1.2.3.0-stable

>1.2

>1.2.0.0-stable

>=1.2

>=1.2.0.0-dev

>=1.2-stable

>=1.2.0.0-stable

<1.3

<1.3.0.0-dev

Definição de versões

ConstraintInternally

⇐1.3

⇐1.3.0.0-stable

1 - 2

>=1.0.0.0-dev <3.0.0.0-dev

~1.3

>=1.3.0.0-dev <2.0.0.0-dev

1.4.*

>=1.4.0.0-dev <1.5.0.0-dev

^1.4

equivalente a >=1.4 e <2.0

O que é o composer.lock?

Após a execução do composer o aquivo composer.lock será criado e ele conterá a lista de dependências e os números exatos das versões utilizadas pelas dependências, este arquivo será utilizado como referência pelo composer para a realização do download das dependências necessitarias para a aplicação.

Conclusão

Depois do lançamento do composer tornou-se possível ter maior controle das dependências utilizadas pelos projetos, além de uma maior padronização das aplicações e bibliotecas disponibilizadas pela comunidade PHP.

Maven

História

  • Começou no projeto Jakarta Alexandria em 2001

  • Primeira versão lançada em 2004

  • Maven 2.0 saiu em 2005

  • Versão 3.0 publicada em 2010

  • 1 milhão de projetos Maven em 2012, 2 milhões em 2014

  • Em 2017 esse número passou de 10 milhões

  • Atualmente esse número está em 14 milhões

Configuração

As configurações são armazenadas no arquivo settings.xml que se encontra na pasta .m2 do diretório home ou de instalação do Maven:

<settings>
  <mirrors/>
  <servers/>
  <proxies/>
  <profiles/>
  <activeProfiles/>
  <localRepository/>
  <interactiveMode/>
  <offline/>
  <pluginGroups/>
</settings>

Configuração - Mirror

Element

Ciclos de Vida

3 Ciclos de vida distintos:

  • Clean

  • Default

  • Site

Ciclo de Vida Default

  1. validate

  2. generate-sources

  3. process-sources

  4. generate-resources

  5. process-resources

  6. compile

  1. process-test-sources

  2. process-test-resources

  3. test-compile

  4. test

  5. package

  6. install

  7. deploy

POM

Project Object Model armazenado no pom.xml.

Têm pelo menos as seguintes propriedades (Coordenadas):

  • GroupId

  • ArtifactId

  • Version

Representado por: GroupId:ArtifactId:Version

POM - Seções

Principais seções do POM:

  • Package

  • Properties

  • Build/Plugins

  • Dependencies

  • Profiles

  • Modules

POM - Package

O elemento package determina o tipo de pacote do projeto.

Alguns tipos de pacotes válidos são: jar, war, ear e pom

Outros podem ser adicionados com plugins, por exemplo jpi para Plugins Jenkins

POM - Properties

  • properties são variáveis que podem ser utilizadas no pom com a sintaxe: ${propriedade}

  • properties

  • Algumas propriedades padrão do Maven:

    • project.build.sourceEncoding

    • maven.compiler.source

    • maven.compiler.target

Dependências - Transitividade

maven dependencies

Dependências - Escopo

Limitam a transitividade das dependências

compile

Escopo padrão, disponível nos Classpaths do projeto

provided

Parecido com compile, mas não copiado no artefato final

runtime

Disponível no classpath de testes e execução mas não de compilação

Dependências - Escopo 2

test

Não requerida para usa normal da aplicação, somente para testes

system

Parecido com provided mas deve fornecer o Jar

import

Utilizado somente com artefatos de tipo pom

Dependências opcionais

Existe a tag optional declarada na tag dependency:

<optional>true</optional>

Para remover dependências existe a tag exclusions:

<exclusions>
  <exclusion>
    <groupId>sample.ProjectB</groupId>
    <artifactId>Project-B</artifactId>
  </exclusion>
</exclusions>

Comandos úteis - Dependências

Lista de dependências: list e tree

$ mvn dependency:list
$ mvn dependency:tree

Análise de dependências

$ mvn dependency:analyze
$ mvn dependency:analyze-report

Comandos úteis - Dependências

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------< br.com.basis.treinamento:parent >-------------------
[INFO] Building parent 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ parent ---
[INFO] br.com.basis.treinamento:parent:jar:1.0.0
[INFO] +- commons-beanutils:commons-beanutils:jar:1.9.3:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.2:compile
[INFO] |  \- commons-collections:commons-collections:jar:3.2.2:compile
[INFO] \- io.jsonwebtoken:jjwt-impl:jar:0.10.5:compile
[INFO]    \- io.jsonwebtoken:jjwt-api:jar:0.10.5:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.810 s
[INFO] Finished at: 2019-05-06T17:24:20-03:00
[INFO] ------------------------------------------------------------------------

Plugins Maven

  • Estendem o Ciclo de Vida Maven

  • Operações comuns são implementadas com Plugins

  • Tem configurações próprias

  • Tem objetivos (goals)

Plugins - Execução e Configuração

  • Objetivos vinculados a etapas do Ciclo de Vida

  • Configurações globais ou por execução

<executions>
  <execution>
    <id>unpack-dependencies</id>
    <phase>package</phase>
    <goals>
      <goal>unpack-dependencies</goal>
    </goals>
    <configuration>
      <!-- Configurações específicas -->
    </configuration>
  </execution>
</executions>

Comandos úteis

help:describe

$ mvn help:describe \
  -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:3.8.1

$ mvn help:describe -Ddetail -Dgoal=compile \
  -Dplugin=org.apache.maven.plugins:maven-compiler-plugin:3.8.1

Perfis

  • Perfis (profiles) permitem parametrização condicional

  • Deixa as builds portáveis

  • Podem ser definidos:

    • localmente no projeto

    • globalmente por usuário

    • globalmente por instalação de Maven

Perfis - Ativação

Os profiles podem ser ativados por:

  • Explicitamente (paramêtro -P)

  • No settings.xml com a tag activeProfiles

  • Baseado em variáveis de ambiente

  • Sistema Operacional

  • Presença ou ausência de arquivos

Perfis - Escopo

Os seguintes elementos podem ser configurados:

  • repositories

  • pluginRepositories

  • dependencies

  • plugins

  • properties

  • modules

  • reporting

  • dependencyManagement

  • distributionManagement

  • build/defaultGoal

  • build/resources

  • build/testResources

  • build/finalName

Projetos multi-módulos

Os projetos multi-módulos Maven são gerenciados pelo Reactor que:

  • Junta os módulos a construir

  • Ordena os módulos

  • Executa a construção dos módulos na ordem

Projetos multi-módulos

A ordem de construção é resolvida assim:

  • Um módulo dependendo de outro no mesmo projeto

  • Um plugin utilizado como declaração por um outro módulo

  • Um plugin utilizado como dependencia de outro módulo

  • Uma extensão utilizada por um módulo do projeto

  • A ordem de declaração no elemento <modules>

Projetos multi-módulos

pluginManagement e dependencyManagement servem a centralizar informações sobre dependências

Os plugins e dependências declaradas nessas tags servem a definir uma configuração padrão.

Os módulos herdam das propriedades do parent.

Projetos multi-módulos

Elementos herdados do Parent:

  • Dependências

  • Listas de Plugins

  • Execução de Plugins com os ids

  • Configuração de Plugin

  • Resources

  • Developers and contributors

Projetos multi-módulos

Os comandos maven executados na raiz do projeto são executados em todos os módulos

A opção -pl permite construir módulos específicos:

$ mvn clean install -pl modulo-a -am

Comandos úteis

help:effective-pom

Gera o pom.xml final, efetivamente executado, resolvendo propriedades herdadas e mescladas

$ mvn help:effective-pom