1. Transformar critérios de entrega em dependências
Uma equipa fictícia prepara a release de um serviço que encaminha pedidos de suporte. Compilar, testar e publicar são ações distintas. Escreve primeiro a condição de negócio: a publicação só pode começar depois de a compilação e os testes obrigatórios terminarem com êxito. Desenha as relações compile → tests → publish. Se tests e publish dependerem apenas de compile, podem avançar em paralelo; a posição de publish no fim do ficheiro não acrescenta a dependência que falta numa lista explícita. Em Cloud Build, waitFor permite representar estas relações. Usa paralelismo para trabalho independente, como documentação e análise estática, mantendo as condições obrigatórias no caminho que conduz à publicação. No trabalho de um gestor técnico, a pergunta útil é quem pode provar cada condição e onde fica esse resultado. Pede à equipa um exemplo de execução falhada e verifica se a publicação ficou bloqueada. Guarda o identificador do build, a revisão do código e o resultado do teste. Uma captura do estado final perde a relação entre estes elementos. O exercício desta aula trata decisões de configuração; não executa um build real nem concede permissões de publicação.
2. Ler a política que produz o estado verde
Um teste pode encontrar uma divergência de reconciliação e o build terminar com êxito porque a configuração tolera essa falha. A distinção interessa na passagem a produção: o requisito era obter reconciliação correta, não apenas terminar um processo. Examina as exceções antes de apresentar o resultado ao responsável APS. Em particular, allowFailure tolera falhas e allowExitCodes permite discriminar códigos, tendo precedência quando ambos estão definidos. Num exemplo com allowFailure: true e allowExitCodes: [3], uma saída 7 continua a ser uma falha do build. O número 3 identifica um resultado do programa; não representa três tentativas. Define com o responsável funcional quais os testes obrigatórios e quais são informativos. Um teste experimental de desempenho pode ser informativo durante a recolha de uma baseline, se isso estiver explicitamente acordado. Um teste obrigatório não deve mudar silenciosamente de categoria para cumprir a janela. No relatório de entrega, separa a falha observada, a exceção autorizada e a decisão pendente. Se alguém pedir para ignorar um resultado, pede a justificação e o impacto concreto no critério de aceitação.
3. Transportar resultados e alcançar dependências
Dois passos podem usar a mesma imagem e continuar a ter sistemas de ficheiros privados diferentes. Um relatório escrito em /tmp/checks no primeiro contentor não passa automaticamente para o segundo. Para partilhar o relatório no mesmo build, usa /workspace ou um volume explicitamente partilhado. Mantém também a dependência de execução: disponibilizar armazenamento não garante que o produtor já terminou. Para conservar evidência depois do build, planeia um destino duradouro aprovado e associa o relatório à revisão; o volume partilhado não é um arquivo entre builds. Numa migração para um private pool sem saída pública, inventaria previamente downloads de pacotes, ferramentas e imagens. Se uma dependência só estiver num endereço público e não existir percurso autorizado, aumentar IAM ou o timeout não resolve a ligação. Um espelho aprovado e acessível pode satisfazer o requisito, desde que a origem, versão e processo de atualização também sejam controlados. Combina um ensaio de conectividade com um ensaio de construção. O primeiro prova que se chega ao destino; o segundo verifica se a dependência correta chega ao passo certo. Regista quem mantém o espelho e como comunica versões retiradas.
4. Distinguir deploy, verificação e tentativa
Uma instalação concluída pode ser seguida de uma verificação falhada. Investiga o job run concreto: que teste correu, de onde, contra que endpoint e com que resultado? As tasks de verificação configuradas na estratégia Cloud Deploy correm no ambiente de execução do serviço. Não assumas que estão no cluster GKE da aplicação. Um probe interno pode passar enquanto o executor externo não tem o percurso necessário. Acesso ao plano de controlo também não demonstra acesso à aplicação. A documentação descreve outra configuração, através do verify de Skaffold, para executar a verificação no cluster GKE. Se o verify job falhou por uma dependência temporariamente indisponível e a causa foi corrigida, repetir esse job permite recolher um novo resultado. Conserva ambas as tentativas no raciocínio do incidente. Ignorar a falha não produz um teste novo. Antes de repetir, pergunta se o teste cria dados ou desencadeia operações: um ensaio que gera pedidos precisa de isolamento e limpeza definidos. No handover, inclui a localização do executor, os pré-requisitos, o responsável e a forma de distinguir uma falha do teste de uma falha do produto.
5. Interpretar a fase e o âmbito da entrega
Uma configuração canary descreve a progressão pretendida, mas a evidência deve mostrar quais as fases executadas. Num destino sem versão anterior reconhecida, as fases canary podem ser omitidas. Avançar para stable implica uma instalação integral nesse destino. Reportar uma exposição de 10% validada neste caso inventaria evidência. Planeia a primeira instalação como tal e recolhe resultados próprios antes de usar essa instalação como referência para alterações posteriores. A decisão de avançar deve explicar o âmbito real da exposição. Para entregar em paralelo a duas regiões com um único checkpoint, o multi-target representa essa etapa; a aprovação configura-se aí, não em child targets com requireApproval: true. Isso não transforma duas regiões numa transação indivisível. Para um destino híbrido personalizado, confirma também o contrato do adaptador: o custom deploy deve escrever results.json no output indicado pelo serviço. Uma ferramenta externa pode concluir a instalação sem produzir esse resultado. No acompanhamento do projeto, mantém separadas três provas: autorização da entrega, execução em cada destino e aceitação operacional. A falta de uma delas precisa de uma ação e de um responsável específicos.
6. Tornar os dados parte da evidência da pipeline
Numa pipeline de machine learning, a revisão do código não identifica sozinha o ensaio. Inclui a versão dos dados, a transformação aplicada, o modelo avaliado e os critérios aprovados. Se uma componente lê um URI constante cujo conteúdo muda, o sistema pode continuar a reconhecer a mesma interface de execução. Uma cache correspondente pode então reutilizar outputs antigos. Torna a versão dos dados explícita nas entradas; quando não consegues tornar a leitura determinística, considera desativar a cache nessa tarefa. Não contes com uma expiração diária que a documentação desta cache não define. Um contrato de dados também deve descrever significado. A coluna elapsed_ms pode manter nome e tipo numérico depois de passar a conter segundos. O treino pode terminar corretamente e produzir um modelo baseado numa interpretação errada. Investiga a origem e valida a transformação antes de promover. No exemplo fictício, o responsável pelos dados fornece a versão do exportador e a equipa do modelo demonstra a conversão. O gestor coordena os dois e conserva a decisão. Para seguir a documentação atual, a referência de cache regista o redirecionamento da página Vertex AI para Gemini Enterprise Agent Platform, sem assumir uma nova versão do exame.
7. Exercício guiado de critérios de promoção
Guarda o código apresentado como run.py e executa python3 run.py num ambiente local com Python 3.13. Não são necessárias credenciais nem recursos cloud. O programa usa contagens fictícias de triagem: 140 críticos detetados, 60 críticos não detetados, 9700 não críticos corretamente classificados e 100 falsos alarmes. Antes de executar, calcula accuracy e recall em separado. Deves obter 98,4% e 70%. A primeira métrica conta todos os acertos; a segunda responde à pergunta concreta sobre deteção dos críticos. A política didática exige recall de pelo menos 90%, pelo menos 100 exemplos críticos, contrato aprovado e correspondência da versão da evidência. Estes limites são inventados para o exercício; não garantem confiança estatística nem são uma política bancária ou requisito Google. Prevê o resultado quando TP passa a 180 e FN a 20. Depois experimenta uma versão errada, um contrato falhado e zero críticos. O programa testa 201 valores de TP, 16 combinações das condições e entradas inválidas. Um resultado eligible_for_review autoriza apenas a conclusão do modelo didático; não autentica evidência real nem aprova um deployment.
8. Preparar a decisão e a passagem para RUN
O caso final combina um build verde, um teste obrigatório falhado e recall insuficiente. A janela de entrega fecha em vinte minutos. Produz uma nota curta com a release candidata, os critérios, o resultado observado e a ação seguinte. A conclusão sustentada é reter a promoção, resolver o contrato e repetir a avaliação adequada. Mantém o serviço atual enquanto se prepara uma nova janela. Não apresentes o reagendamento como se fosse uma correção técnica; atribui as correções aos responsáveis e define qual a evidência necessária para voltar à decisão. Para preparar autonomia de RUN, junta um procedimento que permita localizar o build, os job runs, os relatórios e a revisão instalada. Explica como investigar ficheiros em falta, falhas de conectividade e resultados reaproveitados. Define a quem escalar uma discrepância de contrato e quem aceita o comportamento funcional. No resumo da aula, confirma quatro perguntas: que dependências bloqueiam a promoção, o que significa o estado verde, de onde veio a verificação e a que dados pertencem os resultados? São perguntas que ajudam a conduzir uma reunião de release em inglês e a transformar uma conversa vaga em ações verificáveis.
"""Original local teaching model. Trusted fictional evidence; no vendor calls."""
from fractions import Fraction
from hashlib import sha256
from itertools import product
from pathlib import Path
import json
import platform
def assess(counts, contract_passed, evidence_version, expected_version):
if set(counts) != {'tp', 'fn', 'tn', 'fp'}:
raise ValueError('exactly four confusion-matrix counts required')
if any(type(v) is not int or v < 0 for v in counts.values()):
raise ValueError('counts must be nonnegative integers, excluding booleans')
positives = counts['tp'] + counts['fn']
total = sum(counts.values())
recall = Fraction(counts['tp'], positives) if positives else None
accuracy = Fraction(counts['tp'] + counts['tn'], total) if total else None
gates = {
'contract_passed': contract_passed is True,
'version_bound': bool(expected_version) and evidence_version == expected_version,
'minimum_critical_examples': positives >= 100,
'critical_recall': recall is not None and recall >= Fraction(9, 10),
}
return {
'accuracy': str(accuracy) if accuracy is not None else None,
'recall': str(recall) if recall is not None else None,
'critical_examples': positives,
'eligible_for_review': all(gates.values()),
'failed_gates': [k for k, ok in gates.items() if not ok],
}
def run():
poor = {'tp': 140, 'fn': 60, 'tn': 9700, 'fp': 100}
boundary = {'tp': 180, 'fn': 20, 'tn': 9700, 'fp': 100}
cases = [
('high-accuracy-low-recall', poor, True, 'r17', 'r17', False),
('exact-recall-boundary', boundary, True, 'r17', 'r17', True),
('failed-contract', boundary, False, 'r17', 'r17', False),
('wrong-version', boundary, True, 'r16', 'r17', False),
('empty-version', boundary, True, '', '', False),
('string-boolean', boundary, 'true', 'r17', 'r17', False),
('small-perfect-sample', {'tp': 9, 'fn': 0, 'tn': 99, 'fp': 0}, True, 'r17', 'r17', False),
('no-critical-examples', {'tp': 0, 'fn': 0, 'tn': 100, 'fp': 0}, True, 'r17', 'r17', False),
('empty-sample', {'tp': 0, 'fn': 0, 'tn': 0, 'fp': 0}, True, 'r17', 'r17', False),
('sample-size-boundary', {'tp': 90, 'fn': 10, 'tn': 100, 'fp': 0}, True, 'r17', 'r17', True),
]
fixtures = []
for name, counts, contract, evidence, expected, eligible in cases:
result = assess(counts, contract, evidence, expected)
assert result['eligible_for_review'] is eligible, name
fixtures.append({'id': name, **result})
assert fixtures[0]['accuracy'] == '123/125'
assert fixtures[0]['recall'] == '7/10'
assert fixtures[7]['recall'] is None
assert fixtures[8]['accuracy'] is None
recall_cases = 0
for tp in range(201):
result = assess({'tp': tp, 'fn': 200-tp, 'tn': 9700, 'fp': 100}, True, 'r17', 'r17')
assert result['eligible_for_review'] == (tp >= 180)
recall_cases += 1
truth_cases = 0
for contract, version, sample, quality in product([False, True], repeat=4):
count = 100 if sample else 10
tp = count if quality else count//2
result = assess({'tp': tp, 'fn': count-tp, 'tn': 900, 'fp': 0}, contract, 'r17' if version else 'r16', 'r17')
assert result['eligible_for_review'] == all([contract, version, sample, quality])
truth_cases += 1
bad_counts = [{}, {**poor, 'extra': 1}, {**poor, 'tp': -1}, {**poor, 'tp': True}, {**poor, 'tp': 140.0}, {**poor, 'tp': '140'}]
rejected = 0
for counts in bad_counts:
try:
assess(counts, True, 'r17', 'r17')
except ValueError:
rejected += 1
assert rejected == len(bad_counts)
return {'scriptSha256': sha256(Path(__file__).read_bytes()).hexdigest(),
'pythonVersion': platform.python_version(), 'fixtures': fixtures,
'namedChecks': len(fixtures), 'recallCases': recall_cases,
'truthCases': truth_cases, 'invalidCountCases': rejected,
'network': False, 'persistentWrites': False, 'vendorExecution': False,
'independentVerification': False,
'limitations': 'Fictional teaching thresholds; no statistical confidence calculation, model training, real evidence authentication or deployment authorization.'}
if __name__ == '__main__':
print(json.dumps(run(), ensure_ascii=False, indent=2))
Uma release de triagem tem build verde mas falha o contrato e deteta apenas 70% dos tickets críticos.
Armadilhas comuns
Confundir ordem textual com dependência, estado verde com todos os testes passados e accuracy agregada com deteção dos críticos.
Tópicos relacionados: Segurança da cadeia de software · SLOs e validação operacional · Contratos de dados e observabilidade de modelos
Uma promoção exige evidência ligada à versão, aos critérios acordados e ao percurso real de execução.
Referência: Configuring the order of build steps · Current linked guide; edition date unconfirmed (2026-09-30 inspection)