Sintoma: no GitHub Actions, um teste recebe o código ou o link de outra execução, e o resultado muda conforme a ordem das tarefas.
Ação recomendada nesta semana: dê a cada unidade concorrente um destino de recebimento identificável, associe a mensagem à execução e só então espere e valide o conteúdo. Não transforme todo o fluxo em uma fila: concurrency controla tarefas, mas não separa caixas de entrada.
Este guia é para quem mantém fluxos do GitHub Actions e investiga códigos trocados, falhas intermitentes ou mensagens que parecem desaparecer.
Também atende equipes de QA que testam o cadastro e a recuperação de senha do próprio produto.
Desenvolvedores independentes e equipes pequenas podem usar as verificações para evitar misturar testes com caixas de entrada pessoais ou de trabalho.
A falha parece igual, mas pode ter causas diferentes
Uma mensagem que não chegou ao teste não significa automaticamente que o GitHub Actions falhou. Comece distinguindo três hipóteses:
- Falha de envio pelo produto: a ação de cadastro ou recuperação não gerou a mensagem. Verifique o evento no sistema sob teste e o resultado do componente responsável pelo envio.
- Atraso de recebimento: a mensagem foi gerada, mas ainda não está disponível quando a consulta acontece. Uma busca que termina cedo demais pode parecer uma falha de envio.
- Leitura cruzada: a mensagem existe, mas outra tarefa a encontrou primeiro, ou a tarefa atual selecionou uma mensagem pertencente a outro teste.
Os sinais de possível leitura cruzada incluem um código válido, mas rejeitado pelo fluxo atual; destinatários que não correspondem à execução; ou falhas que mudam quando a ordem das tarefas muda. Esses sinais orientam a investigação, mas não provam a causa. É necessário comparar a mensagem selecionada com a ação que deveria tê-la produzido.
Na análise de falhas, use evidências que permitam reconstruir o caminho: identificador da execução, tarefa ou cenário, endereço destinatário, assunto e marcador incluído na mensagem. Não registre o conteúdo inteiro se ele contiver dados pessoais ou credenciais. Em geral, os campos de correlação e o resultado das asserções bastam para identificar em que ponto ocorreu o desvio.
Caixa compartilhada ou destino isolado: onde o risco muda
Tarefas de uma matriz podem executar em paralelo, conforme a configuração do fluxo; a documentação do GitHub explica o comportamento das variações de tarefas em matriz. Se várias tarefas disparam mensagens e consultam o mesmo recebimento, é possível que uma tarefa encontre uma mensagem produzida por outra. Isso é uma hipótese a verificar na implementação, não uma falha geral confirmada da plataforma.
O risco aparece quando a consulta usa critérios amplos, como “a mensagem mais recente”, sem validar para quem foi enviada ou a qual cenário pertence. Mesmo que cada tarefa gere um código diferente, um leitor que consome a primeira mensagem disponível pode capturar o código errado. Se uma mensagem for removida ou marcada como lida durante a consulta, outras tarefas podem deixar de encontrá-la. O comportamento depende da infraestrutura de recebimento e da forma como o teste consulta as mensagens.
| Estratégia | Isolamento e custo operacional | Adequação relativa |
|---|---|---|
| Uma caixa de entrada compartilhada, sem filtro de execução | Pouca configuração inicial, mas cada tarefa pode selecionar mensagens de outra. Diagnosticar a falha exige reconstruir a sequência de consultas. | Baixa para tarefas concorrentes |
| Destino ou endereço distinto por tarefa concorrente | Reduz a sobreposição entre mensagens e facilita identificar a origem. Exige que o ambiente de teste consiga fornecer ou encaminhar destinos distintos. | Alta quando o recebimento permite |
| Caixa compartilhada com identificador e filtros rigorosos | Mantém um ponto de recebimento, mas exige que cada mensagem e consulta carreguem uma correlação verificável. Um filtro fraco ainda permite seleção incorreta. | Média; depende da qualidade da correlação |
| Limitar a concorrência de um recurso realmente compartilhado | Reduz o acesso simultâneo ao recurso, mas pode deixar trabalho esperando ou cancelar uma execução pendente conforme a configuração. Não cria isolamento de mensagens. | Média para conflitos comprovados |
A avaliação é qualitativa: compara capacidade de evitar sobreposição e esforço de operação, não mede taxa de sucesso. Para CI de e-mail, prefira alinhar o isolamento ao que executa em paralelo. Se uma tarefa de matriz representa um cenário independente, ela precisa de um destino ou marcador que a diferencie das demais. Se várias etapas sequenciais dentro da mesma tarefa compartilham um destino, podem usar o mesmo contexto, desde que não disputem mensagens.
Uma diferença importante: endereços distintos não garantem isolamento se todos forem encaminhados para uma única caixa que as tarefas consultam sem filtro. Nesse caso, o teste ainda precisa conferir o destinatário e a associação da mensagem. Para decidir entre endereço dedicado e caixa compartilhada com filtros, confira como o serviço de recebimento expõe destinatário, assunto e conteúdo. Não presuma que um recurso de CI fará essa associação automaticamente.
Identificador por execução ou busca pela mensagem mais recente
A busca pela mensagem mais recente é simples, mas frágil: outra tarefa pode ter provocado um envio mais novo antes da consulta. É melhor que o produto de teste inclua um marcador que a execução consiga reconhecer e que não revele dados pessoais. O marcador pode identificar a execução, a tarefa ou o cenário, e pode aparecer em um campo que o teste consiga consultar, como o assunto ou o conteúdo.
O GitHub Actions disponibiliza contextos com dados da execução e da estratégia. A referência oficial de contextos documenta os valores que podem compor essa identificação. Por exemplo, um trabalho de matriz pode formar um marcador de execução com os contextos da execução e do índice da tarefa:
env:
TEST_RUN_MARKER: ${{ github.run_id }}-${{ github.run_attempt }}-${{ strategy.job-index }}
Esse exemplo fornece uma base para correlação, não um endereço de e-mail nem uma garantia de isolamento. Antes de usar o valor, confirme que o contexto está disponível no local do fluxo em que a expressão é avaliada. Evite colocar tokens, códigos reais ou dados de clientes no marcador. O identificador deve permitir localizar a execução, não expor informações confidenciais.
Quando o sistema sob teste aceitar dados de correlação, inclua o marcador na solicitação que dispara a mensagem e faça o teste procurar uma mensagem correspondente. Se a aplicação não permite acrescentar metadados, tente correlacionar pelo destinatário, pelo assunto ou por um valor sintético exclusivo do cenário. Não torne a asserção tão permissiva que aceite uma mensagem antiga ou de outro fluxo.
O teste deve validar mais do que a existência de uma mensagem. Confira se o destinatário corresponde ao esperado, se o marcador pertence à execução atual e se o link ou código está presente e é utilizável dentro do próprio cenário. Para uma recuperação de senha, por exemplo, a asserção deve verificar que o link corresponde ao usuário sintético criado pelo teste, não apenas que há um link de recuperação no corpo.
Espera com saída definida ou consulta sem limite
Uma consulta de e-mail precisa ter uma condição clara de término. Faça novas consultas até encontrar a mensagem que satisfaça os critérios ou até alcançar o limite configurado para o teste. Se a condição não for atendida, encerre com um erro que indique o que foi procurado e o que foi encontrado. Não dependa de uma pausa fixa sem verificar o resultado: ela pode ser curta demais para o ambiente ou apenas aumentar o tempo de execução quando a mensagem já está disponível.
O fluxo de diagnóstico pode seguir esta ordem:
- Confirme nos registros do produto que a ação de teste solicitou o envio da mensagem.
- Registre o identificador da execução e o marcador esperado, sem expor credenciais.
- Consulte o recebimento usando o destinatário e o marcador, em vez de aceitar a mensagem mais recente sem validação.
- Repita a consulta com uma condição de saída explícita e guarde o resultado de cada tentativa que ajude a explicar a falha.
- Ao encontrar uma mensagem, valide destinatário, marcador e campo esperado — código ou link — antes de concluir o teste.
- Se a condição de saída ocorrer sem correspondência, compare as mensagens disponíveis e classifique o caso como ausência, filtro incompatível ou possível leitura por outra tarefa.
- Preserve os registros mínimos necessários para reproduzir a falha e remova dados pessoais ou segredos antes de compartilhá-los.
Essa sequência ajuda a separar três resultados que costumam ser confundidos. Nenhuma mensagem visível pode indicar envio não acionado, atraso ou consulta ao destino incorreto. Mensagem presente, mas rejeitada pelo filtro aponta para uma condição de busca incompatível com o conteúdo recebido. Mensagem com marcador ou destinatário de outra tarefa sustenta a hipótese de leitura cruzada e pede revisão da separação entre tarefas.
Use os registros para provar o que ocorreu, não para supor uma velocidade de entrega. Não há um tempo universal que permita afirmar que toda mensagem de teste deve chegar dentro de um intervalo fixo. O limite de espera deve refletir o comportamento esperado do ambiente e o que a equipe aceita como duração máxima do teste. Quando ele for excedido, o erro deve mostrar a execução, o destinatário esperado e o resultado da última busca — sem imprimir o código de verificação.
Para proteger as informações do fluxo, limite também o que aparece nos logs e nos artefatos. As recomendações oficiais do GitHub para uso seguro de fluxos de trabalho destacam a necessidade de tratar entradas e segredos com cuidado. Se os registros de diagnóstico precisarem ser preservados para análise, a documentação de artefatos de fluxo de trabalho explica como armazenar arquivos gerados por uma execução. Remova tokens e dados pessoais antes de publicar ou compartilhar esses arquivos.
concurrency limita execução, não cria caixas de entrada
O GitHub Actions permite configurar concorrência para fluxos e tarefas. A documentação explica como grupos de concorrência controlam execuções em andamento e pendentes, incluindo opções que afetam cancelamento e fila. Consulte as regras atuais de concorrência de fluxos e tarefas antes de alterar o comportamento de um fluxo.
Esse recurso é útil quando há um recurso compartilhado que realmente não suporta acesso simultâneo. Pode fazer sentido, por exemplo, limitar tarefas que alteram o mesmo ambiente de teste. Mas o grupo de concorrência não separa os destinatários, não adiciona um marcador às mensagens e não impede que uma tarefa consulte o recebimento de outra. Ele administra execuções; o isolamento do e-mail continua sendo responsabilidade do desenho do teste.
Revise também o escopo do grupo. Se tarefas independentes usarem um grupo comum, a configuração pode impedir que todas avancem como esperado. Se cancel-in-progress estiver ativado, uma nova execução poderá cancelar outra que esteja em andamento, de acordo com a configuração documentada. Esse comportamento pode esconder uma disputa em vez de corrigi-la, além de descartar um teste válido.
Antes de aplicar um limite, identifique qual recurso está sendo compartilhado e quais execuções entram no mesmo grupo. A documentação de controle de concorrência oferece os detalhes de configuração. Use o grupo mais estreito que proteja o recurso conflitante. Mantenha em paralelo as tarefas que não disputam esse recurso, e não use serialização global como substituto para destinatários únicos ou filtros corretos.
Checklist de isolamento antes de alterar o fluxo
- [ ] Cada tarefa que pode enviar e consultar mensagens ao mesmo tempo tem um endereço ou destino distinguível?
- [ ] Se várias tarefas usam uma caixa compartilhada, cada consulta confere destinatário e marcador da execução?
- [ ] A mensagem de teste contém um identificador não sensível que permite ligá-la ao cenário correto?
- [ ] A asserção verifica a mensagem esperada, em vez de aceitar qualquer código ou link recente?
- [ ] A espera tem uma condição de saída e informa o que foi procurado quando termina sem correspondência?
- [ ] Os registros ajudam a distinguir envio não acionado, mensagem ainda não visível e seleção de mensagem errada?
- [ ] Tokens, códigos válidos e dados pessoais ficam fora dos logs e dos artefatos compartilhados?
- [ ] Cada grupo
concurrencyprotege um recurso compartilhado identificado, em vez de serializar tarefas sem relação? - [ ] O comportamento de cancelamento e de execução pendente foi revisado para evitar descartar testes válidos?
- [ ] Os casos cobrem tanto o cadastro quanto a recuperação de senha do produto próprio, se ambos enviarem mensagens?
Se a maioria das verificações de associação falhar, corrija primeiro o modelo de recebimento. Se a associação estiver correta, mas as mensagens chegarem após o limite de espera, investigue o caminho de envio e ajuste a espera com base nos registros do ambiente. Se o erro desaparecer apenas quando a execução fica serial, teste se há consumo ou consulta destrutiva da mensagem compartilhada antes de concluir que o fluxo inteiro precisa ser sequencial.
Perguntas frequentes sobre mensagens cruzadas no CI
Por que um teste paralelo pode capturar o código de verificação de outra execução?
Isso pode acontecer quando tarefas diferentes consultam o mesmo estado de recebimento e selecionam a primeira mensagem disponível, sem conferir destinatário ou identificador da execução. A hipótese precisa ser verificada nos registros: compare o endereço, o assunto, o marcador da mensagem e a tarefa que a leu. Uma falha intermitente, sozinha, não prova que o GitHub Actions causou o problema.
Cada tarefa de CI precisa receber em um endereço diferente?
Quando tarefas concorrentes podem gerar mensagens ao mesmo tempo, um destino distinto por unidade de concorrência costuma facilitar o isolamento. Se a infraestrutura não permitir endereços separados, use um identificador único na mensagem e filtre por destinatário, assunto ou conteúdo antes de aceitá-la. A granularidade deve acompanhar o paralelismo real, não necessariamente cada etapa sequencial do fluxo.
O concurrency do GitHub Actions impede a troca de mensagens?
Não por si só. O recurso controla a execução de fluxos ou tarefas que compartilham um grupo de concorrência; ele não cria caixas de entrada nem associa mensagens aos testes. Pode ser adequado para proteger um recurso compartilhado, mas limitar o fluxo inteiro pode cancelar ou atrasar trabalho válido. Primeiro isole o recebimento e use concurrency apenas onde houver conflito comprovado.
Como separar atraso de entrega de leitura cruzada no teste de e-mail?
Registre o identificador da execução, o instante em que a ação foi solicitada, o resultado da consulta e os campos usados no filtro. Se a mensagem ainda não apareceu, o teste pode estar esperando o envio ou a entrega. Se aparece com outro destinatário ou marcador, investigue associação e leitura. Se a mensagem correta chegou, mas o filtro a rejeitou, revise a condição de busca.
Uma caixa temporária serve para inspeção manual, não para corrigir a arquitetura do CI
Para uma checagem manual de mensagens que o próprio produto envia, uma caixa temporária pode evitar expor um endereço pessoal ou misturar testes com a caixa de trabalho. O VoidFwd pode ser uma opção para esse tipo de inspeção pontual; a equipe ainda precisa validar o recebimento, a associação e as asserções do fluxo automatizado. Uma caixa temporária não substitui endereços isolados, não garante entrega nem resolve por conta própria uma leitura cruzada. Para decidir quando esse tipo de endereço é adequado, compare caixa temporária e alias de e-mail e considere os limites de privacidade descritos no guia de privacidade.
Perguntas frequentes
Por que um teste paralelo pode capturar o código de verificação de outra execução?
Isso pode acontecer quando tarefas diferentes consultam o mesmo estado de recebimento e selecionam a primeira mensagem disponível, sem conferir destinatário ou identificador da execução. A hipótese precisa ser verificada nos registros: compare o endereço, o assunto, o marcador da mensagem e a tarefa que a leu. Uma falha intermitente, sozinha, não prova que o GitHub Actions causou o problema.
Cada tarefa de CI precisa receber em um endereço diferente?
Quando tarefas concorrentes podem gerar mensagens ao mesmo tempo, um destino distinto por unidade de concorrência costuma facilitar o isolamento. Se a infraestrutura não permitir endereços separados, use um identificador único na mensagem e filtre por destinatário, assunto ou conteúdo antes de aceitá-la. A granularidade deve acompanhar o paralelismo real, não necessariamente cada etapa sequencial do fluxo.
O concurrency do GitHub Actions impede a troca de mensagens?
Não por si só. O recurso controla a execução de fluxos ou tarefas que compartilham um grupo de concorrência; ele não cria caixas de entrada nem associa mensagens aos testes. Pode ser adequado para proteger um recurso compartilhado, mas limitar o fluxo inteiro pode cancelar ou atrasar trabalho válido. Primeiro isole o recebimento e use concurrency apenas onde houver conflito comprovado.
Como separar atraso de entrega de leitura cruzada no teste de e-mail?
Registre o identificador da execução, o instante em que a ação foi solicitada, o resultado da consulta e os campos usados no filtro. Se a mensagem ainda não apareceu, o teste pode estar esperando o envio ou a entrega. Se aparece com outro destinatário ou marcador, investigue associação e leitura. Se a mensagem correta chegou, mas o filtro a rejeitou, revise a condição de busca.