Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/reference/organization/custom-property.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Definition of a `Custom Property` on organization level, the following propertie
| _default_value_ | string or list[string] or null | The default value to assign to a repository if the property is required | |
| _description_ | string or null | A description of this property | |
| _allowed_values_ | list[string] or null | The list of allowed values if either `single_select` or `multi_select` is used | |
| _values_editable_by_ | string or null | Who can edit the values of this property on a repository | `org_actors`, `org_and_repo_actors` or `null` |

!!! note

Expand Down
1 change: 1 addition & 0 deletions examples/template/otterdog-defaults.libsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ local newCustomProperty(name) = {
default_value: null,
description: null,
allowed_values: [],
values_editable_by: null,
};

# Function to create a new organization with default settings.
Expand Down
12 changes: 12 additions & 0 deletions otterdog/models/custom_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class CustomProperty(ModelObject):
default_value: str | list[str] | None
description: str | None
allowed_values: list[str] | None
values_editable_by: str | None

@property
def model_object_name(self) -> str:
Expand Down Expand Up @@ -130,6 +131,17 @@ def validate(self, context: ValidationContext, parent_object: Any) -> None:
f"but some of its elements are not in the list of allowed values '{self.allowed_values}'.",
)

if is_set_and_present(self.values_editable_by) and self.values_editable_by not in {
"org_actors",
"org_and_repo_actors",
}:
context.add_failure(
FailureType.ERROR,
f"{self.get_model_header(parent_object)} has 'values_editable_by' of value "
f"'{self.values_editable_by}', "
f"while only values ('org_actors' | 'org_and_repo_actors' | null) are allowed.",
)

def include_field_for_diff_computation(self, field: dataclasses.Field) -> bool:
if self.required is not True and field.name in ["default_value"]:
return False
Expand Down
6 changes: 6 additions & 0 deletions otterdog/resources/schemas/custom-property.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"allowed_values": {
"type": "array",
"items": { "type": "string" }
},
"values_editable_by": {
"anyOf": [
{ "type": "string", "enum": ["org_actors", "org_and_repo_actors"] },
{ "type": "null" }
]
}
},

Expand Down
6 changes: 6 additions & 0 deletions otterdog/webapp/templates/home/organization.html
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ <h3 class="card-title">Status</h3>
<th>Required</th>
<th>Default Value</th>
<th>Allowed Values</th>
<th>Values Editable By</th>
</tr>
</thead>
<tbody>
Expand All @@ -476,6 +477,11 @@ <h3 class="card-title">Status</h3>
{{ custom_property.allowed_values|pprint }}
{% endif %}
</td>
<td>
{% if custom_property.values_editable_by %}
{{ custom_property.values_editable_by }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Expand Down
4 changes: 4 additions & 0 deletions tests/models/test_custom_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def model_data(self) -> Any:
"default_value": "Python",
"description": "Primary language",
"allowed_values": ["Python", "Java"],
"values_editable_by": "org_and_repo_actors",
}

@property
Expand All @@ -45,6 +46,7 @@ def provider_data(self) -> Any:
"default_value": "Python",
"description": "Primary language",
"allowed_values": ["Python", "Java"],
"values_editable_by": "org_and_repo_actors",
}

def test_load_from_model(self):
Expand All @@ -57,6 +59,7 @@ def test_load_from_model(self):
assert custom_property.default_value == "Python"
assert custom_property.description == "Primary language"
assert custom_property.allowed_values == ["Python", "Java"]
assert custom_property.values_editable_by == "org_and_repo_actors"

def test_load_from_provider(self):
"""Loads a custom property from provider data."""
Expand All @@ -68,6 +71,7 @@ def test_load_from_provider(self):
assert custom_property.default_value == "Python"
assert custom_property.description == "Primary language"
assert custom_property.allowed_values == ["Python", "Java"]
assert custom_property.values_editable_by == "org_and_repo_actors"

async def test_to_provider_excludes_name(self):
"""Converts to provider data without including the name key."""
Expand Down
14 changes: 14 additions & 0 deletions tests/providers/github/integration/test_org_custom_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ async def test_create(github: GitHubProviderTestKit):
"default_value": "Python",
"description": "Primary language",
"allowed_values": ["Python", "Java"],
"values_editable_by": None,
},
response_json={},
)
Expand All @@ -59,6 +60,7 @@ async def test_create(github: GitHubProviderTestKit):
default_value="Python",
description="Primary language",
allowed_values=["Python", "Java"],
values_editable_by=None,
),
)

Expand All @@ -73,6 +75,7 @@ async def test_create_string_type(github: GitHubProviderTestKit):
"required": False,
"default_value": "",
"description": None,
"values_editable_by": None,
},
response_json={},
)
Expand All @@ -87,6 +90,7 @@ async def test_create_string_type(github: GitHubProviderTestKit):
default_value="",
description=None,
allowed_values=[],
values_editable_by=None,
),
)

Expand All @@ -101,6 +105,7 @@ async def test_create_string_type_with_non_empty_allowed_values(github: GitHubPr
"required": False,
"default_value": "",
"description": None,
"values_editable_by": None,
},
response_json={},
)
Expand All @@ -115,6 +120,7 @@ async def test_create_string_type_with_non_empty_allowed_values(github: GitHubPr
default_value="",
description=None,
allowed_values=["some_value"],
values_editable_by=None,
),
)

Expand All @@ -132,13 +138,15 @@ async def test_read(github: GitHubProviderTestKit):
"default_value": "Python",
"description": "Primary language",
"allowed_values": ["Python", "Java"],
"values_editable_by": None,
},
{
"property_name": "cost_center",
"value_type": "string",
"required": False,
"default_value": "",
"description": None,
"values_editable_by": None,
},
],
)
Expand All @@ -154,6 +162,7 @@ async def test_read(github: GitHubProviderTestKit):
default_value="Python",
description="Primary language",
allowed_values=["Python", "Java"],
values_editable_by=None,
),
CustomProperty(
name="cost_center",
Expand All @@ -162,6 +171,7 @@ async def test_read(github: GitHubProviderTestKit):
default_value="",
description=None,
allowed_values=[],
values_editable_by=None,
),
]

Expand All @@ -177,6 +187,7 @@ async def test_update(github: GitHubProviderTestKit):
"default_value": "Java",
"description": "Primary language",
"allowed_values": ["Python", "Java"],
"values_editable_by": None,
},
response_json={},
)
Expand All @@ -190,6 +201,7 @@ async def test_update(github: GitHubProviderTestKit):
default_value="Python",
description="Primary language",
allowed_values=["Python", "Java"],
values_editable_by=None,
),
new=CustomProperty(
name="language",
Expand All @@ -198,6 +210,7 @@ async def test_update(github: GitHubProviderTestKit):
default_value="Java",
description="Primary language",
allowed_values=["Python", "Java"],
values_editable_by=None,
),
)

Expand All @@ -219,6 +232,7 @@ async def test_delete(github: GitHubProviderTestKit):
default_value="Python",
description="Primary language",
allowed_values=["Python", "Java"],
values_editable_by=None,
),
new=None,
)