Skip to main content

Documentação Dos Recursos

Dentro de uma entidade, vimos que temos um docs que esta faltando uma annotation.

alt text

E logo no overview também podemos observar do View Source envia direto para o repositório, mas View TechDocs está desabilitado.

alt text

É necessário avisar na definição deste component onde está a sua documentação através de uma annotation.

Vamos fazer acontecer e depois explicar. Vamos adicionar a seguinte annotation.

apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: artist-web
description: The place to be, for great artists
labels:
example.com/custom: custom_label_value
annotations:
example.com/service-discovery: artistweb
circleci.com/project-slug: github/example-org/artist-website
backstage.io/techdocs-ref: dir:. # Adicionamos esta anotação
## ...
spec:
## ...

O techdocs irá procurar onde esta a pasta docs. Vamos criá-la na raiz da pasta backstage do projeto e colocar alguma documentação em markdown ali. Vamos definir como documentation.md.

❯ tree  
.
├── README.md
├── backstage
│ ├── api-external.yaml
│ ├── api.yaml
│ ├── component-website.yaml
│ ├── docs
│ │ └── documentation.md
│ ├── group.yaml
│ └── system.yaml
└── openapi
└── swagger.json

alt text

Esta construindo, mas um erro acontecerá. Na verdade ele busca pelo index.md, então renomeando o arquivo documentation.md para index.md conseguiremos o nosso resultado na aba docs.

alt text

Também, podemos navegar sobre as documentações usando o sidebar e vemos que ele gerou a documentação para o component.

alt text

Mas como de fato isso aconteceu?

Techdocs Configuration

A configuração do techdocs fica no arquivo app-config.yaml.

# Reference documentation http://backstage.io/docs/features/techdocs/configuration
# Note: After experimenting with basic setup, use CI/CD to generate docs
# and an external cloud storage when deploying TechDocs for production use-case.
# https://backstage.io/docs/features/techdocs/how-to-guides#how-to-migrate-from-techdocs-basic-to-recommended-deployment-approach
techdocs:
builder: 'local' # Alternatives - 'external'
generator:
runIn: 'docker' # Alternatives - 'local'
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read documentation for using alternatives.

O que é o MkDocs?

Precisamos entender o que é pois o Techdocs usar o MKDocs para gerar a documentação a partir de arquivos markdown.

O MkDocs é uma ferramenta de geração de documentação estática, projetada para criar sites de documentação com base em arquivos Markdown.

Transforma o conteúdo de uma pasta de documentos Markdown em páginas HTML que podem ser facilmente hospedadas em servidores ou serviços de hospedagem de sites estáticos, como GitHub Pages.


Sabendo disso, se o mkdocs precisa processar uma entrada para gerar uma saída precisamos definir como ele fará isso e para onde irão os arquivos gerados.

Não necessariamente precisamos gerar isso localmente, poderíamos ter um runner totalmente externo para fazer esse processamento. Inclusive os arquivos gerados poderiam ser armazenados totalmente externos ao backstage como por exemplo um s3 na aws.

Ao invés de usarmos um docker poderíamos simplesmente utilizar um container como serviço.

Na configuração padrão como vimos acima ele esta usando o docker localmente para processar os arquivos. Essa imagem spotify/techdocs nunca foi diretamente baixada por mim, foi executada durante o processo.

docker images  
REPOSITORY TAG IMAGE ID CREATED SIZE
kindest/node <none> 6f8c6c736970 2 weeks ago 1.04GB
spotify/techdocs v1.2.4 55addc1021da 5 months ago 663MB

Se tivessemos executando o backstage como um container ele precisaria subir um container dentro de outro container se fosse deste modo? Então para manter isso tenha em mente que é necessário que a imagem seja capaz de fazer isso.

O python é necessário para o plugin do techdocs. Se na mesma máquina ou container que estiver rodando o backstage tivermos os pacotes instalados não precisaríamos fazer isso.

  • python3
  • python3-pip
  • python3-venv

E rodar pip3 install mkdocs-techdocs-core.

Se fossemos agregar isso no próprio container do backstage futuramente precisamos disso.

RUN apt-get update && apt-get install -y python3 python3-pip python3-venv

ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"

RUN pip3 install mkdocs-techdocs-core

Usando localmente e mantendo o docker precisamos definir para onde irão os arquivos gerados. Vamos adicionar configurar o diretório e ver o que acontece.

techdocs:
builder: 'local' # Alternatives - 'external'
generator:
runIn: 'docker' # Alternatives - 'local'
publisher:
type: 'local' # Alternatives - 'googleGcs' or 'awsS3'. Read
local:
publishDirectory: '/home/david/labs/backstage-site'

Quando formos na página novamente do componentes, será novamente processado e o container irá colocar os arquivos nesta pasta.

 ~/labs/backstage-site
tree
.
└── default
└── component
└── artist-web
├── 404.html
├── assets
│   ├── images
│   │   └── favicon.png
│   ├── javascripts
│   │   ├── bundle.c8d2eff1.min.js
│   │   ├── bundle.c8d2eff1.min.js.map
│   │   ├── lunr
│   │   │   ├── min
│   │   │   │   ├── lunr.ar.min.js
│   │   │   │   ├── lunr.da.min.js
│   │   │   │   ├── lunr.de.min.js
│   │   │   │   ├── lunr.du.min.js
│   │   │   │   ├── lunr.el.min.js
│   │   │   │   ├── lunr.es.min.js
│   │   │   │   ├── lunr.fi.min.js
│   │   │   │   ├── lunr.fr.min.js
│   │   │   │   ├── lunr.he.min.js
│   │   │   │   ├── lunr.hi.min.js
│   │   │   │   ├── lunr.hu.min.js
│   │   │   │   ├── lunr.hy.min.js
│   │   │   │   ├── lunr.it.min.js
│   │   │   │   ├── lunr.ja.min.js
│   │   │   │   ├── lunr.jp.min.js
│   │   │   │   ├── lunr.kn.min.js
│   │   │   │   ├── lunr.ko.min.js
│   │   │   │   ├── lunr.multi.min.js
│   │   │   │   ├── lunr.nl.min.js
│   │   │   │   ├── lunr.no.min.js
│   │   │   │   ├── lunr.pt.min.js
│   │   │   │   ├── lunr.ro.min.js
│   │   │   │   ├── lunr.ru.min.js
│   │   │   │   ├── lunr.sa.min.js
│   │   │   │   ├── lunr.stemmer.support.min.js
│   │   │   │   ├── lunr.sv.min.js
│   │   │   │   ├── lunr.ta.min.js
│   │   │   │   ├── lunr.te.min.js
│   │   │   │   ├── lunr.th.min.js
│   │   │   │   ├── lunr.tr.min.js
│   │   │   │   ├── lunr.vi.min.js
│   │   │   │   └── lunr.zh.min.js
│   │   │   ├── tinyseg.js
│   │   │   └── wordcut.js
│   │   └── workers
│   │   ├── search.b8dbb3d2.min.js
│   │   └── search.b8dbb3d2.min.js.map
│   └── stylesheets
│   ├── main.7e359304.min.css
│   ├── main.7e359304.min.css.map
│   ├── palette.06af60db.min.css
│   └── palette.06af60db.min.css.map
├── documentation
│   └── index.html
├── index.html
├── search
│   ├── lunr.js
│   ├── main.js
│   ├── search_index.json
│   └── worker.js
├── sitemap.xml
├── sitemap.xml.gz
└── techdocs_metadata.json

13 directories, 53 files

Se colocarmos a annotation em uma api por exemplo desse jeito, estamos pegando a mesma documentação anterior.

apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: petstore-api
description: Petstore API Swagger
annotations:
backstage.io/techdocs-ref: dir:.
###...

É bastante recomendável que a pasta docs esteja junto com o yaml então vamos alterar totalmente a nossa estrutura a partir deste momento.

Eu tentei fazer referencias usando a annotation backstage.io/techdocs-ref: dir:./docs/newdocs e outras tentativas para avisar sobre o path, mas não consegui então vamos alterar. Por isso fiz o comentário sobre erro de estrutura em catalog.

Uma outra proposta é mantemos as pastas com os nomes das coisas e todos os arquivos sejam chamados catalog-info.yaml que o padrão utilizado pelo backstage.

Entendendo esses limites, a abordagem correta para trabalhar visando que podemos ter monorepo (pior caso) é.

  • Não ter a pasta backstage como definimos anteriormente.
  • Ter um catalog-info.yaml na raiz do projeto, pois se ele de fato for um monorepo então será um system provavelmente.
  • Em cada pasta dos diferentes projetos do monorepo teremos o catalog-info.yaml e seu docs.

Para isso devemos mexer na definição dos providers que temos procurando os arquivos.

  providers:
github:
providerId:
organization: davidpuziol
schedule:
frequency: { minutes: 3 }
timeout: { minutes: 3 }
filters:
branch: 'main' # string
repository: '.*' # Regex
#catalogPath: '/backstage/**/*.{yaml,yml}' # Busca recursivamente
catalogPath: '/**/catalog-info.{yaml,yml}'

A maneira acima garante que mesmo que se você tiver a pasta backend irá funcionar, pois não exigirá a pasta, porém vamos fixar o nome catalog-info.yaml. Dentro deste mesmo arquivo, caso seja necessário, podemos definir mais de um objeto dentro dele.

Ficamos assim por enquanto.

❯ tree
.
├── README.md
├── backstage
│ ├── api
│ │ ├── catalog-info.yaml
│ │ └── docs
│ │ └── index.md
│ ├── api-external
│ │ ├── catalog-info.yaml
│ │ └── docs
│ │ └── index.md
│ ├── docs
│ │ └── index.md
│ ├── group
│ │ └── catalog-info.yaml
│ ├── system
│ │ └── catalog-info.yaml
│ └── website
│ ├── catalog-info.yaml
│ └── docs
│ └── index.md
└── openapi
└── swagger.json

E tudo funcionará de acordo. Lembrando que cada um dos catalogs-info.yaml possuem definições completamente diferentes.

Se conseguiu tudo até aqui, é necessário fazer essas mudanças também no backstage-base que define alguns grupos iniciais que usaremos no futuro. Esse repositório funcionará como a estrutura da empresa fake que estamos montado. Criamos domain, grupos, subgrupos, user para simular uma empresa.