qontract-reconcile 0.10.1rc921__py3-none-any.whl → 0.10.1rc923__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.1
2
2
  Name: qontract-reconcile
3
- Version: 0.10.1rc921
3
+ Version: 0.10.1rc923
4
4
  Summary: Collection of tools to reconcile services with their desired state as defined in the app-interface DB.
5
5
  Home-page: https://github.com/app-sre/qontract-reconcile
6
6
  Author: Red Hat App-SRE Team
@@ -366,8 +366,8 @@ reconcile/gql_definitions/status_board/status_board.py,sha256=vHEzncabujkqbjJ-ib
366
366
  reconcile/gql_definitions/statuspage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
367
367
  reconcile/gql_definitions/statuspage/statuspages.py,sha256=CTRzjiR9k41LqlkgyoNHwC2JERsoD_Run_aK7jw_Ono,5299
368
368
  reconcile/gql_definitions/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
369
- reconcile/gql_definitions/templating/template_collection.py,sha256=GiCtqtTj8602ppCatuF9HhQkHXDOd76Z9CSJQ1KwBuc,3532
370
- reconcile/gql_definitions/templating/templates.py,sha256=ejAvQ13zfNMQTz3FWtRUic6dSvio3aAgBKEqt600hbk,2821
369
+ reconcile/gql_definitions/templating/template_collection.py,sha256=QA68QNszPgJY996pPPJmdTULI1gjcT8MDvk1NLKi6_Y,4017
370
+ reconcile/gql_definitions/templating/templates.py,sha256=bV1JWwxDW8opARBOrZ_h5NBsJfM-9aL-povmTZnpTOk,3296
371
371
  reconcile/gql_definitions/terraform_cloudflare_dns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
372
372
  reconcile/gql_definitions/terraform_cloudflare_dns/app_interface_cloudflare_dns_settings.py,sha256=eyGX9HcTF6MZbOYZ6Kl6Mg3k6nJTUtwqs9gDxBP_8Dk,1920
373
373
  reconcile/gql_definitions/terraform_cloudflare_dns/terraform_cloudflare_zones.py,sha256=dBQ2tyAp-eRZs59mguaTc6-x67JUoSxtZ8mOjbRqDuc,5832
@@ -463,12 +463,12 @@ reconcile/templates/jira-checkpoint-missinginfo.j2,sha256=c_Vvg-lEENsB3tgxm9B6Y9
463
463
  reconcile/templates/rosa-classic-cluster-creation.sh.j2,sha256=FVBmnR2FmVModhqOYNBInhF8zk0Qnj9og9KHK5-X9v0,2361
464
464
  reconcile/templates/rosa-hcp-cluster-creation.sh.j2,sha256=2wTdv9qvapCvT8NSi_hq8sXhpFSaxRX-V6Cao1diCI8,2393
465
465
  reconcile/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
466
- reconcile/templating/renderer.py,sha256=VQVsQxMjKfftpsgzpd1jJ-bhrsgi8zjDYXYzMfI4vZA,12104
467
- reconcile/templating/validator.py,sha256=tGI7PwPMAmRJ_-Gg_O7NoZO8ytg_QUeCQAv6G1smitc,4736
466
+ reconcile/templating/renderer.py,sha256=oUUiHHSgD5bcUN3Xf-yoEezAf3LjqN-2GlYhQUTPIZY,13067
467
+ reconcile/templating/validator.py,sha256=5f9f35PCHOOdjb7KZquL2YdabyuAUokPDa4xutSEHIQ,5360
468
468
  reconcile/templating/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
469
469
  reconcile/templating/lib/merge_request_manager.py,sha256=4oe3EwQOP7CZSraocivbRzzOuVb0ooElaUS2_DGsF50,5603
470
470
  reconcile/templating/lib/model.py,sha256=fb6FYYLQjmoh2DjVKO7TEWCuDPf1Q34xmOx0M9Z07ek,324
471
- reconcile/templating/lib/rendering.py,sha256=ShYt_BOMS75yiJ7lNcI9NoZyQp5wpy_lEmzVETY57dE,5030
471
+ reconcile/templating/lib/rendering.py,sha256=6kt8NCCwB4vLKYal7KtRmBDguIC1p_PIQCRr-vL7p5w,5504
472
472
  reconcile/terraform_init/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
473
473
  reconcile/terraform_init/integration.py,sha256=glQ9uy8Kj2aTQXCAupwSFeih7reX_xMX_UuWW_ywBMU,6100
474
474
  reconcile/terraform_init/merge_request.py,sha256=3CYtgSd7Q9zjKg4wsDz437EPCRfGeZZ8fZ0Y-ChKXJY,1475
@@ -667,7 +667,7 @@ reconcile/utils/imap_client.py,sha256=PMsX8UjJ2F59fXbbqREjLVdapYWznYTB8svFmpt39q
667
667
  reconcile/utils/instrumented_wrappers.py,sha256=eVwMoa6FCrYxLv3RML3WpZF9qKVfCTjMxphgVXG03OM,1073
668
668
  reconcile/utils/jenkins_api.py,sha256=RaKuZmO7_lbI-hE6c_Pq2a6CQdmBVj7BcP2jR68cIbI,7081
669
669
  reconcile/utils/jira_client.py,sha256=VdWJfI9VAK2ZtYHmvuqL635t0S5eYtmBY6zR8R-qr-s,7775
670
- reconcile/utils/jjb_client.py,sha256=Bdxk18lWxxZVMM1hTqTpe0JZ6uj8eqpfoQiFhLHEPy8,14501
670
+ reconcile/utils/jjb_client.py,sha256=9Aw4SfV4pBNW5Kj7dGZwakUlwsWuqtAAiSD9o1F4AZA,14524
671
671
  reconcile/utils/jsonpath.py,sha256=wdxOMqR-GMpQf5vRPWRMqAF7bCiXDBkkcFfY2U4j_tk,5536
672
672
  reconcile/utils/jump_host.py,sha256=W3w0S-Qa-VLK5JGg-G4f2a4_5GA34KZVV3XNAaI53Y4,5148
673
673
  reconcile/utils/keycloak.py,sha256=YWSEUGrOVqFaJUk055dKUWpLDPdDRvhcmvR-lfbmxdE,3388
@@ -741,7 +741,7 @@ reconcile/utils/internal_groups/models.py,sha256=y_IqBVqfGqNXiu0VudvBWFrm_-uafVm
741
741
  reconcile/utils/jinja2/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
742
742
  reconcile/utils/jinja2/extensions.py,sha256=7K-uo6G2eCWa98MHT8fRPYIKCLQB_5D2keqQ_LyAfHM,1293
743
743
  reconcile/utils/jinja2/filters.py,sha256=RVVkpf87FllrPUpqk_8KN-r1IsmnS0bpygAVvsvIr5g,4504
744
- reconcile/utils/jinja2/utils.py,sha256=BOqB17nFKzzdC13hqOebd-IDcstjkvmlyQJJGNaMbxM,6723
744
+ reconcile/utils/jinja2/utils.py,sha256=nyTS7SafbjQliIg0PZhqK0YGfFL0W2V6XA5CRaqOkrA,7809
745
745
  reconcile/utils/jobcontroller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
746
746
  reconcile/utils/jobcontroller/controller.py,sha256=2V_vm5thFx6adW4bMy9CdHXFesuo6S4lSkEpGxkXSM0,14492
747
747
  reconcile/utils/jobcontroller/models.py,sha256=tSRAkUX23iyn4YPsWEicFXwRxw3mXb5B2pDOWmXX8wQ,6350
@@ -844,8 +844,8 @@ tools/test/test_qontract_cli.py,sha256=_D61RFGAN5x44CY1tYbouhlGXXABwYfxKSWSQx3Jr
844
844
  tools/test/test_saas_promotion_state.py,sha256=dy4kkSSAQ7bC0Xp2CociETGN-2aABEfL6FU5D9Jl00Y,6056
845
845
  tools/test/test_sd_app_sre_alert_report.py,sha256=v363r9zM7__0kR5K6mvJoGFcM9BvE33fWAayrqkpojA,2116
846
846
  tools/test/test_sre_checkpoints.py,sha256=SKqPPTl9ua0RFdSSofnoQX-JZE6dFLO3LRhfQzqtfh8,2607
847
- qontract_reconcile-0.10.1rc921.dist-info/METADATA,sha256=SpNBTIDWOYtsmjJ-o-tNFYFAzDMWgKbggJxyukAXWng,2273
848
- qontract_reconcile-0.10.1rc921.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
849
- qontract_reconcile-0.10.1rc921.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
850
- qontract_reconcile-0.10.1rc921.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
851
- qontract_reconcile-0.10.1rc921.dist-info/RECORD,,
847
+ qontract_reconcile-0.10.1rc923.dist-info/METADATA,sha256=OjR8Y-8f7JvaPxAt_N-8baMq5aI7LwcbOL2Cirs809I,2273
848
+ qontract_reconcile-0.10.1rc923.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
849
+ qontract_reconcile-0.10.1rc923.dist-info/entry_points.txt,sha256=GKQqCl2j2X1BJQ69een6rHcR26PmnxnONLNOQB-nRjY,491
850
+ qontract_reconcile-0.10.1rc923.dist-info/top_level.txt,sha256=l5ISPoXzt0SdR4jVdkfa7RPSKNc8zAHYWAnR-Dw8Ey8,24
851
+ qontract_reconcile-0.10.1rc923.dist-info/RECORD,,
@@ -45,6 +45,11 @@ query TemplateCollection_v1 {
45
45
  identifier
46
46
  }
47
47
  template
48
+ templateRenderOptions {
49
+ trimBlocks
50
+ lstripBlocks
51
+ keepTrailingNewline
52
+ }
48
53
  }
49
54
  }
50
55
  }
@@ -76,6 +81,12 @@ class TemplatePatchV1(ConfiguredBaseModel):
76
81
  identifier: Optional[str] = Field(..., alias="identifier")
77
82
 
78
83
 
84
+ class TemplateRenderOptionsV1(ConfiguredBaseModel):
85
+ trim_blocks: Optional[bool] = Field(..., alias="trimBlocks")
86
+ lstrip_blocks: Optional[bool] = Field(..., alias="lstripBlocks")
87
+ keep_trailing_newline: Optional[bool] = Field(..., alias="keepTrailingNewline")
88
+
89
+
79
90
  class TemplateV1(ConfiguredBaseModel):
80
91
  name: str = Field(..., alias="name")
81
92
  auto_approved: Optional[bool] = Field(..., alias="autoApproved")
@@ -83,6 +94,7 @@ class TemplateV1(ConfiguredBaseModel):
83
94
  target_path: str = Field(..., alias="targetPath")
84
95
  patch: Optional[TemplatePatchV1] = Field(..., alias="patch")
85
96
  template: str = Field(..., alias="template")
97
+ template_render_options: Optional[TemplateRenderOptionsV1] = Field(..., alias="templateRenderOptions")
86
98
 
87
99
 
88
100
  class TemplateCollectionV1(ConfiguredBaseModel):
@@ -38,6 +38,11 @@ query Templatev1 {
38
38
  expectedTargetPath
39
39
  expectedToRender
40
40
  }
41
+ templateRenderOptions {
42
+ trimBlocks
43
+ lstripBlocks
44
+ keepTrailingNewline
45
+ }
41
46
  }
42
47
  }
43
48
  """
@@ -63,6 +68,12 @@ class TemplateTestV1(ConfiguredBaseModel):
63
68
  expected_to_render: Optional[bool] = Field(..., alias="expectedToRender")
64
69
 
65
70
 
71
+ class TemplateRenderOptionsV1(ConfiguredBaseModel):
72
+ trim_blocks: Optional[bool] = Field(..., alias="trimBlocks")
73
+ lstrip_blocks: Optional[bool] = Field(..., alias="lstripBlocks")
74
+ keep_trailing_newline: Optional[bool] = Field(..., alias="keepTrailingNewline")
75
+
76
+
66
77
  class TemplateV1(ConfiguredBaseModel):
67
78
  name: str = Field(..., alias="name")
68
79
  auto_approved: Optional[bool] = Field(..., alias="autoApproved")
@@ -71,6 +82,7 @@ class TemplateV1(ConfiguredBaseModel):
71
82
  target_path: str = Field(..., alias="targetPath")
72
83
  template: str = Field(..., alias="template")
73
84
  template_test: list[TemplateTestV1] = Field(..., alias="templateTest")
85
+ template_render_options: Optional[TemplateRenderOptionsV1] = Field(..., alias="templateRenderOptions")
74
86
 
75
87
 
76
88
  class Templatev1QueryData(ConfiguredBaseModel):
@@ -5,7 +5,11 @@ from typing import Any, Protocol
5
5
 
6
6
  from pydantic import BaseModel
7
7
 
8
- from reconcile.utils.jinja2.utils import Jinja2TemplateError, process_jinja2_template
8
+ from reconcile.utils.jinja2.utils import (
9
+ Jinja2TemplateError,
10
+ TemplateRenderOptions,
11
+ process_jinja2_template,
12
+ )
9
13
  from reconcile.utils.jsonpath import parse_jsonpath
10
14
  from reconcile.utils.ruamel import create_ruamel_instance
11
15
  from reconcile.utils.secret_reader import SecretReaderBase
@@ -43,11 +47,13 @@ class Renderer(ABC):
43
47
  template: Template,
44
48
  data: TemplateData,
45
49
  secret_reader: SecretReaderBase | None = None,
50
+ template_render_options: TemplateRenderOptions | None = None,
46
51
  ):
47
52
  self.template = template
48
53
  self.data = data
49
54
  self.secret_reader = secret_reader
50
55
  self.ruamel_instance = create_ruamel_instance(explicit_start=True)
56
+ self.template_render_options = template_render_options
51
57
 
52
58
  def _jinja2_render_kwargs(self) -> dict[str, Any]:
53
59
  return {**self.data.variables, "current": self.data.current}
@@ -58,6 +64,7 @@ class Renderer(ABC):
58
64
  body=template,
59
65
  vars=self._jinja2_render_kwargs(),
60
66
  secret_reader=self.secret_reader,
67
+ template_render_options=self.template_render_options,
61
68
  )
62
69
  except Jinja2TemplateError as e:
63
70
  logging.error(f"Error rendering template {self.template.name}: {e}")
@@ -150,11 +157,18 @@ def create_renderer(
150
157
  template: Template,
151
158
  data: TemplateData,
152
159
  secret_reader: SecretReaderBase | None = None,
160
+ template_render_options: TemplateRenderOptions | None = None,
153
161
  ) -> Renderer:
154
162
  if template.patch:
155
- return PatchRenderer(template=template, data=data, secret_reader=secret_reader)
163
+ return PatchRenderer(
164
+ template=template,
165
+ data=data,
166
+ secret_reader=secret_reader,
167
+ template_render_options=template_render_options,
168
+ )
156
169
  return FullRenderer(
157
170
  template=template,
158
171
  data=data,
159
172
  secret_reader=secret_reader,
173
+ template_render_options=template_render_options,
160
174
  )
@@ -23,6 +23,7 @@ from reconcile.templating.lib.merge_request_manager import (
23
23
  )
24
24
  from reconcile.templating.lib.model import TemplateInput, TemplateOutput
25
25
  from reconcile.templating.lib.rendering import (
26
+ Renderer,
26
27
  TemplateData,
27
28
  create_renderer,
28
29
  )
@@ -32,12 +33,13 @@ from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
32
33
  from reconcile.utils import gql
33
34
  from reconcile.utils.git import clone
34
35
  from reconcile.utils.gql import GqlApi, init_from_config
35
- from reconcile.utils.jinja2.utils import process_jinja2_template
36
+ from reconcile.utils.jinja2.utils import TemplateRenderOptions, process_jinja2_template
36
37
  from reconcile.utils.ruamel import create_ruamel_instance
37
38
  from reconcile.utils.runtime.integration import (
38
39
  PydanticRunParams,
39
40
  QontractReconcileIntegration,
40
41
  )
42
+ from reconcile.utils.secret_reader import SecretReaderBase
41
43
  from reconcile.utils.vcs import VCS
42
44
 
43
45
  QONTRACT_INTEGRATION = "template-renderer"
@@ -207,6 +209,31 @@ class TemplateRendererIntegration(QontractReconcileIntegration):
207
209
  def __init__(self, params: TemplateRendererIntegrationParams) -> None:
208
210
  super().__init__(params)
209
211
 
212
+ @staticmethod
213
+ def _create_renderer(
214
+ template: TemplateV1,
215
+ variables: dict,
216
+ secret_reader: SecretReaderBase | None = None,
217
+ ) -> Renderer:
218
+ return create_renderer(
219
+ template,
220
+ TemplateData(
221
+ variables=variables,
222
+ ),
223
+ secret_reader=secret_reader,
224
+ template_render_options=TemplateRenderOptions.create(
225
+ trim_blocks=template.template_render_options.trim_blocks
226
+ if template.template_render_options
227
+ else None,
228
+ lstrip_blocks=template.template_render_options.lstrip_blocks
229
+ if template.template_render_options
230
+ else None,
231
+ keep_trailing_newline=template.template_render_options.keep_trailing_newline
232
+ if template.template_render_options
233
+ else None,
234
+ ),
235
+ )
236
+
210
237
  def process_template(
211
238
  self,
212
239
  template: TemplateV1,
@@ -215,12 +242,8 @@ class TemplateRendererIntegration(QontractReconcileIntegration):
215
242
  ruaml_instance: yaml.YAML,
216
243
  template_input: TemplateInput,
217
244
  ) -> TemplateOutput | None:
218
- r = create_renderer(
219
- template,
220
- TemplateData(
221
- variables=variables,
222
- ),
223
- secret_reader=self.secret_reader,
245
+ r = TemplateRendererIntegration._create_renderer(
246
+ template, variables, secret_reader=self.secret_reader
224
247
  )
225
248
  target_path = r.render_target_path()
226
249
 
@@ -12,6 +12,7 @@ from reconcile.gql_definitions.templating.templates import (
12
12
  )
13
13
  from reconcile.templating.lib.rendering import Renderer, TemplateData, create_renderer
14
14
  from reconcile.utils import gql
15
+ from reconcile.utils.jinja2.utils import TemplateRenderOptions
15
16
  from reconcile.utils.ruamel import create_ruamel_instance
16
17
  from reconcile.utils.runtime.integration import (
17
18
  QontractReconcileIntegration,
@@ -50,6 +51,17 @@ class TemplateValidatorIntegration(QontractReconcileIntegration):
50
51
  current=ruaml_instance.load(template_test.current or ""),
51
52
  ),
52
53
  secret_reader=secret_reader,
54
+ template_render_options=TemplateRenderOptions.create(
55
+ trim_blocks=template.template_render_options.trim_blocks
56
+ if template.template_render_options
57
+ else None,
58
+ lstrip_blocks=template.template_render_options.lstrip_blocks
59
+ if template.template_render_options
60
+ else None,
61
+ keep_trailing_newline=template.template_render_options.keep_trailing_newline
62
+ if template.template_render_options
63
+ else None,
64
+ ),
53
65
  )
54
66
 
55
67
  @staticmethod
@@ -1,8 +1,9 @@
1
1
  from functools import cache
2
- from typing import Any
2
+ from typing import Any, Self
3
3
 
4
4
  import jinja2
5
5
  from jinja2.sandbox import SandboxedEnvironment
6
+ from pydantic import BaseModel
6
7
  from sretoolbox.utils import retry
7
8
 
8
9
  from reconcile import queries
@@ -31,18 +32,46 @@ class Jinja2TemplateError(Exception):
31
32
  super().__init__("error processing jinja2 template: " + str(msg))
32
33
 
33
34
 
35
+ class TemplateRenderOptions(BaseModel):
36
+ trim_blocks: bool
37
+ lstrip_blocks: bool
38
+ keep_trailing_newline: bool
39
+
40
+ class Config:
41
+ frozen = True
42
+
43
+ @classmethod
44
+ def create(
45
+ cls,
46
+ trim_blocks: bool | None = None,
47
+ lstrip_blocks: bool | None = None,
48
+ keep_trailing_newline: bool | None = None,
49
+ ) -> Self:
50
+ return cls(
51
+ trim_blocks=trim_blocks or False,
52
+ lstrip_blocks=lstrip_blocks or False,
53
+ keep_trailing_newline=keep_trailing_newline or False,
54
+ )
55
+
56
+
34
57
  @cache
35
- def compile_jinja2_template(body: str, extra_curly: bool = False) -> Any:
36
- env: dict = {}
58
+ def compile_jinja2_template(
59
+ body: str,
60
+ extra_curly: bool = False,
61
+ template_render_options: TemplateRenderOptions | None = None,
62
+ ) -> Any:
63
+ if not template_render_options:
64
+ template_render_options = TemplateRenderOptions.create()
65
+ env: dict[str, Any] = template_render_options.dict()
37
66
  if extra_curly:
38
- env = {
67
+ env.update({
39
68
  "block_start_string": "{{%",
40
69
  "block_end_string": "%}}",
41
70
  "variable_start_string": "{{{",
42
71
  "variable_end_string": "}}}",
43
72
  "comment_start_string": "{{#",
44
73
  "comment_end_string": "#}}",
45
- }
74
+ })
46
75
 
47
76
  jinja_env = SandboxedEnvironment(
48
77
  extensions=[B64EncodeExtension, RaiseErrorExtension],
@@ -154,6 +183,7 @@ def process_jinja2_template(
154
183
  extra_curly: bool = False,
155
184
  settings: dict[str, Any] | None = None,
156
185
  secret_reader: SecretReaderBase | None = None,
186
+ template_render_options: TemplateRenderOptions | None = None,
157
187
  ) -> Any:
158
188
  if vars is None:
159
189
  vars = {}
@@ -187,7 +217,7 @@ def process_jinja2_template(
187
217
  for k, v in vars["_template_mocks"].items():
188
218
  vars[k] = lambda *args, **kwargs: v
189
219
  try:
190
- template = compile_jinja2_template(body, extra_curly)
220
+ template = compile_jinja2_template(body, extra_curly, template_render_options)
191
221
  r = template.render(vars)
192
222
  except Exception as e:
193
223
  raise Jinja2TemplateError(e)
@@ -197,9 +227,10 @@ def process_jinja2_template(
197
227
  def process_extracurlyjinja2_template(
198
228
  body: str,
199
229
  vars: dict[str, Any] | None = None,
200
- extra_curly: bool = True,
230
+ extra_curly: bool = True, # ignored. Just to be compatible with process_jinja2_template
201
231
  settings: dict[str, Any] | None = None,
202
232
  secret_reader: SecretReaderBase | None = None,
233
+ template_render_options: TemplateRenderOptions | None = None,
203
234
  ) -> Any:
204
235
  if vars is None:
205
236
  vars = {}
@@ -209,6 +240,7 @@ def process_extracurlyjinja2_template(
209
240
  extra_curly=True,
210
241
  settings=settings,
211
242
  secret_reader=secret_reader,
243
+ template_render_options=template_render_options,
212
244
  )
213
245
 
214
246
 
@@ -288,7 +288,7 @@ class JJB: # pylint: disable=too-many-public-methods
288
288
  project_url_raw = job["properties"][0]["github"]["url"]
289
289
  if "https://github.com" in project_url_raw:
290
290
  continue
291
- if job.get("disabled"):
291
+ if str(job.get("disabled")).lower() == "true":
292
292
  continue
293
293
  job_url = "{}/project/{}".format(
294
294
  self.instance_urls[name], job["name"]