CI/CD / Integration and candidate foundations / Lesson 3
Source events and the revision under test
Keep event identity, checkout identity, and release eligibility connected.
On this page
Lesson goals
- Distinguish branch, merge-result, tag, and scheduled checks.
- Build a trigger decision table without enabling a workflow.
An event and a revision are different facts
A source event explains why a pipeline exists; a revision explains which bytes it checks. A branch push can create a run, while a merge-request pipeline may test the source branch or a synthesized merged result depending on platform configuration. Record both. Parcel’s release notes saying tested main are ambiguous if main advanced after checkout. An immutable revision identifier and the event context let a reviewer distinguish a new commit, a rerun of an old commit, and a test of a prospective merge.
Write trigger behavior as a table
Consider four event classes: untrusted change proposal, protected integration push, release tag, and schedule. Proposals need fast tests without release privileges. Integration pushes produce candidates after required checks. Tags may select an already built candidate only if the tag-to-revision relationship is verified. Schedules can detect dependency drift without representing a new release request. These distinctions prevent duplicate pipelines and accidental privilege escalation. A broad trigger is not automatically dangerous, but combining broad triggering with privileged execution demands a precise trust review.
proposal -> test, no release authority
integration -> test and candidate
release tag -> verify candidate relationship
schedule -> drift checks, no implicit release
This is a design table, not executable CI configuration. Branch protection, tag permissions, and event payload semantics must be checked in the chosen platform before translating it into rules.
Test the combination that matters
A passing source branch does not prove compatibility with a target branch that changed meanwhile. Merged-result pipelines or merge queues can test a combined state and reduce that gap, but support and exact behavior vary by platform and subscription. Even then, runtime configuration and dependency inputs remain outside the source merge unless captured separately. Decide what must be revalidated when the target advances. Do not attach an old successful status to a newer revision merely to avoid queue time.
Separate eligibility from execution
An event can be eligible for tests but ineligible for release. The following complete model requires a protected integration event and successful evidence. The trusted boolean is declared input, not something that should be accepted from an arbitrary contributor-controlled file. Real systems derive trust from the platform and repository policy. Keeping this predicate small makes it easier to review negative cases, including a release-looking branch name in a fork or a scheduled run on an old revision.
def eligible(event, protected, checks):
return event == "integration" and protected and checks
for event, protected in [("proposal", False), ("integration", True), ("schedule", True)]:
print(event, eligible(event, protected, True))
proposal False
integration True
schedule False
The model performs no checkout and grants no permissions. A real platform must supply verified event and protection information rather than trusting user input.
Avoid duplicate work without losing required checks
A push to a branch with an open proposal can trigger both push and proposal pipelines. Running both may consume capacity and publish confusing duplicate statuses. Decide which event owns each check, then ensure required status names still appear for every merge path. Path filters also need care: a change to a shared compiler setting can affect code outside the edited directory. A skipped pipeline should not leave a required check waiting forever or permit untested shared configuration changes.
Common errors and fixes
The release tag points to an untested revision.
- Why it happens
- A human-readable tag name was accepted without resolving its target.
- How to fix it
- Resolve the tag and match it to candidate evidence before promotion.
- Prevent it next time
- Require explicit revision and artifact relationships in release records.
Two pipelines report conflicting results for one proposal.
- Why it happens
- Both push and proposal triggers own the same status.
- How to fix it
- Define event ownership and stable required status names.
- Prevent it next time
- Review the complete event matrix, including open-proposal pushes.
A path filter skips tests after a shared build change.
- Why it happens
- The filter models file location instead of dependency impact.
- How to fix it
- Include shared inputs or conservatively run affected tests.
- Prevent it next time
- Maintain dependency-aware filter reviews and negative examples.
Check your understanding
1. A scheduled check finds dependency drift but source has not changed. Should it automatically release?
Show worked solution
Not under the declared table. The schedule reports new evidence about mutable external inputs. A reviewed change should update the dependency record, produce a candidate, and pass the normal release contract rather than smuggling a release through a maintenance trigger.
2. A proposal passes, then main changes before merging. What evidence is missing?
Show worked solution
Evidence that the proposed change works with the new target state is missing. Revalidate the combined revision through the platform’s supported merge-result or queue mechanism, or another documented integration check. Preserve both source and tested-combination identities.
Key takeaways
- Record why a run exists and exactly what it checked.
- Trigger rules and release privileges require separate review.