Pular para o conteúdo principal

Manual do desenvolvedor

O branch de desenvolvimento é next. É nela que as solicitações de pull requests devem ser feitas e, depois de aprovado, será liberado automaticamente no ambiente de teste (staging).

Depois de revisado, testado e aprovado, o pull requests deve ser comparado e mesclado com o branch main, que será liberado no ambiente de produção.

As branchs fixas existentes:

  • next é a branch de desenvolvimento (padrão)
  • main é a branch de produção e versão final

O Tangram é construído usando uma coleção de pacotes, todos feitos no mesmo repositório Git, chamado monorepo.

Usamos duas ferramentas para nos ajudar a gerenciar as dependências de instalação e publicar os pacotes:

  • Yarn workspaces para lidar com dependências em todos os pacotes
  • Lerna para publicar pacotes, marcar versões, entre outros

Antes de instalar as dependências, é necessário configurar o .npmrc na máquina ou projeto, incluindo credenciais jFrog. Para mais informações acesse nossa wiki.

Para instalar todas as dependências neste projeto, é necessário instalar o Yarn e executar o seguinte comando no terminal:

yarn install

Assim será instalada todas as dependências de cada pacote do projeto. Além disso, é possível conectar os pacotes que estamos desenvolvendo.

yarn setup

Assim serão vinculados os pacotes e dependências. Além disso, construirá cada pacote.

Para criar todos os arquivos do pacote, execute o seguinte comando:

yarn build

Agora você deve estar com tudo pronto para começar a contribuir com o Tangram!

Documentação

Playground

Utilizamos o Ladle como ferramenta de playground. Para iniciá-lo você pode executar o seguinte comando:

yarn playground start

Docusaurus

Para iniciar o Docusaurus com documentação pública, você pode executar o seguinte comando:

// documentação em inglês
yarn docs start
// documentação em português
yarn docs start:br

Tarefas comuns

Algumas das tarefas que você pode precisar executar:

Tarefas comuns
ComandoUtilização
yarn buildUtilize lerna para executar o script build em cada pacote
yarn cleanRedefine o estado do projeto removendo todos os node_modules e executando o script clean em cada pacote
yarn formatFormata os arquivos usando o Prettier e verifica se os arquivos foram formatados
yarn testExecuta teste nos arquivos em cada pacote do projeto
yarn lintExecuta o eslint nos arquivos no projeto
lerna add <dependency-name> --scope=<package-name>Para adicionar alguma dependência de em um pacote específico (workspace). Use -D para adicionar no modo dev

Convenções para os commits

Este projeto segue um formato estruturado para escrever mensagens de commit. O principal benefício é que podemos usar esses detalhes para gerar automaticamente coisas como logs de mudanças, por exemplo, além de esclarecer a quais mudanças correspondem quando olhamos nosso histórico Git.

Nos baseamos no padrão criado pela equipe AngularJS.

Formato das mensagens

Dica

Partes desta seção foram duplicadas das convenções de commit do AngularJs.

Cada mensagem de commit consiste em um cabeçalho, um corpo e um rodapé. O cabeçalho tem um formato específico que inclui um tipo, um escopo e um assunto:

<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>

O cabeçalho é obrigatório e o escopo do cabeçalho é opcional. Existem algumas regras de validação que também aplicamos:

  • O cabeçalho deve sempre ter menos de 72 caracteres
  • Qualquer linha no corpo do commit deve ter menos de 100 caracteres

Muitas dessas regras são para ajudar na integração do git com ferramentas comuns. Verificamos este formato de commit usando uma ferramenta chamada commitlint.

Tipo

Deve ser um dos seguintes:

  • feat: Um novo recurso
  • fix: Uma correção de bug
  • docs: Alterações apenas na documentação
  • test: Adicionar testes ausentes ou corrigir testes existentes
  • refactor: Uma alteração de código que não corrige um bug nem adiciona um recurso
  • perf: Uma alteração de código que melhora o desempenho
  • revert: Uma mudança de código que reverte um commit anterior
  • chore: Mudanças no processo de construção, ferramentas, dependências (package.json por exemplo)

Assunto

O assunto contém uma descrição sucinta da mudança:

  • use o tempo presente imperativo: "altera" e não "alterado" nem "alterações"
  • não coloque a primeira letra em maiúscula
  • sem ponto (.) no final

Corpo

Assim como no assunto, use o imperativo, presente: "altera" e não "alterado" nem "alterações". O corpo deve incluir a motivação para a mudança e contrastar isso com o comportamento anterior.

O rodapé deve conter todas as informações sobre alterações significativas. Quando for necessário utilizar o Breaking Changes ele deve começar com a palavra BREAKING CHANGE: com um espaço ou duas novas linhas.

Exemplos

Feature (feat)
// Adicionar uma nova funcionalidade a um trecho de código é considerado um recurso.
// Isso pode ser visto como uma extensão de uma API existente.
- function MyComponent({ propA }) {
+ function MyComponent({ propA, propB }) {
// ...
}
Bug fix (fix)
// Atualizar uma implementação para corrigir uma falha no código existente
// é considerado uma correção de bug
function add(a, b) {
- return a - b;
+ return a + b;
}

Pacotes

Estes são os pacotes do projeto:

  • @resultadosdigitais/tangram-components;

    • Localizado em packages/components
    • Responsável pelos componentes em ReactJS
  • @resultadosdigitais/tangram-react-icons

    • Localizado em packages/react-icons
    • Armazena todos os ícones SVG e os constrói como React Icons
  • @resultadosdigitais/tangram-design-tokens

    • Localizado em packages/design-tokens
    • Armazena todos os tokens de design
  • @resultadosdigitais/tangram-react-datepicker

    • Localizado em packages/react-datepicker
    • Armazena todos os componentes do DatePicker

Estilo de codificação

Componentes em ReactJS

É importante manter um padrão de escrita de nossos componentes, principalmente devido à quantidade de componentes que teremos, para manter um padrão que nos permita ler e modificar com mais facilidade.

Exportando componentes

Os componentes desenvolvidos precisam ser exportados tanto no ponto de entrada principal quanto na pasta de entrada de cada componente.

1. Ponto de entrada principal

Exporte o componente no ponto de entrada principal localizado em packages/components/src/index.js:

export { default as Component } from './Component';
export * from './Component';

Com isso é possível acessar o componente dentro do pacote.

import { Component } from '@resultadosdigitais/tangram-components';
2. Pasta de entrada

Exporte a pasta do componente para disponibilizar a inclusão apenas o que for necessário packages/components/src/Component/index.js:

export { default } from './Component';
export { default as SubComponent } from './SubComponent';

Com isso é possível acessar a pasta do componente e evitar incluir todos os componentes no bundle.

import Component

Exportando enumeradores

Atenção!

É que seja importante mapear os enums nos componentes que precisam deles, em vez de fazer referência a um valor padrão para todos os componentes, pois isso nos ajuda a evitar problemas com a alteração desses valores. Portanto, mesmo que outros componentes compartilhem os mesmos valores, é válido mapear esses valores em seu componente.

Exporamos enumeradores como um utilitário para nos ajudar na implementação para evitar que forneçamos um valor inexistente. Observe que os enumeradores são escritos no plural quando o exportamos, e o prop é escrito no singular.

const Button = ({ kind }) => {
// ... component code
};

// No plural
Button.kinds = {
default: KINDS.DEFAULT,
primary: KINDS.PRIMARY,
success: KINDS.SUCCESS
};

Button.propTypes = {
// No singular
kind: PropTypes.oneOf([
Button.kinds.default,
Button.kinds.primary,
Button.kinds.success
])
};

Exemplo dos enumeradores na implementação com a nova definição.

<Button kind={Button.kinds.primary}>Action</Button>

Arquivos e pastas

@resultadosdigitais/tangram-components

Ficam na pasta packages/components/ e tambem temos um ponto de entrada localizado em /src/index.js que exporta todos os componentes:

export { default as Button } from './Button';
  • Todos os componentes pertencem a /src em sua própria pasta
  • Nomeie arquivos e pastas usando a forma singular, não no plural
  • Há excessões que é preciso lidar com componentes cujo nome faz sentido no plural, por exemplo: Tabs
...
Button
- Button.test.js
- Button.js
- constant.js
- index.js
- ...
  • Button.test.js: Arquivo com testes de componentes
  • Button.js: Código do componente com o estilo dentro (styled-components)
  • constant.js: Responsável por armazenar as constantes relacionadas ao componente
  • index.js: Ponto de entrada para exportar o componente
  • config.js: Responsável por armazenar configurações e funções auxiliares

A pasta helper, localizada em /src/helper, é responsável por armazenar todas as configurações comuns, funções, hooks, etc.

@resultadosdigitais/tangram-react-icons

Atenção

Ao adicionar um novo ícone remova todos os valores fill fill="#000" dentro de cada SVG. Esse valor é adicionado automaticamente por scripts de ícones em React.

Todos os ícones pertencem a packages/react-icons/svg em sua própria pasta. Nomeie os arquivos usando a forma singular, não no plural.

- align-center.svg
- align-justify.svg
- ...

Todas as configurações relacionadas à construção estão em packages/react-icons nos seguintes arquivos:

- svgr.config.js
- babel.config.js
- rollup.config.js

@resultadosdigitais/tangram-design-tokens

Todos os tokens pertencem a packages/design-tokens/src nos seguintes arquivos:

- base.json
- theme.json
- index.js

Todas as configurações relacionadas à construção estão em packages/design-tokens/tasks.

Pull request

Labels

Pull requests devem ter uma label seguindo o fluxo do FrontHub Lib Flow para indicar o tipo de mudança. Você pode adicionar mais de uma, se necessário.

Caso queira publicar a mudança, certifique-se que o pull request tenha a label version:release.

Certifique-se de que todas as alterações breaking change estão corretamente marcadas com version:major.

Issues

Se o seu pull request está resolvendo algum problema, você deve vincular a issue à sua solicitação de pull request.

Deploy

Staging

Para publicar as alterações, é necessário abrir um pull request para a branch next, dessa forma o Circle CI iniciará a publicação para AWS, e quando o processo for finalizado o resultado será exibido em Tangram staging.

Caso seja necessário publicar uma nova versão, ao adicionar a label version:release, será publicada uma versão canary durante os commits no PR. Se ainda for necessário publicar uma pre-release basta deixar a label version:release no PR quando ele for mergeado. Caso contrário, basta remover a label antes de mergear.

Production

O deploy de produção é executado sempre que uma branch é mergeada na branch main. O Circle CI iniciará a implantação para AWS e quando o processo for finalizado o resultado será exibido em Tangram.

Caso seja necessário publicar uma nova versão, só é necessário adicionar uma das labels de versão e a label version:release no pull request.

Publicações e lançamentos

Versões finais

Publicação de uma nova versão

  • Crie um pull request da branch origin/next para a origin/main
  • Adicione a label version:release
  • Aguarde a aprovação dos reviewers
  • Mergeie o pull request

Próximas versões

Certifique-se de testar a versão lançada! Se você quiser ser extremamente cuidadoso, pode publicar uma versão canary ou realizar um pré-lançamento ao mergear o pull request da sua feature na branch next.

Um pull request aberto na branch next e com a label version:release, vai publicar uma versão canary e o mesmo quando for mergeado vai publicar uma versão de pré-lançamento.

Não se esqueça de remover a label version:release caso só queira gerar a canary e não publicar uma versão no merge.

Caso tenha esquecido de adicionar a label, temos duas opções:

  • Vá até o último pull request com base na next, adicione a label version:release e rode o CI novamente.
  • Crie um novo pull request com a label version:release, espere o CI rodar para publicar a canary e feche o pull request.

O GitHub, como outros serviços, não permite que você crie um pull request sem pelo menos um commit em mais de uma branch base. Para resolver isso é necessário criar um commit extra:

git checkout -b empty-release --track origin/main
git commit --allow-empty -m "Release review"
git push origin empty-release

FAQ

Como faço para instalar uma dependência?

Dica

É importante manter as dependências comuns na raiz e deixar o Lerna gerenciá-las. Ele fornece maior desempenho de instalação.

  • Para instalar uma dependência comum para todos os pacotes, você pode executar yarn add -W <dependency-name>
  • Para instalar uma dependência para apenas um pacote, você pode executar lerna add <dependency-name> --scope=<package-name>
    • Exemplo: lerna add -D lodash --scope=@resultadosdigitais/tangram-components

Como faço para adicionar um novo ícone à biblioteca do react-icons?

Dica

O ícone precisa estar no formato svg e, se tiver mais de uma palavra no nome, é necessário separá-las com hífen.

  • Após adicionar o novo ícone ao diretório react-icons/svg, você pode executar yarn build dentro de react-icons para gerar o componente
  • Ao abrir o pull request, selecione a label version:release, para gerar uma canary, possibilitando testar o código em staging para verificar se o novo ícone foi corretamente adicionado à documentação.

Feedback