1 pontos por GN⁺ 2025-02-09 | 1 comentários | Compartilhar no WhatsApp
  • Nas equipes de operações, ainda restam procedimentos manuais (toil) difíceis de eliminar completamente, como mudanças de infraestrutura ou provisionamento de contas, e conforme a empresa cresce aumentam as etapas e exceções
  • Cada etapa pode parecer automatizável, mas se apenas partes forem transformadas em scripts, cresce o número de ferramentas de propósito único e o usuário ainda precisa seguir documentos de procedimento longos
  • Um script do-nothing não executa automaticamente o trabalho real; em vez disso, encapsula cada etapa do procedimento em uma função e orienta o usuário passo a passo
  • O usuário tem menos chance de perder o ponto em que está ou pular etapas, e depois fica mais fácil para o desenvolvedor trocar o texto de orientação de uma etapa específica por código de automação real
  • Embora não reduza o volume imediato de trabalho manual, ele diminui o custo inicial da automação, permitindo remover o toil de forma gradual ao longo do tempo

Quando procedimentos manuais viram um fardo

  • Toda equipe de operações ainda tem procedimentos manuais que não conseguiu automatizar, e é difícil eliminar completamente o toil
  • Em empresas em crescimento, procedimentos como mudanças de infraestrutura ou provisionamento de contas de usuário tendem a se tornar o centro de grandes cargas de toil
  • Um procedimento de provisionamento de conta de usuário pode passar por várias etapas como estas
    • Gerar o par de chaves SSH do usuário
    • Fazer commit da chave pública no Git e dar push para a master
    • Esperar a conclusão do job de build
    • Confirmar o endereço de email do usuário no diretório de funcionários
    • Entregar a chave privada ao usuário via 1Password
  • Em ambientes reais, o procedimento pode chegar a 20 etapas, ou exigir acompanhar continuamente ramificações e casos especiais durante a execução
  • Esse tipo de trabalho exige muita concentração, mas em vez de resolver problemas interessantes, se parece mais com marcar mais uma caixa na checklist, virando um trabalho arrastado

As lacunas deixadas pela automação parcial

  • Esse trabalho arrastado parece um bom alvo para automação
    • É fácil imaginar maneiras de automatizar cada etapa
    • Computadores podem executar instruções com mais rapidez e precisão do que pessoas
    • Também há menor chance de ocorrer deriva prática (practical drift)
  • O problema é que automatizar esse tipo de tarefa muitas vezes parece algo de tudo ou nada
  • Dá para criar scripts que cuidem só de 2 ou 5 etapas, mas isso não reduz muito o incômodo do procedimento como um todo
  • À medida que aumentam os scripts de propósito único, cada ferramenta passa a ter convenções e comportamentos esperados diferentes, e o usuário ainda precisa seguir documentação com várias etapas

Como funciona o script do-nothing

  • Quase todo trabalho arrastado pode ser convertido em um script do-nothing
  • A ideia central é colocar as instruções da tarefa no código e encapsular cada etapa em uma função
  • O fluxo do script de exemplo é o seguinte
    • CreateSSHKeypairStep exibe o comando ssh-keygen e espera até o usuário pressionar Enter
    • GitCommitStep orienta a copiar a chave pública para o repositório Git e depois executar git commit e git push
    • WaitForBuildStep orienta a aguardar a conclusão no URL do job de build
    • RetrieveUserEmailStep orienta a localizar o endereço de email no diretório e recebê-lo como entrada, salvando-o em context["email"]
    • SendPrivateKeyStep orienta a criar um documento da chave privada no 1Password e compartilhá-lo com o usuário desse email
  • Esse script não executa de fato nenhuma etapa do procedimento; ele apenas orienta o usuário uma etapa por vez e espera a conclusão manual

O caminho até a automação

  • À primeira vista, o script do-nothing pode parecer só uma forma mais difícil de ler documentação, mas na prática ele ajuda a manter o fluxo de trabalho mais seguro
    • Reduz a chance de o usuário perder em que ponto está ou pular etapas
    • Fica mais fácil manter a concentração e levar a tarefa até o fim
    • Como cada etapa fica separada em uma função, o texto de uma etapa específica pode ser substituído por código que execute a ação de verdade
    • Com o tempo, surge uma biblioteca de etapas reutilizáveis, e os trabalhos posteriores de automação ficam mais eficientes
  • O script do-nothing em si não reduz o volume de trabalho manual da equipe
  • Seu efeito está em criar um estado em que começar a automatizar fica mais fácil, permitindo que a equipe elimine o toil gradualmente com o passar do tempo

1 comentários

 
GN⁺ 2025-02-09
Comentários no Hacker News
  • Gosto muito dessa abordagem
    No geral, é outra forma de definir uma interface em torno de um processo. Esse processo pode ser manual ou automatizado, mas a interface pode permanecer a mesma. Então isso é bem poderoso na hora de automatizar etapas
    Basta aplicar exatamente do mesmo jeito que você aplicaria a outros sistemas
    Já fiz isso antes, preenchendo Google Sheets manualmente e depois automatizando com um script, e também fazendo com que, ao criar um ticket no Jira, ele fosse automaticamente coletado e processado. Dá para começar mais rápido, automatizar só as partes mais chatas, e nem é necessário automatizar tudo
    Um efeito colateral de um script que não faz nada é que ele tem mais chance de ser realmente usado do que a documentação, então pode se manter atualizado com mais frequência

    • Na minha opinião nada modesta, codificar gradualmente um processo em scripts desse jeito cria um sistema centrado no processo, e não um sistema que engole o processo
      Sou a favor de ter uma lista de scripts que automatizam tarefas comuns. Mas, no momento em que esses scripts começam a ser chamados por serviços em produção, isso cria uma enorme dívida técnica para a pessoa azarada que vai ter de desembaraçar essa teia de espaguete
      Indo além, como um processo centrado em pessoas acaba codificando o sistema, mudanças favoráveis ao sistema de software — por exemplo, dividir o sistema em componentes — se tornam impossíveis. No fim, o crescimento incremental vira uma forma de empurrar cada vez mais coisas para dentro do processo, e isso se torna um ciclo autorreprodutivo de continuar acrescentando coisas a um monólito de scripts
    • A abordagem antiga era assim: 1) capturar o processo atual como ele é 2) fazer esse processo passar no teste do ridículo 3) torná-lo automatizável
      Enquanto se avança por 3 e 4, faz-se o processo iterar, com o maior número possível de pessoas usando-o, e o processo vai sendo ajustado de acordo com os usos indevidos que aparecem no mundo real
      4) automatizar o processo
      Todo mundo concorda com 1 e 2, e a maioria acaba concordando com 4 também, mas fazer 3 aumenta o número de pessoas que passam a pedir 4 e a entendê-lo
      Só que a limitação dessa abordagem é que ela funciona bem se você puder automatizar o começo ou o fim do processo, mas, se houver dois pontos de automação isolados no meio, ela não é melhor do que uma ferramenta de linha de comando com prompts
    • Exato. Para mim, isso também é mais uma oportunidade de usar e compartilhar Jupyter notebooks
      Basta explicar o que precisa ser feito e fornecer boilerplate, exemplos ou executáveis parametrizados
      Seria legal usar notebooks como um sistema de documentação de fato. Só que eles são pesados demais para serem colocados como camada sobre um SaaS em nuvem como o Confluence e, no estado atual, também há margem demais para problemas como escalonamento de privilégios
    • Já consigo ver a montanha de “Zen and the Art of Motorcycle Maintenance”
      Essa abordagem transforma uma página de instruções do Confluence em um walkthrough meio interativo. Esse é o lado consciente
      O outro lado é a automação de testes. Ela começa com um monte de XPath superajustado e etapas não documentadas. Cada vez que a aplicação muda, você acaba redescobrindo essas etapas. Esse é o lado inconsciente
      Tomara que a gente consiga chegar ao topo e ainda assim executar tudo rapidamente, sem deixar de entender como chegamos lá e por que ficou daquele jeito
    • O que já pode ser feito por comando eu gostaria que o script fizesse diretamente
      Basta confirmar com o usuário algo como Execute command (y/N)?
      Odeio ter de copiar e colar de um terminal para outro. Isso também consome muita concentração
      Só precisa perguntar ao usuário sobre o trabalho manual que ainda não virou comando: Look up the e-mail address for foo. Paste it here: ou Put that shit in 1Password: Are you done (y/N)?
  • Abordagem interessante
    Mas a tarefa usada como exemplo só mostra o quão inseguro era o processo de provisionamento de chaves SSH dessa empresa. Na prática, o usuário deveria gerar a própria chave privada e entregar apenas a chave pública ao administrador do sistema para que ele conceda o acesso. Em nenhum momento o administrador deveria ter uma cópia da chave privada, nem temporariamente. Por isso, a etapa com 1Password nem deveria existir
    Para constar, sou o autor do github-keygen, uma ferramenta que automatiza a geração de chaves SSH dedicadas ao acesso ao GitHub e a configuração de SSH nesse contexto
    https://github.com/dolmen/github-keygen

    • Também não parece muito seguro deixar usuários sem muita experiência gerenciarem as próprias chaves. Esse é justamente o ponto de levar isso para um script
    • A etapa o usuário deveria gerar a própria chave privada e entregar apenas a chave pública ao administrador do sistema sempre foi chata de implementar
      Nós migramos do SSH para autenticação baseada em certificados, e não ficamos mais movendo chaves públicas para todo lado. O processo inteiro realmente ficou muito mais simples
    • Isso é mesmo a linha de base? De todo modo, a TI não controla tudo na máquina de trabalho que contém a chave privada? Eu sei que senhas são diferentes, mas a chave privada continua armazenada na máquina
  • Só fui tentar essa abordagem quase um ano depois de este texto ter sido publicado pela primeira vez
    Por causa de bugs na nossa cadeia de ferramentas, o runbook de hotfix era cerca de duas vezes mais complexo que o processo normal de release
    Não recebeu tanto reconhecimento assim, mas algo que antes era usado só em incidentes sev 1 ou em trabalho de épico na fase final, talvez uma vez a cada 10 semanas, passou a ser usado em média uma vez por semana, e em algumas semanas até 3 vezes. Como nem tudo precisava virar feature toggle, deu para atacar a dívida técnica muito mais a fundo
    Se você estiver numa empresa pequena, onde é fácil copiar dados de produção para um ambiente de pré-produção, talvez não veja esse tipo de resultado. Mas nós nos comunicávamos com mais de 150 endpoints, algo como 3 por serviço em média. Havia muitos conjuntos de dados, e alguns deles eram coletados de um jeito tipo Kafka antes de existir Kafka
    Só havia uma pessoa tentando replicar os dados de produção, e essa pessoa também não tinha tempo nem energia, então isso só acontecia uma ou duas vezes por ano. Esse ritmo era muito mais lento que o ritmo de mudança dos clientes e das funcionalidades. No fim, tivemos que mexer com o processo de deploy blue-green e com o jmeter para descobrir se estávamos chegando perto e como medir sucesso/falha antes de entrar em produção
    No fim das contas, o que travava as pessoas era um processo de build cheio de detalhes e sujeito a erro, e isso só se resolveu depois que eu o automatizei pela metade
    Mais tarde, conforme o uso aumentou, encontrei todas as URLs das etapas manuais, coloquei numa tabela de consulta dentro da ferramenta e também as expus no processo normal de validação para aprovação de release. Isso deixou o coordenador um pouco mais rápido e menos estressado. O processo era tão chato que três equipes se revezavam para dividir a carga

  • Quando se fala em “reduzir a energia de ativação da automação do trabalho”, isso quer dizer que um script que não faz nada acaba depois ganhando etapas que realmente automatizam alguma coisa?
    Vendo como um placeholder para automações futuras, isso parece um bom equilíbrio entre automação e eficiência. Dá para fazer a primeira tentativa sem investir demais e deixar frutos fáceis ao alcance para quando, mais tarde, o esforço passar a ter um valor mais claramente justificável

    • Isso mesmo
      Como cada etapa do procedimento agora está encapsulada em uma função, dá para substituir o texto de uma etapa específica por código que executa automaticamente a ação real
  • class Foo(object): def run(self, context): ...
    Um objeto com um único método de execução já existe embutido no Python. Isso se chama função
    def foo(context): ...

    • Mas como sobreviver sem consumir uma abstração completamente quebrada por dia?
    • A vantagem da abordagem original é que, se depois isso se tornar necessário, você pode simplesmente adicionar mais métodos privados pertencentes só àquela classe
      Na abordagem com funções, se surgir necessidade de novas funções, você vai adicioná-las no nível global. Com uma ou duas isso é totalmente ok, mas quando começam a ser mais, você acaba com um monte de funções no mesmo nível e as dependências entre elas deixam de ficar claras
    • Isso me lembra https://www.youtube.com/watch?v=QM1iUe6IofM do Brain Will. Há uma série praticamente inteira de reclamações sobre esse tipo de tema
      Em um dos vídeos, ele mostra exemplos de simplificação de código abstraído sem necessidade
  • Excelente, mas não dá para interromper
    Seria bom mostrar todas as etapas logo de cara e ir marcando cada item conforme avança. Às vezes é melhor se preparar de verdade com uma visão mais ampla
    Também poderia deixar um log resumido em arquivo
    Há tantas coisas que daria para melhorar que talvez a solução mais simples acabe sendo a melhor

    • Com uma biblioteca de linha de comando melhor, dá para mostrar um checklist e a saída da execução de cada etapa. Isso funciona bem independentemente de quais etapas estejam automatizadas
      Só que um script de shell que não faz nada é tão fácil de começar que fica difícil não ir até o fim. Talvez fosse melhor gastar esse esforço automatizando uma etapa. Você pode acabar caindo em pântanos divertidos, mas pouco produtivos, como decidir qual biblioteca de TUI usar ou como estruturar tudo
    • Fico feliz que alguém tenha mencionado o fato de que “não dá para interromper”. Por isso eu uso Makefile em vez de script Bash
      Cada etapa é uma regra chamada *.done e, quando concluída, gera um arquivo .done. Dá para interromper a qualquer momento, mexer no script para corrigir algo e depois retomar com make
      Mas escrever esse Makefile é realmente doloroso. Será que existe uma solução melhor?
    • Quando faço algo assim, deixo estado persistente para permitir interrupção. Por exemplo, se for uma tarefa anual, eu executo ./do-the-thing.sh 2025, crio um diretório 2025 e guardo ali o estado de até onde cheguei
      Ao aprovar a primeira etapa, você pode fazer touch no arquivo 2025/first-step. Se o script morrer ou for interrompido e depois executado de novo, ele verifica esse arquivo e pula a primeira etapa
      Quando algo muda e a automação deixa de funcionar, é bom poder sair, corrigir o script e executá-lo de novo sem perder o estado
      Em geral, eu faço o script apenas informar a próxima etapa manual e encerrar. Assim o terminal fica livre para outras coisas. E pelo histórico de comandos fica fácil executar o script de novo
    • Isso é de fato uma crítica ao texto? E você foi embora deixando a conclusão no ar. Qual solução seria “a mais simples”?
    • Já usei um script parecido, mas se você colocar por engano um endereço de e-mail errado, vira um “e agora?”. Tem que reiniciar o script inteiro? Ficar preso no script pode ser doloroso
  • Há discussões anteriores também. Muitos comentários
    https://news.ycombinator.com/item?id=29083367 - 3 anos atrás, 230 comentários
    https://news.ycombinator.com/item?id=20495739 - 6 anos atrás, 124 comentários

  • Não dá para exagerar o quanto eu gosto dessa abordagem
    Já a apliquei com sucesso em vários projetos. Meu exemplo favorito é um robô cirúrgico de 30 milhões de dólares que falhava em testes de laboratório por causa de “fatores humanos”

    • Seria ótimo se você pudesse compartilhar pelo menos um exemplo com mais detalhes, ou resumir sua experiência e dicas. Aqui mesmo ou num post de blog, eu gostaria de ler
      Eu estou em outra área, prática jurídica, mas queria pensar em como aplicar essa abordagem na minha empresa
  • Gosto dessa abordagem. Já gosto de fazer algo parecido em sistemas baseados em linguagens de programação com um certo nível de complexidade. No lado da programação funcional, acho que isso é chamado de buracos (holes)
    O erro not implemented em interfaces segue uma lógica parecida, mas vejo bastante valor em escrever algo trivial que produza uma saída válida, embora sem sentido, para cada uma das várias partes que dependem umas das outras. Isso acelera o processo de criar essas partes e aumenta bastante a chance de testá-las e construí-las uma de cada vez. Reduz a necessidade de escrever várias partes de uma vez antes de começar a testar
    Como no caso de uso tratado no texto, no contexto de scripts pode ser difícil essa validade em nível de tipos se tornar importante. Os efeitos da linha de comando, do ponto de vista funcional, provavelmente seriam em grande parte efeitos colaterais. Mas, por acontecerem de forma sequencial, o impacto é bem menor, e graças ao prompt de espera dá para preservar a ordem do trabalho mantendo, a um custo pequeno, etapas manuais que de qualquer forma teriam de ser feitas mesmo sem o script
    É um apoio provisório, incompleto, mas fundamentalmente útil

  • Em teoria parece bom, mas na prática acho que seria difícil
    Se a equipe de operações estiver repetindo a mesma tarefa e vir que um script que não faz nada realmente não faz nada, no momento em que achar que já decorou os passos, ou sentir que fazer manualmente é mais rápido ou mais interessante, vai parar de usar isso rapidamente
    Já escrevi muita automação e documentação para equipes de operações, mas fazer as pessoas usarem isso e continuarem usando sempre foi um problema. Até mudanças na documentação precisavam ser anunciadas. As pessoas param de ler a documentação muito rápido depois que acham que já sabem fazer algo
    Num mundo perfeito, essa abordagem faz bastante sentido, e eu mesmo talvez a usasse para coisas pessoais. Mas a realidade quase nunca é perfeita. Eu só usaria desse jeito se 90% já estivesse automatizado e ainda faltasse 1 etapa sem solução. Mesmo assim, parte da equipe de operações pode acabar pulando essa etapa manual e presumindo que tudo foi automatizado por mágica

    • Em geral, parte disso pode ser automatizada, ou algumas etapas manuais podem ser validadas. Aí, de repente, vira um script que faz alguma coisa