What happened:
When a pipeline's repository is migrated from one SCM to another (e.g. a GitHub Enterprise Server → GitHub Enterprise Cloud migration, or any change of SCM host/context), the pipeline record can end up partially updated:
scmRepo (and name) reflect the new SCM
scmUri and scmContext still point at the old SCM
The pipeline then becomes unusable — starting jobs and "Sync pipeline" fail — because the stored scmUri/scmContext no longer resolve to a valid repo. It happens intermittently, not on every migration.
Root cause:
Pipeline.update() (in screwdriver-models) re-derives scmRepo/name from (scmUri, scmContext) via scm.decorateUrl on every update. BaseModel.update() only persists dirty fields. scmContext is always dirty (it is set through the setter in the PipelineModel constructor), but scmUri is dirty only when it is explicitly reassigned. As a result, an update can persist a freshly-derived scmRepo without persisting a matching scmUri, allowing the SCM identity fields to drift out of sync at the database level.
What you expected to happen:
scmUri, scmContext, scmRepo, and name together describe a single SCM identity. They should always be persisted together and remain mutually consistent, so a migration can never leave a pipeline half-updated.
How to reproduce it:
- Have an active pipeline whose repository is then migrated to a different SCM host/context (so the underlying repo metadata resolves to the new SCM).
- Trigger a pipeline update (e.g. a webhook, event, or sync) so
Pipeline.update() runs.
- Inspect the pipeline row:
scmRepo reflects the new SCM while scmUri/scmContext still reference the old one.
Fix:
screwdriver-cd/models#674 — persist the full SCM identity unit (scmUri, scmContext, scmRepo, name) atomically in Pipeline.update().
What happened:
When a pipeline's repository is migrated from one SCM to another (e.g. a GitHub Enterprise Server → GitHub Enterprise Cloud migration, or any change of SCM host/context), the pipeline record can end up partially updated:
scmRepo(andname) reflect the new SCMscmUriandscmContextstill point at the old SCMThe pipeline then becomes unusable — starting jobs and "Sync pipeline" fail — because the stored
scmUri/scmContextno longer resolve to a valid repo. It happens intermittently, not on every migration.Root cause:
Pipeline.update()(inscrewdriver-models) re-derivesscmRepo/namefrom(scmUri, scmContext)viascm.decorateUrlon every update.BaseModel.update()only persists dirty fields.scmContextis always dirty (it is set through the setter in thePipelineModelconstructor), butscmUriis dirty only when it is explicitly reassigned. As a result, an update can persist a freshly-derivedscmRepowithout persisting a matchingscmUri, allowing the SCM identity fields to drift out of sync at the database level.What you expected to happen:
scmUri,scmContext,scmRepo, andnametogether describe a single SCM identity. They should always be persisted together and remain mutually consistent, so a migration can never leave a pipeline half-updated.How to reproduce it:
Pipeline.update()runs.scmReporeflects the new SCM whilescmUri/scmContextstill reference the old one.Fix:
screwdriver-cd/models#674 — persist the full SCM identity unit (
scmUri,scmContext,scmRepo,name) atomically inPipeline.update().