Skip to content

Commit 4560c7c

Browse files
authored
Merge pull request #254 from dbt-labs/release-0.3.3
2 parents 50068f5 + c95082b commit 4560c7c

File tree

20 files changed

+1274
-61
lines changed

20 files changed

+1274
-61
lines changed

CHANGELOG.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [Unreleased](https://github.com/dbt-labs/terraform-provider-dbtcloud/compare/v0.3.1...HEAD)
5+
## [Unreleased](https://github.com/dbt-labs/terraform-provider-dbtcloud/compare/v0.3.3...HEAD)
66

7-
## [0.3.1](https://github.com/dbt-labs/terraform-provider-dbtcloud/compare/v0.3.0...v0.3.1)
7+
## [0.3.3](https://github.com/dbt-labs/terraform-provider-dbtcloud/compare/v0.3.2...v0.3.3)
8+
9+
## Changes
10+
11+
- [#250](https://github.com/dbt-labs/terraform-provider-dbtcloud/issues/250) - [Experimental] Create a new resource called `dbtcloud_group_partial_permissions` to manage permissions of a single group from different resources which can be set across different Terraform projects/workspaces. The dbt Cloud API doesn't provide endpoints for adding/removing single permissions, so the logic in the provider is more complex than other resources. If the resource works as expected for the provider users we could create similar ones for "partial" notifications and "partial" license mappings.
12+
13+
## [0.3.2](https://github.com/dbt-labs/terraform-provider-dbtcloud/compare/v0.3.0...v0.3.2)
814

915
## Changes
1016

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ install: build
1515
mv ./$(BINARY) $(HOME)/.terraform.d/plugins/$(BINARY)
1616

1717
doc:
18-
go generate ./... && rm docs/resources/dbt_cloud_* && rm docs/data-sources/dbt_cloud_* && cp -r guides docs/
18+
go generate ./... && cp -r guides docs/
1919

2020
test: deps
2121
go test -mod=readonly -count=1 ./...
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
---
2+
page_title: "dbtcloud_group_partial_permissions Resource - dbtcloud"
3+
subcategory: ""
4+
description: |-
5+
Provide a partial set of permissions for a group. This is different from dbt_cloud_group as it allows to have multiple resources updating the same dbt Cloud group and is useful for companies managing a single dbt Cloud Account configuration from different Terraform projects/workspaces.
6+
If a company uses only one Terraform project/workspace to manage all their dbt Cloud Account config, it is recommended to use dbt_cloud_group instead of dbt_cloud_group_partial_permissions.
7+
~> This is currently an experimental resource and any feedback is welcome in the GitHub repository.
8+
The current behavior of the resource is the following:
9+
when using dbt_cloud_group_partial_permissions, don't use dbt_cloud_group for the same group in any other project/workspace. Otherwise, the behavior is undefined and partial permissions might be removed.when defining a new dbt_cloud_group_partial_permissions
10+
11+
if the group doesn't exist with the given name, it will be createdif a group exists with the given name, permissions will be added in the dbt Cloud group if they are not present yetin a given Terraform project/workspace, avoid having different ~~dbtcloudgrouppartialpermissions` for the same group name to prevent sync issues. Add all the permissions in the same resource.all resources for the same group name need to have the same values for assign_by_default and sso_mapping_groups. Those fields are not considered "partial". (Please raise feedback in GitHub if you think that sso_mapping_groups should be "partial" as well)when a resource is updated, the dbt Cloud group will be updated accordingly, removing and adding permissionswhen the resource is deleted/destroyed, if the resulting permission sets is empty, the group will be deleted ; otherwise, the group will be updated, removing the permissions from the deleted resource
12+
---
13+
14+
# dbtcloud_group_partial_permissions (Resource)
15+
16+
17+
Provide a partial set of permissions for a group. This is different from `dbt_cloud_group` as it allows to have multiple resources updating the same dbt Cloud group and is useful for companies managing a single dbt Cloud Account configuration from different Terraform projects/workspaces.
18+
19+
If a company uses only one Terraform project/workspace to manage all their dbt Cloud Account config, it is recommended to use `dbt_cloud_group` instead of `dbt_cloud_group_partial_permissions`.
20+
21+
~> This is currently an experimental resource and any feedback is welcome in the GitHub repository.
22+
23+
The current behavior of the resource is the following:
24+
25+
- when using `dbt_cloud_group_partial_permissions`, don't use `dbt_cloud_group` for the same group in any other project/workspace. Otherwise, the behavior is undefined and partial permissions might be removed.
26+
- when defining a new `dbt_cloud_group_partial_permissions`
27+
- if the group doesn't exist with the given `name`, it will be created
28+
- if a group exists with the given `name`, permissions will be added in the dbt Cloud group if they are not present yet
29+
- in a given Terraform project/workspace, avoid having different ~~dbt_cloud_group_partial_permissions` for the same group name to prevent sync issues. Add all the permissions in the same resource.
30+
- all resources for the same group name need to have the same values for `assign_by_default` and `sso_mapping_groups`. Those fields are not considered "partial". (Please raise feedback in GitHub if you think that `sso_mapping_groups` should be "partial" as well)
31+
- when a resource is updated, the dbt Cloud group will be updated accordingly, removing and adding permissions
32+
- when the resource is deleted/destroyed, if the resulting permission sets is empty, the group will be deleted ; otherwise, the group will be updated, removing the permissions from the deleted resource
33+
34+
## Example Usage
35+
36+
```terraform
37+
// we add some permissions to the group "TF Group 1" (existing or not) to a new project
38+
resource "dbtcloud_group_partial_permissions" "tf_group_1" {
39+
name = "TF Group 1"
40+
group_permissions = [
41+
{
42+
permission_set = "developer"
43+
project_id = dbtcloud_project.dbt_project.id
44+
all_projects = false
45+
},
46+
{
47+
permission_set = "git_admin"
48+
project_id = dbtcloud_project.dbt_project.id
49+
all_projects = false
50+
}
51+
]
52+
}
53+
54+
// we add Admin permissions to the group "TF Group 2" (existing or not) to a new project
55+
// it is possible to add more permissions to the same group name in other Terraform projects/workspaces, using another `dbtcloud_group_partial_permissions` resource
56+
resource "dbtcloud_group_partial_permissions" "tf_group_2" {
57+
name = "TF Group 2"
58+
sso_mapping_groups = ["group2"]
59+
group_permissions = [
60+
{
61+
permission_set = "admin"
62+
project_id = dbtcloud_project.dbt_project.id
63+
all_projects = false
64+
}
65+
]
66+
}
67+
```
68+
69+
<!-- schema generated by tfplugindocs -->
70+
## Schema
71+
72+
### Required
73+
74+
- `name` (String) The name of the group. This is used to identify an existing group
75+
76+
### Optional
77+
78+
- `assign_by_default` (Boolean) Whether the group will be assigned by default to users. The value needs to be the same for all partial permissions for the same group.
79+
- `group_permissions` (Attributes Set) Partial permissions for the group. Those permissions will be added/removed when config is added/removed. (see [below for nested schema](#nestedatt--group_permissions))
80+
- `sso_mapping_groups` (Set of String) Mapping groups from the IdP. At the moment the complete list needs to be provided in each partial permission for the same group.
81+
82+
### Read-Only
83+
84+
- `id` (Number) The ID of the group
85+
86+
<a id="nestedatt--group_permissions"></a>
87+
### Nested Schema for `group_permissions`
88+
89+
Required:
90+
91+
- `all_projects` (Boolean) Whether access should be provided for all projects or not.
92+
- `permission_set` (String) Set of permissions to apply. The permissions allowed are the same as the ones for the `dbtcloud_group` resource.
93+
94+
Optional:
95+
96+
- `project_id` (Number) Project ID to apply this permission to for this group.

docs/resources/job.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ resource "dbtcloud_job" "daily_job" {
3636
run_generate_sources = true
3737
target_name = "default"
3838
triggers = {
39-
"github_webhook" : false,
40-
"git_provider_webhook" : false,
39+
"github_webhook" : false
40+
"git_provider_webhook" : false
4141
"schedule" : true
4242
"on_merge" : false
4343
}
@@ -62,8 +62,8 @@ resource "dbtcloud_job" "ci_job" {
6262
project_id = dbtcloud_project.dbt_project.id
6363
run_generate_sources = false
6464
triggers = {
65-
"github_webhook" : true,
66-
"git_provider_webhook" : true,
65+
"github_webhook" : true
66+
"git_provider_webhook" : true
6767
"schedule" : false
6868
"on_merge" : false
6969
}
@@ -86,8 +86,8 @@ resource "dbtcloud_job" "downstream_job" {
8686
project_id = dbtcloud_project.dbt_project2.id
8787
run_generate_sources = true
8888
triggers = {
89-
"github_webhook" : false,
90-
"git_provider_webhook" : false,
89+
"github_webhook" : false
90+
"git_provider_webhook" : false
9191
"schedule" : false
9292
"on_merge" : false
9393
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// we add some permissions to the group "TF Group 1" (existing or not) to a new project
2+
resource "dbtcloud_group_partial_permissions" "tf_group_1" {
3+
name = "TF Group 1"
4+
group_permissions = [
5+
{
6+
permission_set = "developer"
7+
project_id = dbtcloud_project.dbt_project.id
8+
all_projects = false
9+
},
10+
{
11+
permission_set = "git_admin"
12+
project_id = dbtcloud_project.dbt_project.id
13+
all_projects = false
14+
}
15+
]
16+
}
17+
18+
// we add Admin permissions to the group "TF Group 2" (existing or not) to a new project
19+
// it is possible to add more permissions to the same group name in other Terraform projects/workspaces, using another `dbtcloud_group_partial_permissions` resource
20+
resource "dbtcloud_group_partial_permissions" "tf_group_2" {
21+
name = "TF Group 2"
22+
sso_mapping_groups = ["group2"]
23+
group_permissions = [
24+
{
25+
permission_set = "admin"
26+
project_id = dbtcloud_project.dbt_project.id
27+
all_projects = false
28+
}
29+
]
30+
}

examples/resources/dbtcloud_job/resource.tf

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ resource "dbtcloud_job" "daily_job" {
1313
run_generate_sources = true
1414
target_name = "default"
1515
triggers = {
16-
"github_webhook" : false,
17-
"git_provider_webhook" : false,
16+
"github_webhook" : false
17+
"git_provider_webhook" : false
1818
"schedule" : true
1919
"on_merge" : false
2020
}
@@ -39,8 +39,8 @@ resource "dbtcloud_job" "ci_job" {
3939
project_id = dbtcloud_project.dbt_project.id
4040
run_generate_sources = false
4141
triggers = {
42-
"github_webhook" : true,
43-
"git_provider_webhook" : true,
42+
"github_webhook" : true
43+
"git_provider_webhook" : true
4444
"schedule" : false
4545
"on_merge" : false
4646
}
@@ -63,8 +63,8 @@ resource "dbtcloud_job" "downstream_job" {
6363
project_id = dbtcloud_project.dbt_project2.id
6464
run_generate_sources = true
6565
triggers = {
66-
"github_webhook" : false,
67-
"git_provider_webhook" : false,
66+
"github_webhook" : false
67+
"git_provider_webhook" : false
6868
"schedule" : false
6969
"on_merge" : false
7070
}

go.mod

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
module github.com/dbt-labs/terraform-provider-dbtcloud
22

3-
go 1.21
3+
go 1.21.0
4+
5+
toolchain go1.21.4
46

57
require (
68
github.com/hashicorp/terraform-plugin-docs v0.16.0
@@ -12,6 +14,7 @@ require (
1214
github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0
1315
github.com/hashicorp/terraform-plugin-testing v1.7.0
1416
github.com/samber/lo v1.39.0
17+
github.com/sirupsen/logrus v1.9.3
1518
)
1619

1720
require (
@@ -59,7 +62,8 @@ require (
5962
github.com/posener/complete v1.2.3 // indirect
6063
github.com/russross/blackfriday v1.6.0 // indirect
6164
github.com/shopspring/decimal v1.3.1 // indirect
62-
github.com/spf13/cast v1.5.0 // indirect
65+
github.com/spf13/cast v1.5.1 // indirect
66+
github.com/stretchr/testify v1.8.4 // indirect
6367
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
6468
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
6569
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect

go.sum

+14-9
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
3737
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
3838
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
3939
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
40-
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
41-
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
40+
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
41+
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
4242
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
4343
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
4444
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
@@ -130,8 +130,8 @@ github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gav
130130
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
131131
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
132132
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
133-
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
134-
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
133+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
134+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
135135
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
136136
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
137137
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -172,8 +172,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
172172
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
173173
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
174174
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
175-
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
176-
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
175+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
176+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
177177
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
178178
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
179179
github.com/samber/lo v1.39.0 h1:4gTz1wUhNYLhFSKl6O+8peW0v2F4BCY034GRpU9WnuA=
@@ -183,18 +183,22 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX
183183
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
184184
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
185185
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
186+
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
187+
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
186188
github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ=
187189
github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
188190
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
189-
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
190-
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
191+
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
192+
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
191193
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
192194
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
193195
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
194196
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
195197
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
196-
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
198+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
197199
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
200+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
201+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
198202
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
199203
github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI=
200204
github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
@@ -241,6 +245,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
241245
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
242246
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
243247
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
248+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
244249
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
245250
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
246251
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

0 commit comments

Comments
 (0)