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:
Comando | Utilização |
---|---|
yarn build | Utilize lerna para executar o script build em cada pacote |
yarn clean | Redefine o estado do projeto removendo todos os node_modules e executando o script clean em cada pacote |
yarn format | Formata os arquivos usando o Prettier e verifica se os arquivos foram formatados |
yarn test | Executa teste nos arquivos em cada pacote do projeto |
yarn lint | Executa 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
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.
Rodapé
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
// 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 }) {
// ...
}
// 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
- Localizado em
@resultadosdigitais/tangram-react-icons
- Localizado em
packages/react-icons
- Armazena todos os ícones SVG e os constrói como React Icons
- Localizado em
@resultadosdigitais/tangram-design-tokens
- Localizado em
packages/design-tokens
- Armazena todos os tokens de design
- Localizado em
@resultadosdigitais/tangram-react-datepicker
- Localizado em
packages/react-datepicker
- Armazena todos os componentes do DatePicker
- Localizado em
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
É 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 componentesButton.js
: Código do componente com o estilo dentro (styled-components)constant.js
: Responsável por armazenar as constantes relacionadas ao componenteindex.js
: Ponto de entrada para exportar o componenteconfig.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
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 aorigin/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 labelversion:release
e rode o CI novamente. - Crie um novo pull request com a label
version:release
, espere o CI rodar para publicar acanary
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?
É 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
- Exemplo:
Como faço para adicionar um novo ícone à biblioteca do react-icons?
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 executaryarn build
dentro dereact-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.