qontract-reconcile 0.10.2.dev234__py3-none-any.whl → 0.10.2.dev236__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qontract-reconcile
3
- Version: 0.10.2.dev234
3
+ Version: 0.10.2.dev236
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Project-URL: homepage, https://github.com/app-sre/qontract-reconcile
6
6
  Project-URL: repository, https://github.com/app-sre/qontract-reconcile
@@ -76,7 +76,7 @@ reconcile/openshift_rolebindings.py,sha256=9mlJ2FjWUoH-rsjtasreA_hV-K5Z_YR00qR_R
76
76
  reconcile/openshift_routes.py,sha256=fXvuPSjcjVw1X3j2EQvUAdbOepmIFdKk-M3qP8QzPiw,1075
77
77
  reconcile/openshift_saas_deploy.py,sha256=T1dvb9zajisaJNjbnR6-AZHU-itscHtr4oCqLj8KCK0,13037
78
78
  reconcile/openshift_saas_deploy_change_tester.py,sha256=12uyBwaeMka1C3_pejmQPIBPAx2V1sJ4dJkScq-2e2M,8793
79
- reconcile/openshift_saas_deploy_trigger_base.py,sha256=ftG8vqXCfaMUrkl1QqbPjnRpnQAmMIGCG0IT-YWAG6U,14366
79
+ reconcile/openshift_saas_deploy_trigger_base.py,sha256=MDu_T7Cx27pmNPkGNFfETht9CaYeBzfe0lmnOAmZir0,14549
80
80
  reconcile/openshift_saas_deploy_trigger_cleaner.py,sha256=roLyVAVntaQptKaZbnN1LyLvCA8fyvqELfjU6M8xfeY,3511
81
81
  reconcile/openshift_saas_deploy_trigger_configs.py,sha256=eUejMGWuaQabZTLuvPLLvROfN5HOFyYZOpH4YEsiU_g,928
82
82
  reconcile/openshift_saas_deploy_trigger_images.py,sha256=iUsiBGJf-CyFw7tSLWo59rXmSvsVnN6TTaAObbsVpNg,936
@@ -218,7 +218,7 @@ reconcile/glitchtip_project_alerts/integration.py,sha256=d3PMy-mQSbSZdIGAVaZCA2U
218
218
  reconcile/glitchtip_project_dsn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
219
  reconcile/glitchtip_project_dsn/integration.py,sha256=2iugub-kHYkHNK33n0v9_TeWonuxCPah_VkoTPvaajE,8077
220
220
  reconcile/gql_definitions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
- reconcile/gql_definitions/introspection.json,sha256=wqSPBHoGwZXz8uFUEqmUFdV3MPjjo8m76EgnAhYbjzo,2353319
221
+ reconcile/gql_definitions/introspection.json,sha256=G1JM6YaRbTYyTEKTlx-UyrLT7reHtMY1vWqu3VhC74A,2339039
222
222
  reconcile/gql_definitions/acs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
223
223
  reconcile/gql_definitions/acs/acs_instances.py,sha256=L91WW9LbhJbBSrECqShQpFtjoBOsmNIYLRpMbx1io5o,2181
224
224
  reconcile/gql_definitions/acs/acs_policies.py,sha256=Ygpfl2-VkYLSlJvHgp_dJBfb66K_Rwfdfpsa18w1v1s,4338
@@ -754,8 +754,8 @@ reconcile/utils/runtime/runner.py,sha256=I30KRrX1UQbHc_Ir1cIZX3OfNSdoHKdnDSPAEB6
754
754
  reconcile/utils/runtime/sharding.py,sha256=r0ieUtNed7NvknSw6qQrCkKpVXE1shuHGnfFcnpA_k4,16142
755
755
  reconcile/utils/saasherder/__init__.py,sha256=3U8plqMAPRE1kjwZ5YnIsYsggTf4_gS7flRUEuXVBAs,343
756
756
  reconcile/utils/saasherder/interfaces.py,sha256=nbGVLiIXJvOtd5ZfKsP3bfrFbMpdQ02D0cTTM9rrED0,9286
757
- reconcile/utils/saasherder/models.py,sha256=MSKaC65_bXSxKvhCibRH5K1DNppLPbw5w7_6VrjCCFU,11018
758
- reconcile/utils/saasherder/saasherder.py,sha256=W9nmQyULr4Jx9VAMwFyhULbKo5WRP9nSieOnpO5UxKQ,90224
757
+ reconcile/utils/saasherder/models.py,sha256=qMYY3SBOEnQlaOqn3bQhV33LDIMLcPjWbtfU9Li8-f0,10986
758
+ reconcile/utils/saasherder/saasherder.py,sha256=BKbus6Rr1cCm7ITKSrvBBJzJnZcRzIofqYa69oX2aY8,91785
759
759
  reconcile/utils/terraform/__init__.py,sha256=zNbiyTWo35AT1sFTElL2j_AA0jJ_yWE_bfFn-nD2xik,250
760
760
  reconcile/utils/terraform/config.py,sha256=5UVrd563TMcvi4ooa5JvWVDW1I3bIWg484u79evfV_8,164
761
761
  reconcile/utils/terraform/config_client.py,sha256=gRL1rQ0AqvShei_rcGqC3HDYGskOFKE1nPrJyJE9yno,4676
@@ -801,7 +801,7 @@ tools/saas_promotion_state/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
801
801
  tools/saas_promotion_state/saas_promotion_state.py,sha256=UfwwRLS5Ya4_Nh1w5n1dvoYtchQvYE9yj1VANt2IKqI,3925
802
802
  tools/sre_checkpoints/__init__.py,sha256=CDaDaywJnmRCLyl_NCcvxi-Zc0hTi_3OdwKiFOyS39I,145
803
803
  tools/sre_checkpoints/util.py,sha256=zEDbGr18ZeHNQwW8pUsr2JRjuXIPz--WAGJxZo9sv_Y,894
804
- qontract_reconcile-0.10.2.dev234.dist-info/METADATA,sha256=iNMIf9DSOc-sdEsqs0SNiNRMJkJ8Oy3g5h-s8CwN9p8,24352
805
- qontract_reconcile-0.10.2.dev234.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
806
- qontract_reconcile-0.10.2.dev234.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
807
- qontract_reconcile-0.10.2.dev234.dist-info/RECORD,,
804
+ qontract_reconcile-0.10.2.dev236.dist-info/METADATA,sha256=ejXZhtaiN90tpRcr_EulEL0K7Vk6PvLWW4doeG_vi5Y,24352
805
+ qontract_reconcile-0.10.2.dev236.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
806
+ qontract_reconcile-0.10.2.dev236.dist-info/entry_points.txt,sha256=5i9l54La3vQrDLAdwDKQWC0iG4sV9RRfOb1BpvzOWLc,698
807
+ qontract_reconcile-0.10.2.dev236.dist-info/RECORD,,
@@ -726,57 +726,6 @@
726
726
  "isDeprecated": false,
727
727
  "deprecationReason": null
728
728
  },
729
- {
730
- "name": "cna_experimental_provisioners_v1",
731
- "description": null,
732
- "args": [
733
- {
734
- "name": "name",
735
- "description": null,
736
- "type": {
737
- "kind": "SCALAR",
738
- "name": "String",
739
- "ofType": null
740
- },
741
- "defaultValue": null
742
- },
743
- {
744
- "name": "path",
745
- "description": null,
746
- "type": {
747
- "kind": "SCALAR",
748
- "name": "String",
749
- "ofType": null
750
- },
751
- "defaultValue": null
752
- },
753
- {
754
- "name": "filter",
755
- "description": null,
756
- "type": {
757
- "kind": "SCALAR",
758
- "name": "JSON",
759
- "ofType": null
760
- },
761
- "defaultValue": null
762
- }
763
- ],
764
- "type": {
765
- "kind": "LIST",
766
- "name": null,
767
- "ofType": {
768
- "kind": "NON_NULL",
769
- "name": null,
770
- "ofType": {
771
- "kind": "OBJECT",
772
- "name": "CNAExperimentalProvisioner_v1",
773
- "ofType": null
774
- }
775
- }
776
- },
777
- "isDeprecated": false,
778
- "deprecationReason": null
779
- },
780
729
  {
781
730
  "name": "clusters_v1",
782
731
  "description": null,
@@ -10638,11 +10587,6 @@
10638
10587
  "kind": "OBJECT",
10639
10588
  "name": "GcpProject_v1",
10640
10589
  "ofType": null
10641
- },
10642
- {
10643
- "kind": "OBJECT",
10644
- "name": "CNAExperimentalProvisioner_v1",
10645
- "ofType": null
10646
10590
  }
10647
10591
  ]
10648
10592
  },
@@ -25411,11 +25355,6 @@
25411
25355
  "interfaces": null,
25412
25356
  "enumValues": null,
25413
25357
  "possibleTypes": [
25414
- {
25415
- "kind": "OBJECT",
25416
- "name": "NamespaceCNAsset_v1",
25417
- "ofType": null
25418
- },
25419
25358
  {
25420
25359
  "kind": "OBJECT",
25421
25360
  "name": "NamespaceTerraformProviderResourceAWS_v1",
@@ -28125,99 +28064,6 @@
28125
28064
  "enumValues": null,
28126
28065
  "possibleTypes": null
28127
28066
  },
28128
- {
28129
- "kind": "OBJECT",
28130
- "name": "CNAExperimentalProvisioner_v1",
28131
- "description": null,
28132
- "fields": [
28133
- {
28134
- "name": "schema",
28135
- "description": null,
28136
- "args": [],
28137
- "type": {
28138
- "kind": "NON_NULL",
28139
- "name": null,
28140
- "ofType": {
28141
- "kind": "SCALAR",
28142
- "name": "String",
28143
- "ofType": null
28144
- }
28145
- },
28146
- "isDeprecated": false,
28147
- "deprecationReason": null
28148
- },
28149
- {
28150
- "name": "path",
28151
- "description": null,
28152
- "args": [],
28153
- "type": {
28154
- "kind": "NON_NULL",
28155
- "name": null,
28156
- "ofType": {
28157
- "kind": "SCALAR",
28158
- "name": "String",
28159
- "ofType": null
28160
- }
28161
- },
28162
- "isDeprecated": false,
28163
- "deprecationReason": null
28164
- },
28165
- {
28166
- "name": "name",
28167
- "description": null,
28168
- "args": [],
28169
- "type": {
28170
- "kind": "NON_NULL",
28171
- "name": null,
28172
- "ofType": {
28173
- "kind": "SCALAR",
28174
- "name": "String",
28175
- "ofType": null
28176
- }
28177
- },
28178
- "isDeprecated": false,
28179
- "deprecationReason": null
28180
- },
28181
- {
28182
- "name": "description",
28183
- "description": null,
28184
- "args": [],
28185
- "type": {
28186
- "kind": "SCALAR",
28187
- "name": "String",
28188
- "ofType": null
28189
- },
28190
- "isDeprecated": false,
28191
- "deprecationReason": null
28192
- },
28193
- {
28194
- "name": "ocm",
28195
- "description": null,
28196
- "args": [],
28197
- "type": {
28198
- "kind": "NON_NULL",
28199
- "name": null,
28200
- "ofType": {
28201
- "kind": "OBJECT",
28202
- "name": "OpenShiftClusterManager_v1",
28203
- "ofType": null
28204
- }
28205
- },
28206
- "isDeprecated": false,
28207
- "deprecationReason": null
28208
- }
28209
- ],
28210
- "inputFields": null,
28211
- "interfaces": [
28212
- {
28213
- "kind": "INTERFACE",
28214
- "name": "ExternalResourcesProvisioner_v1",
28215
- "ofType": null
28216
- }
28217
- ],
28218
- "enumValues": null,
28219
- "possibleTypes": null
28220
- },
28221
28067
  {
28222
28068
  "kind": "OBJECT",
28223
28069
  "name": "VaultInstance_v1",
@@ -40028,185 +39874,6 @@
40028
39874
  "enumValues": null,
40029
39875
  "possibleTypes": null
40030
39876
  },
40031
- {
40032
- "kind": "OBJECT",
40033
- "name": "NamespaceCNAsset_v1",
40034
- "description": null,
40035
- "fields": [
40036
- {
40037
- "name": "provider",
40038
- "description": null,
40039
- "args": [],
40040
- "type": {
40041
- "kind": "NON_NULL",
40042
- "name": null,
40043
- "ofType": {
40044
- "kind": "SCALAR",
40045
- "name": "String",
40046
- "ofType": null
40047
- }
40048
- },
40049
- "isDeprecated": false,
40050
- "deprecationReason": null
40051
- },
40052
- {
40053
- "name": "provisioner",
40054
- "description": null,
40055
- "args": [],
40056
- "type": {
40057
- "kind": "NON_NULL",
40058
- "name": null,
40059
- "ofType": {
40060
- "kind": "OBJECT",
40061
- "name": "CNAExperimentalProvisioner_v1",
40062
- "ofType": null
40063
- }
40064
- },
40065
- "isDeprecated": false,
40066
- "deprecationReason": null
40067
- },
40068
- {
40069
- "name": "resources",
40070
- "description": null,
40071
- "args": [],
40072
- "type": {
40073
- "kind": "NON_NULL",
40074
- "name": null,
40075
- "ofType": {
40076
- "kind": "LIST",
40077
- "name": null,
40078
- "ofType": {
40079
- "kind": "NON_NULL",
40080
- "name": null,
40081
- "ofType": {
40082
- "kind": "INTERFACE",
40083
- "name": "CNAsset_v1",
40084
- "ofType": null
40085
- }
40086
- }
40087
- }
40088
- },
40089
- "isDeprecated": false,
40090
- "deprecationReason": null
40091
- }
40092
- ],
40093
- "inputFields": null,
40094
- "interfaces": [
40095
- {
40096
- "kind": "INTERFACE",
40097
- "name": "NamespaceExternalResource_v1",
40098
- "ofType": null
40099
- }
40100
- ],
40101
- "enumValues": null,
40102
- "possibleTypes": null
40103
- },
40104
- {
40105
- "kind": "INTERFACE",
40106
- "name": "CNAsset_v1",
40107
- "description": null,
40108
- "fields": [
40109
- {
40110
- "name": "provider",
40111
- "description": null,
40112
- "args": [],
40113
- "type": {
40114
- "kind": "NON_NULL",
40115
- "name": null,
40116
- "ofType": {
40117
- "kind": "SCALAR",
40118
- "name": "String",
40119
- "ofType": null
40120
- }
40121
- },
40122
- "isDeprecated": false,
40123
- "deprecationReason": null
40124
- }
40125
- ],
40126
- "inputFields": null,
40127
- "interfaces": null,
40128
- "enumValues": null,
40129
- "possibleTypes": [
40130
- {
40131
- "kind": "OBJECT",
40132
- "name": "CNANullAsset_v1",
40133
- "ofType": null
40134
- }
40135
- ]
40136
- },
40137
- {
40138
- "kind": "OBJECT",
40139
- "name": "CNANullAsset_v1",
40140
- "description": null,
40141
- "fields": [
40142
- {
40143
- "name": "provider",
40144
- "description": null,
40145
- "args": [],
40146
- "type": {
40147
- "kind": "NON_NULL",
40148
- "name": null,
40149
- "ofType": {
40150
- "kind": "SCALAR",
40151
- "name": "String",
40152
- "ofType": null
40153
- }
40154
- },
40155
- "isDeprecated": false,
40156
- "deprecationReason": null
40157
- },
40158
- {
40159
- "name": "identifier",
40160
- "description": null,
40161
- "args": [],
40162
- "type": {
40163
- "kind": "NON_NULL",
40164
- "name": null,
40165
- "ofType": {
40166
- "kind": "SCALAR",
40167
- "name": "String",
40168
- "ofType": null
40169
- }
40170
- },
40171
- "isDeprecated": false,
40172
- "deprecationReason": null
40173
- },
40174
- {
40175
- "name": "description",
40176
- "description": null,
40177
- "args": [],
40178
- "type": {
40179
- "kind": "SCALAR",
40180
- "name": "String",
40181
- "ofType": null
40182
- },
40183
- "isDeprecated": false,
40184
- "deprecationReason": null
40185
- },
40186
- {
40187
- "name": "addr_block",
40188
- "description": null,
40189
- "args": [],
40190
- "type": {
40191
- "kind": "SCALAR",
40192
- "name": "String",
40193
- "ofType": null
40194
- },
40195
- "isDeprecated": false,
40196
- "deprecationReason": null
40197
- }
40198
- ],
40199
- "inputFields": null,
40200
- "interfaces": [
40201
- {
40202
- "kind": "INTERFACE",
40203
- "name": "CNAsset_v1",
40204
- "ofType": null
40205
- }
40206
- ],
40207
- "enumValues": null,
40208
- "possibleTypes": null
40209
- },
40210
39877
  {
40211
39878
  "kind": "OBJECT",
40212
39879
  "name": "AWSAccountSharingOptionAMI_v1",
@@ -278,6 +278,7 @@ def _trigger_tekton(
278
278
  integration_version,
279
279
  saasherder.include_trigger_trace,
280
280
  spec.reason,
281
+ spec.target_ref,
281
282
  )
282
283
 
283
284
  error = False
@@ -334,6 +335,7 @@ def _construct_tekton_trigger_resource(
334
335
  integration_version: str,
335
336
  include_trigger_trace: bool,
336
337
  reason: str | None,
338
+ target_ref: str,
337
339
  ) -> tuple[OR, str]:
338
340
  """Construct a resource (PipelineRun) to trigger a deployment via Tekton.
339
341
 
@@ -348,6 +350,7 @@ def _construct_tekton_trigger_resource(
348
350
  integration_version (string): Version of calling integration
349
351
  include_trigger_trace (bool): Should include traces of the triggering integration and reason
350
352
  reason (string): The reason this trigger was created
353
+ target_ref (string): the ref of the target, can be a branch or a commit hash.
351
354
 
352
355
  Returns:
353
356
  OpenshiftResource: OpenShift resource to be applied
@@ -385,6 +388,7 @@ def _construct_tekton_trigger_resource(
385
388
  "labels": {
386
389
  "qontract.saas_file_name": saas_file_name,
387
390
  "qontract.env_name": env_name,
391
+ "qontract.target_ref": target_ref,
388
392
  },
389
393
  },
390
394
  "spec": {
@@ -53,7 +53,7 @@ class UpstreamJob:
53
53
  return self.__str__()
54
54
 
55
55
 
56
- @dataclass
56
+ @dataclass(frozen=True)
57
57
  class TriggerSpecBase:
58
58
  saas_file_name: str
59
59
  env_name: str
@@ -63,6 +63,8 @@ class TriggerSpecBase:
63
63
  cluster_name: str
64
64
  namespace_name: str
65
65
  state_content: Any
66
+ reason: str | None
67
+ target_ref: str
66
68
 
67
69
  @property
68
70
  def state_key(self) -> str:
@@ -76,13 +78,11 @@ class SLOKey:
76
78
  cluster_name: str
77
79
 
78
80
 
79
- @dataclass
81
+ @dataclass(frozen=True)
80
82
  class TriggerSpecConfig(TriggerSpecBase):
81
83
  resource_template_url: str
82
- target_ref: str
83
84
  slos: list[SLODocument] | None = None
84
85
  target_name: str | None = None
85
- reason: str | None = None
86
86
 
87
87
  @property
88
88
  def state_key(self) -> str:
@@ -108,10 +108,9 @@ class TriggerSpecConfig(TriggerSpecBase):
108
108
  ]
109
109
 
110
110
 
111
- @dataclass
111
+ @dataclass(frozen=True)
112
112
  class TriggerSpecMovingCommit(TriggerSpecBase):
113
113
  ref: str
114
- reason: str | None = None
115
114
 
116
115
  @property
117
116
  def state_key(self) -> str:
@@ -122,11 +121,10 @@ class TriggerSpecMovingCommit(TriggerSpecBase):
122
121
  return key
123
122
 
124
123
 
125
- @dataclass
124
+ @dataclass(frozen=True)
126
125
  class TriggerSpecUpstreamJob(TriggerSpecBase):
127
126
  instance_name: str
128
127
  job_name: str
129
- reason: str | None = None
130
128
 
131
129
  @property
132
130
  def state_key(self) -> str:
@@ -137,10 +135,9 @@ class TriggerSpecUpstreamJob(TriggerSpecBase):
137
135
  return key
138
136
 
139
137
 
140
- @dataclass
138
+ @dataclass(frozen=True)
141
139
  class TriggerSpecContainerImage(TriggerSpecBase):
142
140
  images: Sequence[str]
143
- reason: str | None = None
144
141
 
145
142
  @property
146
143
  def state_key(self) -> str:
@@ -1278,6 +1278,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1278
1278
  resource_template_url=rt.url,
1279
1279
  target_ref=target.ref,
1280
1280
  state_content=None,
1281
+ reason=None,
1281
1282
  ).state_key
1282
1283
  digest = SaasHerder.get_target_config_hash(
1283
1284
  all_trigger_specs[state_key].state_content
@@ -1432,6 +1433,15 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1432
1433
  )
1433
1434
  return list(itertools.chain.from_iterable(results))
1434
1435
 
1436
+ def _build_trigger_spec_moving_commit_reason(
1437
+ self,
1438
+ url: str,
1439
+ desired_commit_sha: str,
1440
+ ) -> str | None:
1441
+ if not self.include_trigger_trace:
1442
+ return None
1443
+ return f"{url}/commit/{desired_commit_sha}"
1444
+
1435
1445
  def get_moving_commits_diff_saas_file(
1436
1446
  self, saas_file: SaasFile, dry_run: bool
1437
1447
  ) -> list[TriggerSpecMovingCommit]:
@@ -1461,9 +1471,12 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1461
1471
  namespace_name=target.namespace.name,
1462
1472
  ref=target.ref,
1463
1473
  state_content=desired_commit_sha,
1474
+ reason=self._build_trigger_spec_moving_commit_reason(
1475
+ url=rt.url,
1476
+ desired_commit_sha=desired_commit_sha,
1477
+ ),
1478
+ target_ref=desired_commit_sha,
1464
1479
  )
1465
- if self.include_trigger_trace:
1466
- trigger_spec.reason = f"{rt.url}/commit/{desired_commit_sha}"
1467
1480
 
1468
1481
  if not self.state:
1469
1482
  raise Exception("state is not initialized")
@@ -1519,6 +1532,24 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1519
1532
 
1520
1533
  return current_state, error
1521
1534
 
1535
+ def _build_trigger_spec_upstream_job_reason(
1536
+ self,
1537
+ last_build_result: Any,
1538
+ server_url: str,
1539
+ job_name: str,
1540
+ url: str,
1541
+ ) -> str | None:
1542
+ if not self.include_trigger_trace:
1543
+ return None
1544
+ last_build_result_number = last_build_result["number"]
1545
+ last_build_result_commit_sha = last_build_result.get("commit_sha")
1546
+ prefix = (
1547
+ f"{url}/commit/{last_build_result_commit_sha} via "
1548
+ if last_build_result_commit_sha
1549
+ else ""
1550
+ )
1551
+ return f"{prefix}{server_url}/job/{job_name}/{last_build_result_number}"
1552
+
1522
1553
  def get_upstream_jobs_diff_saas_file(
1523
1554
  self, saas_file: SaasFile, dry_run: bool, current_state: dict[str, Any]
1524
1555
  ) -> list[TriggerSpecUpstreamJob]:
@@ -1546,16 +1577,14 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1546
1577
  instance_name=target.upstream.instance.name,
1547
1578
  job_name=job_name,
1548
1579
  state_content=last_build_result,
1580
+ reason=self._build_trigger_spec_upstream_job_reason(
1581
+ last_build_result=last_build_result,
1582
+ server_url=target.upstream.instance.server_url,
1583
+ job_name=job_name,
1584
+ url=rt.url,
1585
+ ),
1586
+ target_ref=last_build_result.get("commit_sha") or target.ref,
1549
1587
  )
1550
- last_build_result_number = last_build_result["number"]
1551
- if self.include_trigger_trace:
1552
- trigger_spec.reason = f"{target.upstream.instance.server_url}/job/{job_name}/{last_build_result_number}"
1553
- last_build_result_commit_sha = last_build_result.get("commit_sha")
1554
- if last_build_result_commit_sha:
1555
- trigger_spec.reason = (
1556
- f"{rt.url}/commit/{last_build_result_commit_sha} via "
1557
- + trigger_spec.reason
1558
- )
1559
1588
  if not self.state:
1560
1589
  raise Exception("state is not initialized")
1561
1590
  state_build_result = self.state.get(trigger_spec.state_key, None)
@@ -1576,6 +1605,7 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1576
1605
  self.update_state(trigger_spec)
1577
1606
  continue
1578
1607
 
1608
+ last_build_result_number = last_build_result["number"]
1579
1609
  state_build_result_number = state_build_result["number"]
1580
1610
  # this is the most important condition
1581
1611
  # if there is a successful newer build -
@@ -1609,6 +1639,20 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1609
1639
  )
1610
1640
  return list(itertools.chain.from_iterable(results))
1611
1641
 
1642
+ def _build_trigger_spec_container_image_reason(
1643
+ self,
1644
+ desired_image_tag: str,
1645
+ image_registries: list[str],
1646
+ url: str,
1647
+ commit_sha: str,
1648
+ ) -> str | None:
1649
+ if not self.include_trigger_trace:
1650
+ return None
1651
+ image_uris = ", ".join(
1652
+ f"{image}:{desired_image_tag}" for image in sorted(image_registries)
1653
+ )
1654
+ return f"{url}/commit/{commit_sha} build {image_uris}"
1655
+
1612
1656
  def get_container_images_diff_saas_file(
1613
1657
  self, saas_file: SaasFile, dry_run: bool
1614
1658
  ) -> list[TriggerSpecContainerImage]:
@@ -1657,15 +1701,14 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1657
1701
  namespace_name=target.namespace.name,
1658
1702
  images=image_registries,
1659
1703
  state_content=desired_image_tag,
1704
+ reason=self._build_trigger_spec_container_image_reason(
1705
+ desired_image_tag=desired_image_tag,
1706
+ image_registries=image_registries,
1707
+ url=rt.url,
1708
+ commit_sha=commit_sha,
1709
+ ),
1710
+ target_ref=commit_sha,
1660
1711
  )
1661
- if self.include_trigger_trace:
1662
- image_uris = ", ".join(
1663
- f"{image}:{desired_image_tag}"
1664
- for image in sorted(image_registries)
1665
- )
1666
- trigger_spec.reason = (
1667
- f"{rt.url}/commit/{commit_sha} build {image_uris}"
1668
- )
1669
1712
  if not self.state:
1670
1713
  raise Exception("state is not initialized")
1671
1714
  current_image_tag = self.state.get(trigger_spec.state_key, None)
@@ -1804,15 +1847,6 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1804
1847
  dtc = SaasHerder.remove_none_values(trigger_spec.state_content)
1805
1848
  if ctc == dtc:
1806
1849
  continue
1807
- if self.include_trigger_trace:
1808
- trigger_spec.reason = f"{self.repo_url}/commit/{RunningState().commit}"
1809
- # For now we count every saas config change as an auto-promotion
1810
- # if the auto promotion field is enabled in the saas target.
1811
- # Ideally, we check if there was an actual ref change in order
1812
- # to reduce false-positives.
1813
- promotion = trigger_spec.state_content.get("promotion")
1814
- if promotion and promotion.get("auto", False):
1815
- trigger_spec.reason += " [auto-promotion]"
1816
1850
  trigger_specs.append(trigger_spec)
1817
1851
  return trigger_specs
1818
1852
 
@@ -1823,6 +1857,23 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1823
1857
  digest = m.hexdigest()[:16]
1824
1858
  return digest
1825
1859
 
1860
+ def _build_trigger_spec_config_reason(
1861
+ self,
1862
+ state_content: dict,
1863
+ ) -> str | None:
1864
+ if not self.include_trigger_trace:
1865
+ return None
1866
+ # For now we count every saas config change as an auto-promotion
1867
+ # if the auto promotion field is enabled in the saas target.
1868
+ # Ideally, we check if there was an actual ref change in order
1869
+ # to reduce false-positives.
1870
+ auto_promotion_suffix = (
1871
+ " [auto-promotion]"
1872
+ if state_content.get("promotion", {}).get("auto", False)
1873
+ else ""
1874
+ )
1875
+ return f"{self.repo_url}/commit/{RunningState().commit}{auto_promotion_suffix}"
1876
+
1826
1877
  def get_saas_targets_config_trigger_specs(
1827
1878
  self, saas_file: SaasFile
1828
1879
  ) -> dict[str, TriggerSpecConfig]:
@@ -1901,6 +1952,9 @@ class SaasHerder: # pylint: disable=too-many-public-methods
1901
1952
  resource_template_url=rt.url,
1902
1953
  target_ref=target.ref,
1903
1954
  slos=target.slos or None,
1955
+ reason=self._build_trigger_spec_config_reason(
1956
+ state_content=serializable_target_config
1957
+ ),
1904
1958
  )
1905
1959
  configs[trigger_spec.state_key] = trigger_spec
1906
1960