← AZ-400: DevOps da entrega à operação
23 / 26 · 120 MIN

Operação de pipelines: eventos, filas e evidência

Diagnosticar seleção e repetição de execuções, preservar trabalho obrigatório e relacionar os artefactos com a entrega autorizada.

Identificar os inputs e os caminhos

Antes de investigar um build, regista a execução, a tentativa, os commits e os caminhos realmente usados. No exemplo, funds era obtido em s; acrescentar tools sem caminhos explícitos passa os repositórios para s/funds e s/tools. O publicador que continua a ler s/out pode encontrar uma saída antiga num agente reutilizado. O problema não fica resolvido apenas porque o ficheiro existe. Confirma o caminho do produtor, o caminho do consumidor e a ligação ao candidato pretendido. Declara self quando os seus ficheiros são necessários juntamente com outro checkout. Usa caminhos explícitos quando isso torna o contrato entre passos mais claro. workspaceRepo escolhe o diretório de trabalho predefinido, mas não escolhe a branch nem junta árvores. Conserva no diagnóstico os identificadores necessários sem imprimir credenciais ou conteúdo sensível.

Escolher a revisão no momento correto

Um checkout inline é resolvido como referência de recurso na compilação. Colocar $(branch) no valor não faz a expansão macro esperada; o serviço pode procurar esse texto literal. Quando a escolha deve ser feita ao preparar a execução, um parâmetro referenciado por expressão de template fornece uma alternativa apropriada. Isso não autoriza qualquer branch: a equipa continua responsável por restringir as escolhas de acordo com o seu processo. Também não se deve assumir que um trigger de conclusão transporta o mesmo commit entre repositórios diferentes. Regista a revisão da aplicação e a revisão do repositório de deployment separadamente. Em GitHub, uma chamada relativa a um workflow local usa o commit do chamador. São contratos diferentes, que devem ficar explícitos antes de atribuir uma falha a código recentemente alterado.

Diagnosticar o evento antes de procurar um agente

Se não existe execução, começa pelos filtros e pela configuração que os avalia. Em Azure, editar um filtro de conclusão numa feature branch não altera automaticamente a versão da branch predefinida usada na avaliação. Tags listadas no trigger são cumulativas e todos os stages selecionados têm de concluir com sucesso. Para CI, confirma também overrides na interface e a capitalização dos caminhos Git. Em Azure Repos, a validação de pull requests é configurada por política da branch de destino. Um bloco pr copiado de outro fornecedor não demonstra a proteção pretendida. Quando surgem duas execuções, compara os motivos: CI e conclusão podem ter iniciado trabalhos distintos. Só depois de compreender a intenção de cada evento decide remover um trigger, evitando perder uma validação necessária.

Distinguir feedback de build e espera de entrega

Uma execução CI em batch pode permanecer aberta à espera de aprovação de deployment. Nesse desenho, adicionar agentes não termina a execução anterior nem liberta o batch seguinte. Se o objetivo é obter feedback rápido e manter aprovação de produção, separa os fluxos e transporta uma identidade de artefacto verificável entre eles. O projeto precisa de definir quem aprova, o que aprova e a evidência necessária para a decisão. Não confundas batch de CI com batch de schedules: no agendamento Azure, always: true pode iniciar outra execução mesmo com batch: true. Uma propriedade com o mesmo nome não garante a mesma semântica em eventos diferentes. Mede o tempo em fila, o tempo de execução e o tempo de espera humana separadamente para escolher a alteração que resolve o atraso observado.

Uma fila não representa todas as obrigações de negócio

No GitHub.com, queue: single mantém apenas uma execução pendente no grupo; uma nova chegada substitui a anterior. cancel-in-progress controla separadamente a execução em curso. queue: max permite mais pendentes, mas tem capacidade limitada e não é compatível com cancel-in-progress: true. A ordem de espera no grupo pode diferir da ordem original dos pedidos. No caso das migrações M1, M2 e M3, a obrigação é aplicar uma sequência com pré-requisitos. Antes de avançar M3, confirma o estado efetivo e recupera a operação M2 que foi cancelada. Um registo durável e um executor que valide pré-requisitos podem apoiar esse desenho. Aumentar a fila não recupera automaticamente trabalho perdido. Define também o tratamento de saturação, repetição e execução parcial, sem presumir rollback de ações externas ao cancelar um workflow.

Interpretar repetição, conclusão e autorização

Uma repetição GitHub conserva GITHUB_SHA, GITHUB_REF e os privilégios do ator que iniciou a execução original. A pessoa que pede re-run pode ser diferente; isso não torna a tentativa uma execução no commit mais recente nem transfere automaticamente os seus privilégios. Identifica a tentativa e a evidência produzida em cada repetição. Num fluxo encadeado por workflow_run, completed inclui conclusões de falha. Se a regra acordada permite publicar apenas após sucesso, aplica uma condição sobre a conclusão upstream no job relevante. Mesmo essa condição não prova que um pacote específico corresponde à execução aceite. Correlaciona o artefacto e verifica o critério da entrega. Mantém separadas as perguntas sobre fim da execução, sucesso técnico, identidade do conteúdo e autorização de negócio; cada uma precisa de evidência própria.

Publicar evidência identificável e preservá-la

Numa matrix, dá nomes distintos aos artefactos de cada dimensão e define como serão agregados. Substituir um artefacto com overwrite cria outra identidade, pelo que uma aprovação ligada ao ID anterior precisa de ser reconciliada. Quando um relatório é obrigatório, a ausência deve falhar a tarefa e chegar à decisão de aceitação; um aviso pode deixar o job verde. Revê igualmente os ficheiros ocultos: incluir um manifesto necessário não autoriza publicar um ficheiro de credenciais na mesma pasta. Depois de descarregar, trata divergências de digest segundo o critério de integridade definido; um aviso não implementa sozinho a rejeição. Planeia a conservação da evidência existente, pois aumentar a retenção não prolonga retroativamente os objetos antigos. Nenhuma destas verificações transforma, por si, o pacote numa entrega aprovada.

Praticar decisões e reconhecer os limites do modelo

O script desta aula trabalha apenas com registos fictícios em memória. Modela algumas regras de admissão na fila, filtros cumulativos e um critério de aceitação que exige revisões, tentativa, ID e outputs específicos. Altera mentalmente um campo antes de executar e prevê a verificação que deve falhar. O caso do pacote residual mostra porque encontrar um ZIP não prova a sua origem. O caso das migrações mostra porque serializar não garante conservar todas as operações. O script não interpreta YAML, não chama Azure ou GitHub e não executa migrações. Os resultados comprovam o comportamento deste modelo e ajudam a discutir decisões; a validação de uma plataforma real exige um ensaio autorizado com configuração e versão identificadas. Resume a decisão, a evidência em falta e a alternativa aceitável antes de consultar as respostas.

"""Local teaching model. Does not run or emulate Azure/GitHub pipeline engines.
Inputs are fictional records. No filesystem writes, network or credentials.
"""
import json


def enqueue(pending, arrival, mode):
    """Selected documented pending-admission rules; no running cancellation."""
    if mode == 'single':
        return [arrival], list(pending)
    if mode == 'max':
        return (list(pending), [arrival]) if len(pending) >= 100 else (pending + [arrival], [])
    raise ValueError('Unsupported teaching-model mode')


def completion_matches(required_tags, actual_tags, required_stages, outcomes):
    return set(required_tags) <= set(actual_tags) and all(
        outcomes.get(stage) == 'success' for stage in required_stages)


def assess_package(candidate, actual, required_files):
    """Fictional acceptance rule, NOT a vendor-provided guarantee."""
    errors = []
    for key in ['app_commit', 'tools_commit', 'attempt', 'artifact_id']:
        if actual.get(key) != candidate.get(key):
            errors.append('identity:' + key)
    if not set(required_files) <= set(actual.get('files', [])):
        errors.append('missing-required-output')
    if not actual.get('digest_matches', False):
        errors.append('digest-not-confirmed')
    return errors


def next_migration(expected, applied, requested):
    """Require applied IDs to be an exact prefix; no actual database operations."""
    if applied != expected[:len(applied)]:
        return 'reconcile'
    remaining = expected[len(applied):]
    if not remaining:
        return 'already-complete'
    return 'eligible' if requested == remaining[0] else 'prerequisite-missing'


def run():
    checks = []
    def check(name, condition):
        if not condition:
            raise AssertionError(name)
        checks.append(name)

    # Explicit fixture from the lesson, not a general Azure path resolver.
    paths = {'funds': 's/funds', 'tools': 's/tools'}
    check('funds path after second checkout', paths['funds'] == 's/funds')
    check('old output path is not current output path', 's/out/package.zip' != paths['funds'] + '/out/package.zip')
    check('one tag cannot satisfy two tags', not completion_matches(['Signed', 'Production'], ['Signed'], ['Build'], {'Build': 'success'}))
    check('all required tags satisfy tag filter', completion_matches(['Signed', 'Production'], ['Signed', 'Production'], ['Build'], {'Build': 'success'}))
    check('running stage does not satisfy completion', not completion_matches([], [], ['Build', 'PreProd'], {'Build': 'success', 'PreProd': 'running'}))
    check('failed stage does not satisfy completion', not completion_matches([], [], ['Build', 'PreProd'], {'Build': 'success', 'PreProd': 'failure'}))
    check('both successful stages satisfy completion', completion_matches([], [], ['Build', 'PreProd'], {'Build': 'success', 'PreProd': 'success'}))
    check('missing named stage is not success', not completion_matches([], [], ['PreProd'], {}))
    pending, canceled = enqueue(['M2'], 'M3', 'single')
    check('single replaces older pending', pending == ['M3'])
    check('single reports canceled pending', canceled == ['M2'])
    pending, canceled = enqueue(['M2'], 'M3', 'max')
    check('max admits another pending below capacity', pending == ['M2', 'M3'] and canceled == [])
    full = [f'run-{n}' for n in range(100)]
    pending, canceled = enqueue(full, 'extra', 'max')
    check('max rejects arrival at capacity', canceled == ['extra'])
    check('max preserves existing pending at capacity', pending == full)
    check('queue helper does not mutate input', full == [f'run-{n}' for n in range(100)])
    arrivals = [{'id': 'M2', 'dispatched': 1, 'waiting': 8}, {'id': 'M3', 'dispatched': 2, 'waiting': 5}]
    ordered = sorted(arrivals, key=lambda r: r['waiting'])
    check('waiting order can differ from dispatch order', [r['id'] for r in ordered] == ['M3', 'M2'])
    candidate = dict(app_commit='F8', tools_commit='T3', attempt='new', artifact_id=811)
    valid = dict(candidate, files=['package.zip', '.manifest'], digest_matches=True)
    required = ['package.zip', '.manifest']
    check('matching complete evidence accepted by fictional rule', assess_package(candidate, valid, required) == [])
    for key, wrong in [('app_commit', 'F7'), ('tools_commit', 'T2'), ('attempt', 'old'), ('artifact_id', 810)]:
        check('reject wrong ' + key, 'identity:' + key in assess_package(candidate, dict(valid, **{key: wrong}), required))
    check('reject missing manifest', 'missing-required-output' in assess_package(candidate, dict(valid, files=['package.zip']), required))
    check('reject digest warning under fictional acceptance rule', 'digest-not-confirmed' in assess_package(candidate, dict(valid, digest_matches=False), required))
    check('absent digest evidence is not accepted', 'digest-not-confirmed' in assess_package(candidate, {k:v for k,v in valid.items() if k != 'digest_matches'}, required))
    # Deliberate exact allowlist, not upload-artifact glob behavior.
    local_files = ['package.zip', '.manifest', '.env']
    selected = [f for f in local_files if f in required]
    check('explicit allowlist includes reviewed manifest', '.manifest' in selected)
    check('explicit allowlist excludes credential fixture', '.env' not in selected)
    sequence = ['M1', 'M2', 'M3']
    check('M3 cannot skip M2', next_migration(sequence, ['M1'], 'M3') == 'prerequisite-missing')
    check('M2 eligible after M1', next_migration(sequence, ['M1'], 'M2') == 'eligible')
    check('M3 eligible after M2', next_migration(sequence, ['M1', 'M2'], 'M3') == 'eligible')
    check('unexpected ledger requires reconciliation', next_migration(sequence, ['M2'], 'M3') == 'reconcile')
    check('complete ledger avoids duplicate application', next_migration(sequence, sequence, 'M3') == 'already-complete')
    return dict(passed=len(checks), checks=checks, execution='local-synthetic-model', network=False, filesystemWrites=False,
                limitations=['No Azure pipeline or GitHub Actions run executed.', 'No YAML parser, scheduler, permission evaluation, action upload or database migration executed.', 'Models selected rules and fictional acceptance records; passing checks are not cloud-platform validation.'])


if __name__ == '__main__':
    print(json.dumps(run(), indent=2))
NA PRÁTICA

Um agente reutilizado publica o ZIP de ontem depois de um segundo checkout alterar os caminhos; a equipa tem de demonstrar F8/T3 e o ensaio exigido antes da entrega.

Armadilhas comuns

Assumir que sucesso do upload prova o candidato, que completed significa success ou que uma fila conserva automaticamente todas as migrações.

Tópicos relacionados: Identidade de artefactos e aprovações · Repositórios e builds reproduzíveis · Migrações e recuperação após falha

Leva esta ideia contigo

Antes de aceitar uma entrega, liga inputs, tentativa, output e aprovação. Reconcilia efeitos externos e operações canceladas segundo os pré-requisitos reais.

Criar conta

Referência: Check out multiple repositories · AZ-400 objectives 2026-07-27

Microsoft é uma marca comercial do grupo de empresas Microsoft. A dr.pt é uma plataforma de preparação independente e não está afiliada, associada, patrocinada, autorizada nem aprovada por Microsoft. Os conteúdos e as perguntas são originais, não são perguntas oficiais de exame, e concluir os nossos testes não atribui nem garante qualquer certificação. Os nomes são usados apenas para identificar o tema. Todas as outras marcas pertencem aos respetivos titulares.