1. Construir uma cadeia de evidência da release
Num cenário fictício de APS, a mudança aprovada refere R84, mas o operador só vê um ficheiro chamado service.zip. O nome é insuficiente para relacionar o pacote com os testes apresentados. Regista origem, execução selecionada, nome do artefacto, conteúdo esperado e critérios de aceitação. Distingue também a escolha manual do recurso da decisão de o usar: o seletor pode apresentar um run que falhou. Investiga onde ocorreu a falha e que evidência continua válida. Não assumes que uma versão indicada para a seleção por omissão prevalece quando um trigger de conclusão escolhe o recurso. Na reunião de preparação, pede ao responsável pelo build e ao responsável pela entrega que apontem para a mesma execução. Se surgir divergência, resolve-a antes de começar a mudança. O objetivo é que outra pessoa consiga reconstruir a decisão a partir dos registos, sem depender da memória de quem executou.
2. Confirmar presença, caminho e conteúdo antes de executar
O caso prático contém plan.json, mas falta service.zip de R84. O download terminou sem erro porque uma seleção ampla pode não falhar quando não encontra ficheiros. Confirma os ficheiros obrigatórios de forma explícita e investiga a publicação, o nome e os filtros usados. Um ZIP antigo no workspace não resolve essa lacuna. Se preDeploy precisa do plano, declara o download nesse hook; a injeção automática pertence a deploy. No exercício com o atalho download e recurso fundsBuild, o conteúdo de service fica em Pipeline.Workspace/fundsBuild/service. Não transfiras essa conclusão para todos os modos da tarefa DownloadPipelineArtifact: consulta os inputs e o destino configurado. Na origem, revê targetPath e a localização de .artifactignore quando o pacote publicado não corresponde ao esperado. Fecha a investigação comparando o conteúdo efetivo com o contrato da release, incluindo plano e binários. Um exit code verde é apenas uma parte da evidência.
3. Gerir disponibilidade e consumo de dependências
Publicar uma versão no feed e promovê-la para uma view são ações distintas. Define quem avalia os resultados antes de tornar a versão visível aos consumidores dessa view. Mudar a view por omissão não cria um novo destino de publicação. Se a versão promovida apresentar um defeito, o plano precisa de contenção dos consumidores e recuperação: não depende de uma operação de demotion que a documentação não suporta. Outro incidente envolve upstreams: LibA foi guardada, mas a instalação exige também LibB, nunca guardada. Remover a origem não demonstra que todo o conjunto de dependências ficou disponível. Faz um inventário do grafo necessário e confirma o restauro no contexto apropriado. Ao investigar uma versão inesperada, considera a precedência dos pacotes publicados diretamente no feed antes de alterar a ordem dos upstreams. Regista os consumidores afetados e a decisão para cada um; o estado do feed não descreve sozinho todas as aplicações já instaladas.
4. Usar cache como aceleração e interpretar o seu estado
O lockfile mudou e a execução obteve inexact por uma restoreKey. A condição que só instala dependências quando o resultado é false deixa passar este caso sem reconciliação. Pede ao aluno que compare o conteúdo restaurado com a intenção do lockfile e justifique a instalação necessária. O cache não é o contrato de aprovação do pacote. Para uma falha diferente, o segmento literal deps.v2 foi interpretado como caminho; as aspas distinguem esse texto do ficheiro cujo conteúdo deve participar na chave. Se uma instalação terminou mas o job falhou depois, verifica se a gravação Post-job: Cache realmente ocorreu. Também não uses a mesma chave em pipelines diferentes como mecanismo garantido de transporte da release. No diagnóstico, separa chave calculada, prefixo encontrado, scope e resultado da gravação. Essa sequência ajuda a explicar tanto misses legítimos como um restauro parcial que ainda exige trabalho.
5. Planear lotes e recuperar uma aplicação parcial
No modelo fictício, oito VMs saudáveis suportam vinte pedidos por segundo cada. Atualizar uma retira vinte e deixa cento e quarenta, suficientes para cento e vinte e cinco pedidos. Atualizar duas deixa cento e vinte e já não cumpre o contrato. O exercício não acrescenta margem de segurança, falhas ou diferenças de capacidade; uma decisão real precisa desses dados. maxParallel limita o lote, mas não prova que a carga cabe no serviço restante. Antes de repetir um stage rolling, considera que o retry pode voltar a executar em todas as VMs. No segundo caso prático, duas terminaram, uma falhou após enviar uma instrução externa e outra ainda está por atualizar. Inventaria versões, saúde e efeitos por alvo, confirma a instrução incerta e escolhe recuperação autorizada. Reduzir concorrência não converte um script sem deduplicação numa operação que só ocorre uma vez. Documenta também o responsável por reconciliar o estado externo.
6. Observar slots sem ignorar efeitos de arranque
No exemplo, a aplicação inicia um consumidor de filas ao arrancar. Durante preview, a configuração do destino pode ser aplicada à origem antes de trocar tráfego HTTP. Pergunta que ligações ficam efetivas e se o arranque pode consumir mensagens reais. Esta consequência depende do comportamento da aplicação descrita; não é uma garantia de que todos os slots processam filas. Se existe requisito de manter autenticação App Service, confirma a incompatibilidade documentada com swap with preview e escolhe um percurso compatível. Para acesso restrito, zero por cento de tráfego automático não torna o hostname privado: define controlos de acesso adequados e verifica a rede permitida e a proibida. Finalmente, cem pedidos do mesmo browser podem ficar presos ao mesmo slot pelo cookie de encaminhamento. Usa observações representativas de sessões e carga, explicando quais os dados que ainda faltam antes de concluir que a distribuição ou a aplicação estão corretas.
7. Separar reposição técnica de aceitação funcional
O endpoint voltou a responder, mas trinta e sete operações têm confirmação desconhecida num serviço externo. Reenviar todas pode duplicar trabalho; encerrar o incidente pode esconder resultados por reconciliar. Usa identificadores e estados observados para determinar o resultado de cada operação e atribui a resolução das exceções. A versão anterior pode repor código sem anular efeitos externos. Para promover uma release, define também observação representativa do trabalho. No exercício, o critério acordado exige cem transações interativas e um ciclo batch completo. Cento e quarenta transações durante a tarde não substituem o batch noturno. Aguarda essa evidência ou revê formalmente o critério com os responsáveis. Estes números são escolhas fictícias do exercício, não limites impostos pela Microsoft. O registo de decisão deve mostrar o que foi observado, o que ficou pendente, quem aceita o risco e que condição permite avançar ou exige parar.
8. Praticar integridade e explicar os limites da evidência
O laboratório abaixo cria ficheiros fictícios numa pasta temporária e compara-os com um manifesto fixo, considerado confiável neste exercício. Prevê primeiro o resultado quando falta service.bin, quando o plano muda e quando a execução esperada é diferente. Executa depois as verificações e explica cada falha. Há um caso deliberado em que ficheiro e manifesto são alterados em conjunto e a comparação passa. Esse resultado demonstra que igualdade de hashes não autentica o autor nem prova aprovação; seria preciso estabelecer confiança na origem do manifesto por meios adequados ao sistema real. O laboratório não implementa esse mecanismo. A segunda parte verifica a aritmética dos lotes e mostra que perder mais uma VM muda a decisão. Termina com uma nota de release: identidade esperada, conteúdo confirmado, evidência ausente e próximo responsável. Relaciona o exercício com a seleção de artefactos, a recuperação de efeitos externos e os critérios funcionais estudados.
# Original local exercise: trusted fixture manifest, never a production verifier.
# Fixed filenames only. Hash equality checks bytes, not authenticity or approval.
# No cloud APIs, network, subprocesses or existing application files are used.
from hashlib import sha256
from pathlib import Path
from tempfile import TemporaryDirectory
REQUIRED = ('service.bin', 'plan.json')
def digest(data):
return sha256(data).hexdigest()
def inspect_bundle(folder, manifest, expected_run):
problems = []
if manifest.get('run') != expected_run:
problems.append('run-mismatch')
declared = manifest.get('files', {})
for name in REQUIRED:
path = folder / name
if name not in declared:
problems.append('undeclared:' + name)
if not path.is_file():
problems.append('missing:' + name)
elif name in declared and digest(path.read_bytes()) != declared[name]:
problems.append('digest:' + name)
return problems
def enough_capacity(healthy, unavailable, per_vm, load):
# Fictional equal-capacity model: no failures or safety margin beyond inputs.
if not 0 <= unavailable <= healthy:
raise ValueError('invalid unavailable count')
return (healthy - unavailable) * per_vm >= load
with TemporaryDirectory(prefix='dr-artifact-lesson-') as temporary:
root = Path(temporary)
payload = {'service.bin': b'fictional-build-R84',
'plan.json': b'{"mode":"reconcile","release":"R84"}'}
for name, data in payload.items():
(root / name).write_bytes(data)
trusted = {'run': 'R84', 'files': {n: digest(v) for n, v in payload.items()}}
assert inspect_bundle(root, trusted, 'R84') == []
assert inspect_bundle(root, trusted, 'R85') == ['run-mismatch']
(root / 'service.bin').unlink()
assert inspect_bundle(root, trusted, 'R84') == ['missing:service.bin']
(root / 'service.bin').write_bytes(b'leftover-from-R83')
assert inspect_bundle(root, trusted, 'R84') == ['digest:service.bin']
(root / 'service.bin').write_bytes(payload['service.bin'])
assert inspect_bundle(root, trusted, 'R84') == []
(root / 'plan.json').write_bytes(b'{"mode":"other"}')
assert inspect_bundle(root, trusted, 'R84') == ['digest:plan.json']
(root / 'plan.json').write_bytes(payload['plan.json'])
incomplete = {'run': 'R84', 'files': {'service.bin': trusted['files']['service.bin']}}
assert inspect_bundle(root, incomplete, 'R84') == ['undeclared:plan.json']
(root / 'service.bin').write_bytes(b'changed-code')
changed_manifest = {'run': 'R84', 'files': dict(trusted['files'])}
changed_manifest['files']['service.bin'] = digest(b'changed-code')
# This passes: a hash cannot authenticate a manifest supplied by an attacker.
assert inspect_bundle(root, changed_manifest, 'R84') == []
assert enough_capacity(8, 0, 20, 125)
assert enough_capacity(8, 1, 20, 125)
assert not enough_capacity(8, 2, 20, 125)
assert enough_capacity(8, 2, 20, 120)
assert not enough_capacity(7, 1, 20, 125)
assert [n for n in range(9) if enough_capacity(8, n, 20, 125)] == [0, 1]
print('14 bundle and capacity assertions passed; no cloud execution or authenticity proof')
R84 tem aprovação, mas falta o seu ZIP. Outra release ficou parcialmente aplicada e deixou uma instrução externa sem confirmação. O aluno decide como conservar identidade, conter efeitos e recuperar com evidência.
Armadilhas comuns
Tratar seleção como aprovação; aceitar ficheiros antigos pelo nome; ignorar inexact; planear demotion não suportada; repetir um stage sem reconciliar efeitos; confundir zero tráfego com acesso privado; assumir que hashes autenticam o manifesto.
Tópicos relacionados: Proveniência de software · Idempotência e reconciliação · Capacidade e disponibilidade · Aceitação da mudança
Entrega o conteúdo cuja identidade e completude consegues demonstrar. Recupera a partir do estado observado e confirma os resultados funcionais antes de declarar a mudança concluída.
Referência: Publish and download pipeline artifacts · AZ-400 objectives 2026-07-27