← Professional Cloud DevOps Engineer: delivery and reliability
11 / 15 · 120 MIN

Pipelines and promotion evidence

Build dependencies, interpret results and decide application and model promotion using operational evidence.

1. Turn delivery criteria into dependencies

A fictional team prepares a release of a service that routes support requests. Compilation, testing and publishing are separate actions. First write the business condition: publishing may begin only after compilation and required tests succeed. Draw compile → tests → publish. If tests and publish depend only on compile, they can proceed in parallel; placing publish at the bottom of the file does not add a missing dependency to an explicit list. Cloud Build uses waitFor to represent these relationships. Apply parallelism to independent work, such as documentation and static analysis, while keeping required conditions on the path leading to publication. For a technical manager, the useful question is who can prove each condition and where its result is recorded. Ask the team for an example failed execution and check whether publication was blocked. Retain the build identifier, code revision and test result. A screenshot of final status loses the relationship between these elements. This lesson examines configuration decisions; it does not execute a real build or grant publication permissions.

2. Read the policy behind green status

A test can detect a reconciliation discrepancy while the build succeeds because configuration tolerates that failure. This distinction matters at production handover: the requirement was correct reconciliation, not merely process completion. Inspect exceptions before presenting the outcome to the APS owner. In particular, allowFailure tolerates failures and allowExitCodes distinguishes codes, taking precedence when both are configured. In an example with allowFailure: true and allowExitCodes: [3], exit 7 still fails the build. The number 3 identifies a program outcome; it does not mean three attempts. Agree with the functional owner which tests are mandatory and which are informational. An experimental performance test may be informational while collecting a baseline, provided this is explicitly agreed. A mandatory test should not silently change category to meet a release window. In the delivery report, distinguish the observed failure, authorized exception and outstanding decision. If someone requests ignoring a result, ask for the rationale and its specific impact on the acceptance criterion.

3. Transfer results and reach dependencies

Two steps may use the same image while still having different private filesystems. A report written under /tmp/checks in the first container does not automatically reach the second. To share the report within the same build, use /workspace or an explicitly shared volume. Keep the execution dependency as well: available storage does not guarantee that its producer has finished. To retain evidence after the build, plan an approved durable destination and bind the report to its revision; the shared volume is not an archive across builds. Before moving to a private pool without public egress, inventory downloads of packages, tools and images. If a dependency exists only at a public address and no authorized path exists, increasing IAM permissions or timeouts cannot fix connectivity. An approved reachable mirror can satisfy the requirement, provided its origin, version and update process are also controlled. Combine a connectivity trial with a build trial. The first establishes reachability; the second checks that the correct dependency reaches the correct step. Record who maintains the mirror and how withdrawn versions are communicated.

4. Distinguish deployment, verification and attempt

A completed installation can be followed by failed verification. Investigate the specific job run: which test ran, from where, against which endpoint and with what result? Verification tasks configured in the Cloud Deploy strategy run in the service's execution environment. Do not assume they run inside the application's GKE cluster. An internal probe may pass while the external executor lacks the required path. Control-plane access does not establish application access either. Documentation describes a different configuration, through Skaffold verify, for running verification inside the GKE cluster. If the verify job failed because a dependency was temporarily unavailable and the cause is fixed, retrying that job collects a new result. Preserve both attempts in the incident account. Ignoring failure does not produce a new test. Before retrying, ask whether the test creates data or triggers operations: a trial generating requests needs defined isolation and cleanup. At handover, include the executor location, prerequisites, owner and method for distinguishing a test failure from a product failure.

5. Interpret delivery phase and scope

Canary configuration describes intended progression, but evidence must show which phases actually ran. On a target without a recognized previous version, canary phases may be skipped. Advancing to stable means full deployment to that target. Reporting validated 10% exposure in this case would invent evidence. Plan the initial installation accordingly and collect its own results before using it as a reference for subsequent changes. The decision to advance should explain the actual exposure scope. For parallel delivery to two regions with one checkpoint, the multi-target represents that stage; approval is configured there, not on child targets with requireApproval: true. This does not make two regions an indivisible transaction. For a custom hybrid target, also check the adapter contract: custom deploy must write results.json to the output location provided by the service. An external tool may complete installation without producing that result. In project tracking, keep three proofs separate: delivery authorization, execution on each target and operational acceptance. A missing proof requires a specific action and owner.

6. Make data part of pipeline evidence

In a machine learning pipeline, code revision alone does not identify a trial. Include the data version, transformation applied, evaluated model and approved criteria. If a component reads a constant URI whose contents change, the system may still recognize the same execution interface. A matching cache can then reuse old outputs. Make data version explicit in the inputs; where the read cannot be made deterministic, consider disabling caching for that task. Do not rely on daily expiry that this cache's documentation does not define. A data contract must also describe meaning. The elapsed_ms column may retain its name and numeric type after starting to contain seconds. Training can finish successfully and produce a model based on a wrong interpretation. Investigate the source and validate the transformation before promotion. In the fictional example, the data owner supplies the exporter version and the model team demonstrates conversion. The manager coordinates both and retains the decision. To follow current documentation, the cache reference records the redirect from the Vertex AI page to Gemini Enterprise Agent Platform without assuming a new exam edition.

7. Guided promotion-criteria exercise

Save the displayed code as run.py and run python3 run.py locally with Python 3.13. No credentials or cloud resources are needed. The program uses fictional triage counts: 140 detected critical tickets, 60 missed critical tickets, 9700 correctly classified noncritical tickets and 100 false alarms. Before running it, calculate accuracy and recall separately. Expect 98.4% and 70%. The first metric counts all correct classifications; the second answers the specific question about critical-ticket detection. The teaching policy requires recall of at least 90%, at least 100 critical examples, a passed contract and matching evidence version. These thresholds are invented for the exercise; they establish neither statistical confidence nor a banking policy or Google requirement. Predict the result when TP becomes 180 and FN becomes 20. Then try a wrong version, failed contract and zero critical tickets. The program checks 201 TP values, 16 combinations of conditions and invalid inputs. An eligible_for_review result establishes only the teaching model's conclusion; it authenticates no real evidence and approves no deployment.

8. Prepare the decision and RUN handover

The final case combines a green build, a failed mandatory test and insufficient recall. The delivery window closes in twenty minutes. Write a short note containing the candidate release, criteria, observed outcome and next action. The supported conclusion is to hold promotion, resolve the contract and repeat the appropriate evaluation. Retain the current service while arranging a new window. Do not present rescheduling as a technical fix; assign corrections to owners and define the evidence needed to revisit the decision. To prepare RUN autonomy, include a procedure for locating the build, job runs, reports and installed revision. Explain how to investigate missing files, connectivity failures and reused results. Define the escalation owner for a contract discrepancy and who accepts functional behavior. To summarize the lesson, confirm four questions: which dependencies block promotion, what does green status mean, where did verification run, and which data do the results belong to? These questions help lead an English-language release meeting and turn a vague discussion into verifiable actions.

"""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))
IN PRACTICE

A triage release has a green build but fails its contract and detects only 70% of critical tickets.

Common pitfalls

Confusing textual order with dependency, green status with all tests passing and aggregate accuracy with critical detection.

Related topics: Software supply chain security · SLOs and operational validation · Data contracts and model observability

Take this idea with you

Promotion requires evidence tied to the version, agreed criteria and actual execution path.

Create account

Reference: Configuring the order of build steps · Current linked guide; edition date unconfirmed (2026-09-30 inspection)

Google Cloud is a trademark of Google LLC. bigsavant.com is an independent preparation platform and is not affiliated with, associated with, sponsored, authorised or endorsed by Google. Content and questions are original, are not official exam questions, and completing our tests does not award or guarantee any certification. Names are used only to identify the subject. All other trademarks belong to their respective owners.