diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1741d1..354c408 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## Goliac v0.15.3
+
+- allow public,internal,private repository visibility
+- allow to restrict public repositories via global rules
+
## Goliac v0.15.2
- refactor error handling
diff --git a/browser/goliac-ui/src/components/RepositoriesApp.vue b/browser/goliac-ui/src/components/RepositoriesApp.vue
index b5a5d8e..19b2b8c 100644
--- a/browser/goliac-ui/src/components/RepositoriesApp.vue
+++ b/browser/goliac-ui/src/components/RepositoriesApp.vue
@@ -16,7 +16,7 @@
:default-sort="{ prop: 'name', order: 'descending' }"
>
-
+
diff --git a/browser/goliac-ui/src/components/RepositoryApp.vue b/browser/goliac-ui/src/components/RepositoryApp.vue
index b7ba851..d3d1e2f 100644
--- a/browser/goliac-ui/src/components/RepositoryApp.vue
+++ b/browser/goliac-ui/src/components/RepositoryApp.vue
@@ -15,8 +15,8 @@
- Public :
- {{ repository.public}}
+ Visibility :
+ {{ repository.visibility}}
Archived :
diff --git a/docs/api_docs/bundle.yaml b/docs/api_docs/bundle.yaml
index 8a13d25..40fc133 100644
--- a/docs/api_docs/bundle.yaml
+++ b/docs/api_docs/bundle.yaml
@@ -321,8 +321,8 @@ definitions:
name:
type: string
x-isnullable: false
- public:
- type: boolean
+ visibility:
+ type: string
x-isnullable: false
x-omitempty: false
autoMergeAllowed:
@@ -351,8 +351,8 @@ definitions:
name:
type: string
x-isnullable: false
- public:
- type: boolean
+ visibility:
+ type: string
x-isnullable: false
x-omitempty: false
archived:
diff --git a/docs/installation.md b/docs/installation.md
index 9d086f4..ee247ae 100644
--- a/docs/installation.md
+++ b/docs/installation.md
@@ -138,6 +138,15 @@ destructive_operations:
teams: false # can Goliac remove teams not listed in this repository
users: false # can Goliac remove users not listed in this repository
rulesets: false # can Goliac remove rulesets not listed in this repository
+
+usersync:
+ plugin: noop # noop, fromgithubsaml, shellscript
+
+#visibility_rules:
+# forbid_public_repositories: true # if you want to forbid public repositories
+# forbid_public_repositories_exclusions: # if you want to allow some public repositories
+# - goliac-teams
+# - repo_public.*
```
and you can configure different ruleset in the `/rulesets` directory like
diff --git a/docs/quick_start.md b/docs/quick_start.md
index 2cb2ced..d3bc6c8 100644
--- a/docs/quick_start.md
+++ b/docs/quick_start.md
@@ -158,7 +158,7 @@ apiVersion: v1
kind: Repository
name: myrepository
spec:
- public: false
+ visibility: private
EOF
git add myrepository.yaml
diff --git a/docs/usage.md b/docs/usage.md
index 114f461..da5bf57 100644
--- a/docs/usage.md
+++ b/docs/usage.md
@@ -49,7 +49,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
allow_auto_merge: true
delete_branch_on_merge: true
allow_update_branch: true
@@ -77,7 +77,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
renameTo: anotherName
```
@@ -99,7 +99,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
rulesets:
- name: myruleset
@@ -118,7 +118,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
rulesets:
- name: myruleset
@@ -141,7 +141,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
rulesets:
- name: myruleset
@@ -168,7 +168,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
branch_protections:
- pattern: master
@@ -195,7 +195,7 @@ apiVersion: v1
kind: Repository
name: awesome-repository
spec:
- public: true
+ visibility: public
...
branch_protections:
- pattern: master
diff --git a/internal/config/repo_config.go b/internal/config/repo_config.go
index 0017fd7..c344e30 100644
--- a/internal/config/repo_config.go
+++ b/internal/config/repo_config.go
@@ -25,6 +25,11 @@ type RepositoryConfig struct {
AllowDestructiveUsers bool `yaml:"users"`
AllowDestructiveRulesets bool `yaml:"rulesets"`
} `yaml:"destructive_operations"`
+
+ VisibilityRules struct {
+ ForbidPublicRepositories bool `yaml:"forbid_public_repositories"`
+ ForbidPublicRepositoriesExclusions []string `yaml:"forbid_public_repositories_exclusions"`
+ } `yaml:"visibility_rules"`
}
// set default values
diff --git a/internal/engine/goliac_reconciliator.go b/internal/engine/goliac_reconciliator.go
index db7eeb9..3ed2f8b 100644
--- a/internal/engine/goliac_reconciliator.go
+++ b/internal/engine/goliac_reconciliator.go
@@ -30,16 +30,18 @@ type GoliacReconciliator interface {
}
type GoliacReconciliatorImpl struct {
- executor ReconciliatorExecutor
- repoconfig *config.RepositoryConfig
- unmanaged *UnmanagedResources
+ executor ReconciliatorExecutor
+ reconciliatorFilter ReconciliatorFilter
+ repoconfig *config.RepositoryConfig
+ unmanaged *UnmanagedResources
}
-func NewGoliacReconciliatorImpl(executor ReconciliatorExecutor, repoconfig *config.RepositoryConfig) GoliacReconciliator {
+func NewGoliacReconciliatorImpl(isEntreprise bool, executor ReconciliatorExecutor, repoconfig *config.RepositoryConfig) GoliacReconciliator {
return &GoliacReconciliatorImpl{
- executor: executor,
- repoconfig: repoconfig,
- unmanaged: nil,
+ executor: executor,
+ reconciliatorFilter: NewReconciliatorFilter(isEntreprise, repoconfig),
+ repoconfig: repoconfig,
+ unmanaged: nil,
}
}
@@ -350,6 +352,7 @@ func (r *GoliacReconciliatorImpl) reconciliateTeams(ctx context.Context, errorCo
}
type GithubRepoComparable struct {
+ Visibility string
BoolProperties map[string]bool
Writers []string
Readers []string
@@ -395,6 +398,7 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
ghRepos := remote.Repositories()
for k, v := range ghRepos {
repo := &GithubRepoComparable{
+ Visibility: v.Visibility,
BoolProperties: map[string]bool{},
Writers: []string{},
Readers: []string{},
@@ -444,7 +448,7 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
teamsRepo.Name = teamsreponame
teamsRepo.Spec.Writers = []string{r.repoconfig.AdminTeam}
teamsRepo.Spec.Readers = []string{}
- teamsRepo.Spec.IsPublic = false
+ teamsRepo.Spec.Visibility = "private"
teamsRepo.Spec.DeleteBranchOnMerge = true
// cf goliac.go:L231-252
bp := entity.RepositoryBranchProtection{
@@ -544,14 +548,14 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
branchprotections[bp.Pattern] = &branchprotection
}
- lRepos[utils.GithubAnsiString(reponame)] = &GithubRepoComparable{
+ lRepos[utils.GithubAnsiString(reponame)] = r.reconciliatorFilter.RepositoryFilter(reponame, &GithubRepoComparable{
BoolProperties: map[string]bool{
- "private": !lRepo.Spec.IsPublic,
"archived": lRepo.Archived,
"allow_auto_merge": lRepo.Spec.AllowAutoMerge,
"delete_branch_on_merge": lRepo.Spec.DeleteBranchOnMerge,
"allow_update_branch": lRepo.Spec.AllowUpdateBranch,
},
+ Visibility: lRepo.Spec.Visibility,
Readers: readers,
Writers: writers,
ExternalUserReaders: eReaders,
@@ -559,7 +563,7 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
InternalUsers: []string{},
Rulesets: rulesets,
BranchProtections: branchprotections,
- }
+ })
}
// now we compare local (slugTeams) and remote (rTeams)
@@ -613,6 +617,10 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
}
}
+ if lRepo.Visibility != rRepo.Visibility {
+ return false
+ }
+
if res, _, _ := entity.StringArrayEquivalent(lRepo.Readers, rRepo.Readers); !res {
return false
}
@@ -640,9 +648,12 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
// reconciliate repositories boolean properties
for lk, lv := range lRepo.BoolProperties {
if rv, ok := rRepo.BoolProperties[lk]; !ok || rv != lv {
- r.UpdateRepositoryUpdateBoolProperty(ctx, errorCollector, dryrun, remote, reponame, lk, lv)
+ r.UpdateRepositoryUpdateProperty(ctx, errorCollector, dryrun, remote, reponame, lk, lv)
}
}
+ if lRepo.Visibility != rRepo.Visibility {
+ r.UpdateRepositoryUpdateProperty(ctx, errorCollector, dryrun, remote, reponame, "visibility", lRepo.Visibility)
+ }
if res, readToRemove, readToAdd := entity.StringArrayEquivalent(lRepo.Readers, rRepo.Readers); !res {
for _, teamSlug := range readToAdd {
@@ -717,11 +728,11 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
// if the repo was just archived in a previous commit and we "resume it"
if aRepo, ok := toArchive[reponame]; ok {
delete(toArchive, reponame)
- r.UpdateRepositoryUpdateBoolProperty(ctx, errorCollector, dryrun, remote, reponame, "archived", false)
+ r.UpdateRepositoryUpdateProperty(ctx, errorCollector, dryrun, remote, reponame, "archived", false)
// calling onChanged to update the repository permissions
onChanged(reponame, aRepo, rRepo)
} else {
- r.CreateRepository(ctx, errorCollector, dryrun, remote, reponame, reponame, lRepo.Writers, lRepo.Readers, lRepo.BoolProperties)
+ r.CreateRepository(ctx, errorCollector, dryrun, remote, reponame, reponame, lRepo.Visibility, lRepo.Writers, lRepo.Readers, lRepo.BoolProperties)
}
}
@@ -731,7 +742,7 @@ func (r *GoliacReconciliatorImpl) reconciliateRepositories(ctx context.Context,
// but if we have ArchiveOnDelete...
if r.repoconfig.ArchiveOnDelete {
if r.repoconfig.DestructiveOperations.AllowDestructiveRepositories {
- r.UpdateRepositoryUpdateBoolProperty(ctx, errorCollector, dryrun, remote, reponame, "archived", true)
+ r.UpdateRepositoryUpdateProperty(ctx, errorCollector, dryrun, remote, reponame, "archived", true)
toArchive[reponame] = rRepo
} else {
r.unmanaged.Repositories[reponame] = true
@@ -975,11 +986,11 @@ func (r *GoliacReconciliatorImpl) DeleteTeam(ctx context.Context, errorCollector
r.unmanaged.Teams[teamslug] = true
}
}
-func (r *GoliacReconciliatorImpl) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, remote *MutableGoliacRemoteImpl, reponame string, descrition string, writers []string, readers []string, boolProperties map[string]bool) {
+func (r *GoliacReconciliatorImpl) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, remote *MutableGoliacRemoteImpl, reponame string, descrition string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
logrus.WithFields(map[string]interface{}{"dryrun": dryrun, "command": "create_repository"}).Infof("repositoryname: %s, readers: %s, writers: %s, boolProperties: %v", reponame, strings.Join(readers, ","), strings.Join(writers, ","), boolProperties)
- remote.CreateRepository(reponame, reponame, writers, readers, boolProperties)
+ remote.CreateRepository(reponame, reponame, visibility, writers, readers, boolProperties)
if r.executor != nil {
- r.executor.CreateRepository(ctx, errorCollector, dryrun, reponame, reponame, writers, readers, boolProperties)
+ r.executor.CreateRepository(ctx, errorCollector, dryrun, reponame, reponame, visibility, writers, readers, boolProperties)
}
}
func (r *GoliacReconciliatorImpl) UpdateRepositoryAddTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, remote *MutableGoliacRemoteImpl, reponame string, teamslug string, permission string) {
@@ -1025,11 +1036,11 @@ func (r *GoliacReconciliatorImpl) RenameRepository(ctx context.Context, errorCol
}
}
-func (r *GoliacReconciliatorImpl) UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, remote *MutableGoliacRemoteImpl, reponame string, propertyName string, propertyValue bool) {
+func (r *GoliacReconciliatorImpl) UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, remote *MutableGoliacRemoteImpl, reponame string, propertyName string, propertyValue interface{}) {
logrus.WithFields(map[string]interface{}{"dryrun": dryrun, "command": "update_repository_update_bool_property"}).Infof("repositoryname: %s %s:%v", reponame, propertyName, propertyValue)
- remote.UpdateRepositoryUpdateBoolProperty(reponame, propertyName, propertyValue)
+ remote.UpdateRepositoryUpdateProperty(reponame, propertyName, propertyValue)
if r.executor != nil {
- r.executor.UpdateRepositoryUpdateBoolProperty(ctx, errorCollector, dryrun, reponame, propertyName, propertyValue)
+ r.executor.UpdateRepositoryUpdateProperty(ctx, errorCollector, dryrun, reponame, propertyName, propertyValue)
}
}
func (r *GoliacReconciliatorImpl) AddRuleset(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, ruleset *GithubRuleSet) {
diff --git a/internal/engine/goliac_reconciliator_filter.go b/internal/engine/goliac_reconciliator_filter.go
new file mode 100644
index 0000000..22af9b3
--- /dev/null
+++ b/internal/engine/goliac_reconciliator_filter.go
@@ -0,0 +1,52 @@
+package engine
+
+import (
+ "regexp"
+
+ "github.com/goliac-project/goliac/internal/config"
+)
+
+type ReconciliatorFilter interface {
+ RepositoryFilter(reponame string, repo *GithubRepoComparable) *GithubRepoComparable
+}
+
+type ReconciliatorFilterImpl struct {
+ isEnterprise bool
+ ForbidPublicRepositories bool
+ ForbidPulicRepostitoriesExcept []*regexp.Regexp
+}
+
+func NewReconciliatorFilter(isEnterprise bool, config *config.RepositoryConfig) *ReconciliatorFilterImpl {
+ exclude := []*regexp.Regexp{}
+ if config != nil {
+ for _, pattern := range config.VisibilityRules.ForbidPublicRepositoriesExclusions {
+ exclude = append(exclude, regexp.MustCompile("^"+pattern+"$"))
+ }
+ }
+
+ return &ReconciliatorFilterImpl{
+ isEnterprise: isEnterprise,
+ ForbidPublicRepositories: config.VisibilityRules.ForbidPublicRepositories,
+ ForbidPulicRepostitoriesExcept: exclude,
+ }
+}
+
+func (r *ReconciliatorFilterImpl) RepositoryFilter(reponame string, repo *GithubRepoComparable) *GithubRepoComparable {
+ if !r.isEnterprise {
+ if repo.Visibility == "internal" {
+ repo.Visibility = "private"
+ }
+ }
+
+ if r.ForbidPublicRepositories {
+ for _, exclude := range r.ForbidPulicRepostitoriesExcept {
+ if exclude.MatchString(reponame) {
+ return repo
+ }
+ }
+ if repo.Visibility == "public" {
+ repo.Visibility = "private"
+ }
+ }
+ return repo
+}
diff --git a/internal/engine/goliac_reconciliator_filter_test.go b/internal/engine/goliac_reconciliator_filter_test.go
new file mode 100644
index 0000000..9fe8a19
--- /dev/null
+++ b/internal/engine/goliac_reconciliator_filter_test.go
@@ -0,0 +1,82 @@
+package engine
+
+import (
+ "testing"
+
+ "github.com/goliac-project/goliac/internal/config"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestReconciliatorFilterImpl_RepositoryFilter(t *testing.T) {
+ t.Run("happy path: public allowed", func(t *testing.T) {
+ config := &config.RepositoryConfig{}
+
+ filter := NewReconciliatorFilter(true, config)
+ repo := &GithubRepoComparable{
+ Visibility: "internal",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "internal", repo.Visibility)
+
+ repo = &GithubRepoComparable{
+ Visibility: "public",
+ }
+
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "public", repo.Visibility)
+ })
+
+ t.Run("happy path: public forbidden", func(t *testing.T) {
+ config := &config.RepositoryConfig{}
+ config.VisibilityRules.ForbidPublicRepositories = true
+
+ filter := NewReconciliatorFilter(true, config)
+ repo := &GithubRepoComparable{
+ Visibility: "internal",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "internal", repo.Visibility)
+
+ repo = &GithubRepoComparable{
+ Visibility: "public",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "private", repo.Visibility)
+ })
+
+ t.Run("happy path: not enterprise", func(t *testing.T) {
+ config := &config.RepositoryConfig{}
+
+ filter := NewReconciliatorFilter(false, config)
+ repo := &GithubRepoComparable{
+ Visibility: "internal",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "private", repo.Visibility)
+
+ repo = &GithubRepoComparable{
+ Visibility: "public",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "public", repo.Visibility)
+ })
+
+ t.Run("happy path: forbidden except", func(t *testing.T) {
+ config := &config.RepositoryConfig{}
+ config.VisibilityRules.ForbidPublicRepositories = true
+ config.VisibilityRules.ForbidPublicRepositoriesExclusions = []string{"repo"}
+
+ filter := NewReconciliatorFilter(true, config)
+ repo := &GithubRepoComparable{
+ Visibility: "public",
+ }
+ repo = filter.RepositoryFilter("repo", repo)
+ assert.Equal(t, "public", repo.Visibility)
+
+ repo = &GithubRepoComparable{
+ Visibility: "public",
+ }
+ repo = filter.RepositoryFilter("repo2", repo)
+ assert.Equal(t, "private", repo.Visibility)
+ })
+}
diff --git a/internal/engine/goliac_reconciliator_test.go b/internal/engine/goliac_reconciliator_test.go
index 66ed8ce..66edce7 100644
--- a/internal/engine/goliac_reconciliator_test.go
+++ b/internal/engine/goliac_reconciliator_test.go
@@ -218,7 +218,7 @@ func (r *ReconciliatorListenerRecorder) UpdateTeamSetParent(ctx context.Context,
func (r *ReconciliatorListenerRecorder) DeleteTeam(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, teamslug string) {
r.TeamDeleted[teamslug] = true
}
-func (r *ReconciliatorListenerRecorder) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, writers []string, readers []string, boolProperties map[string]bool) {
+func (r *ReconciliatorListenerRecorder) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
r.RepositoryCreated[reponame] = true
}
func (r *ReconciliatorListenerRecorder) UpdateRepositoryAddTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, teamslug string, permission string) {
@@ -236,7 +236,7 @@ func (r *ReconciliatorListenerRecorder) DeleteRepository(ctx context.Context, er
func (r *ReconciliatorListenerRecorder) RenameRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, newname string) {
r.RepositoriesRenamed[reponame] = true
}
-func (r *ReconciliatorListenerRecorder) UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue bool) {
+func (r *ReconciliatorListenerRecorder) UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue interface{}) {
r.RepositoriesUpdatePrivate[reponame] = true
}
func (r *ReconciliatorListenerRecorder) UpdateRepositorySetExternalUser(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, githubid string, permission string) {
@@ -319,7 +319,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -365,7 +365,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -411,7 +411,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -475,7 +475,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -544,7 +544,7 @@ func TestReconciliationTeam(t *testing.T) {
EveryoneTeamEnabled: true,
}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -592,7 +592,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -629,7 +629,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -705,7 +705,7 @@ func TestReconciliationTeam(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -784,7 +784,7 @@ func TestReconciliationTeam(t *testing.T) {
recorder := NewReconciliatorListenerRecorder()
repoconfig := &config.RepositoryConfig{}
repoconfig.DestructiveOperations.AllowDestructiveTeams = true
- r := NewGoliacReconciliatorImpl(recorder, repoconfig)
+ r := NewGoliacReconciliatorImpl(false, recorder, repoconfig)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
teams: make(map[string]*entity.Team),
@@ -821,7 +821,7 @@ func TestReconciliationRepo(t *testing.T) {
recorder := NewReconciliatorListenerRecorder()
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -862,7 +862,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -917,7 +917,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -990,7 +990,7 @@ func TestReconciliationRepo(t *testing.T) {
EveryoneTeamEnabled: true,
}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1062,7 +1062,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1145,7 +1145,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1233,7 +1233,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1311,7 +1311,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1391,7 +1391,7 @@ func TestReconciliationRepo(t *testing.T) {
recorder := NewReconciliatorListenerRecorder()
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1466,7 +1466,7 @@ func TestReconciliationRepo(t *testing.T) {
recorder := NewReconciliatorListenerRecorder()
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1543,7 +1543,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1623,7 +1623,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1700,7 +1700,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1784,7 +1784,7 @@ func TestReconciliationRepo(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1820,7 +1820,7 @@ func TestReconciliationRepo(t *testing.T) {
ArchiveOnDelete: true,
}
repoconfig.DestructiveOperations.AllowDestructiveRepositories = true
- r := NewGoliacReconciliatorImpl(recorder, repoconfig)
+ r := NewGoliacReconciliatorImpl(false, recorder, repoconfig)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1859,7 +1859,7 @@ func TestReconciliationRepo(t *testing.T) {
ArchiveOnDelete: false,
}
repoconfig.DestructiveOperations.AllowDestructiveRepositories = true
- r := NewGoliacReconciliatorImpl(recorder, repoconfig)
+ r := NewGoliacReconciliatorImpl(false, recorder, repoconfig)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -1899,7 +1899,7 @@ func TestReconciliationRepo(t *testing.T) {
ArchiveOnDelete: false,
}
repoconfig.DestructiveOperations.AllowDestructiveRepositories = true
- r := NewGoliacReconciliatorImpl(recorder, repoconfig)
+ r := NewGoliacReconciliatorImpl(false, recorder, repoconfig)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2022,7 +2022,7 @@ func TestReconciliationRulesets(t *testing.T) {
recorder := NewReconciliatorListenerRecorder()
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2079,7 +2079,7 @@ func TestReconciliationRulesets(t *testing.T) {
Ruleset: "new",
})
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2136,7 +2136,7 @@ func TestReconciliationRulesets(t *testing.T) {
Ruleset: "update",
})
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2195,7 +2195,7 @@ func TestReconciliationRulesets(t *testing.T) {
}
repoconf.DestructiveOperations.AllowDestructiveRulesets = true
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2240,7 +2240,7 @@ func TestReconciliationRepoRulesets(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2337,7 +2337,7 @@ func TestReconciliationRepoRulesets(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2428,7 +2428,7 @@ func TestReconciliationRepoBranchProtection(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
@@ -2515,7 +2515,7 @@ func TestReconciliationRepoBranchProtection(t *testing.T) {
repoconf := config.RepositoryConfig{}
- r := NewGoliacReconciliatorImpl(recorder, &repoconf)
+ r := NewGoliacReconciliatorImpl(false, recorder, &repoconf)
local := GoliacLocalMock{
users: make(map[string]*entity.User),
diff --git a/internal/engine/mutable_remote.go b/internal/engine/mutable_remote.go
index 00432c4..a8f7e0b 100644
--- a/internal/engine/mutable_remote.go
+++ b/internal/engine/mutable_remote.go
@@ -169,9 +169,10 @@ func (m *MutableGoliacRemoteImpl) DeleteTeam(teamslug string) {
delete(m.teamRepos, teamslug)
}
}
-func (m *MutableGoliacRemoteImpl) CreateRepository(reponame string, descrition string, writers []string, readers []string, boolProperties map[string]bool) {
+func (m *MutableGoliacRemoteImpl) CreateRepository(reponame string, descrition string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
r := GithubRepository{
Name: reponame,
+ Visibility: visibility,
BoolProperties: boolProperties,
ExternalUsers: map[string]string{},
}
@@ -226,15 +227,19 @@ func (m *MutableGoliacRemoteImpl) RenameRepository(reponame string, newname stri
/*
UpdateRepositoryUpdateBoolProperty is used for
-- private
-- archived
-- allow_auto_merge
-- delete_branch_on_merge
-- allow_update_branch
+- visibility (string)
+- archived (bool)
+- allow_auto_merge (bool)
+- delete_branch_on_merge (bool)
+- allow_update_branch (bool)
*/
-func (m *MutableGoliacRemoteImpl) UpdateRepositoryUpdateBoolProperty(reponame string, propertyName string, propertyValue bool) {
+func (m *MutableGoliacRemoteImpl) UpdateRepositoryUpdateProperty(reponame string, propertyName string, propertyValue interface{}) {
if r, ok := m.repositories[reponame]; ok {
- r.BoolProperties[propertyName] = propertyValue
+ if propertyName == "visibility" {
+ r.Visibility = propertyValue.(string)
+ } else {
+ r.BoolProperties[propertyName] = propertyValue.(bool)
+ }
}
}
func (m *MutableGoliacRemoteImpl) UpdateRepositorySetExternalUser(reponame string, collaboatorGithubId string, permission string) {
diff --git a/internal/engine/reconciliator_executor.go b/internal/engine/reconciliator_executor.go
index 106ea58..691a96b 100644
--- a/internal/engine/reconciliator_executor.go
+++ b/internal/engine/reconciliator_executor.go
@@ -17,8 +17,8 @@ type ReconciliatorExecutor interface {
UpdateTeamSetParent(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, teamslug string, parentTeam *int)
DeleteTeam(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, teamslug string)
- CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, writers []string, readers []string, boolProperties map[string]bool)
- UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue bool)
+ CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, visibility string, writers []string, readers []string, boolProperties map[string]bool)
+ UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue interface{})
UpdateRepositoryAddTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, teamslug string, permission string) // permission can be "pull", "push", or "admin" which correspond to read, write, and admin access.
UpdateRepositoryUpdateTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, teamslug string, permission string) // permission can be "pull", "push", or "admin" which correspond to read, write, and admin access.
UpdateRepositoryRemoveTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, teamslug string)
diff --git a/internal/engine/remote.go b/internal/engine/remote.go
index dadbe32..5a6787c 100644
--- a/internal/engine/remote.go
+++ b/internal/engine/remote.go
@@ -61,7 +61,8 @@ type GithubRepository struct {
Name string
Id int
RefId string
- BoolProperties map[string]bool // archived, private, allow_auto_merge, delete_branch_on_merge, allow_update_branch
+ Visibility string // public, internal, private
+ BoolProperties map[string]bool // archived, allow_auto_merge, delete_branch_on_merge, allow_update_branch
ExternalUsers map[string]string // [githubid]permission
InternalUsers map[string]string // [githubid]permission
RuleSets map[string]*GithubRuleSet // [name]ruleset
@@ -493,7 +494,7 @@ query listAllReposInOrg($orgLogin: String!, $endCursor: String) {
id
databaseId
isArchived
- isPrivate
+ visibility
autoMergeAllowed
deleteBranchOnMerge
allowUpdateBranch
@@ -608,7 +609,7 @@ type GraplQLRepositories struct {
Id string
DatabaseId int
IsArchived bool
- IsPrivate bool
+ Visibility string
AutoMergeAllowed bool
DeleteBranchOnMerge bool
AllowUpdateBranch bool
@@ -683,12 +684,12 @@ func (g *GoliacRemoteImpl) loadRepositories(ctx context.Context) (map[string]*Gi
for _, c := range gResult.Data.Organization.Repositories.Nodes {
repo := &GithubRepository{
- Name: c.Name,
- Id: c.DatabaseId,
- RefId: c.Id,
+ Name: c.Name,
+ Id: c.DatabaseId,
+ RefId: c.Id,
+ Visibility: strings.ToLower(c.Visibility),
BoolProperties: map[string]bool{
"archived": c.IsArchived,
- "private": c.IsPrivate,
"allow_auto_merge": c.AutoMergeAllowed,
"delete_branch_on_merge": c.DeleteBranchOnMerge,
"allow_update_branch": c.AllowUpdateBranch,
@@ -2360,14 +2361,13 @@ type CreateRepositoryResponse struct {
/*
boolProperties are:
-- private
- archived
- allow_auto_merge
- delete_branch_on_merge
- allow_update_branch
- ...
*/
-func (g *GoliacRemoteImpl) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, description string, writers []string, readers []string, boolProperties map[string]bool) {
+func (g *GoliacRemoteImpl) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, description string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
repoId := 0
repoRefId := reponame
// create repository
@@ -2376,6 +2376,7 @@ func (g *GoliacRemoteImpl) CreateRepository(ctx context.Context, errorCollector
props := map[string]interface{}{
"name": reponame,
"description": description,
+ "visibility": visibility,
}
for k, v := range boolProperties {
props[k] = v
@@ -2409,6 +2410,7 @@ func (g *GoliacRemoteImpl) CreateRepository(ctx context.Context, errorCollector
Name: reponame,
Id: repoId,
RefId: repoRefId,
+ Visibility: visibility,
BoolProperties: boolProperties,
}
g.repositories[reponame] = newRepo
@@ -2558,13 +2560,13 @@ func (g *GoliacRemoteImpl) UpdateRepositoryRemoveTeamAccess(ctx context.Context,
/*
Used for
-- private
-- allow_auto_merge
-- delete_branch_on_merge
-- allow_update_branch
-- archived
+- visibility (string)
+- allow_auto_merge (bool)
+- delete_branch_on_merge (bool)
+- allow_update_branch (bool)
+- archived (bool)
*/
-func (g *GoliacRemoteImpl) UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue bool) {
+func (g *GoliacRemoteImpl) UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue interface{}) {
// https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#update-a-repository
if !dryrun {
body, err := g.client.CallRestAPI(
@@ -2581,7 +2583,11 @@ func (g *GoliacRemoteImpl) UpdateRepositoryUpdateBoolProperty(ctx context.Contex
}
if repo, ok := g.repositories[reponame]; ok {
- repo.BoolProperties[propertyName] = propertyValue
+ if propertyName == "visibility" {
+ repo.Visibility = propertyValue.(string)
+ } else {
+ repo.BoolProperties[propertyName] = propertyValue.(bool)
+ }
}
}
diff --git a/internal/engine/remote_test.go b/internal/engine/remote_test.go
index 5bf9c3d..7fb7328 100644
--- a/internal/engine/remote_test.go
+++ b/internal/engine/remote_test.go
@@ -103,7 +103,7 @@ func (m *MockGithubClient) reposNodes(first, after string, args ast.ArgumentList
searchName, _ := hasChild("name", children)
searchArchived, _ := hasChild("isArchived", children)
- searchPrivate, _ := hasChild("isPrivate", children)
+ searchPrivate, _ := hasChild("visibility", children)
index := iAfter
totalCount := 0
@@ -120,7 +120,11 @@ func (m *MockGithubClient) reposNodes(first, after string, args ast.ArgumentList
block["isArchived"] = index%3 == 0 // let's pretend each 3 repo is an archive repo
}
if searchPrivate {
- block["isPrivate"] = index%10 == 0 // let's pretend each 10 repo is a private repo
+ if index%10 == 0 { // let's pretend each 10 repo is a private repo
+ block["visibility"] = "private"
+ } else {
+ block["visibility"] = "public"
+ }
}
index++
if index > maxToFake { // let's pretend we have maxToFake repos
@@ -447,8 +451,8 @@ func TestRemoteRepository(t *testing.T) {
assert.Equal(t, 133, len(repositories))
assert.Equal(t, false, repositories["repo_1"].BoolProperties["archived"])
assert.Equal(t, true, repositories["repo_3"].BoolProperties["archived"])
- assert.Equal(t, false, repositories["repo_1"].BoolProperties["private"])
- assert.Equal(t, true, repositories["repo_10"].BoolProperties["private"])
+ assert.Equal(t, "public", repositories["repo_1"].Visibility)
+ assert.Equal(t, "private", repositories["repo_10"].Visibility)
})
t.Run("happy path: load remote teams", func(t *testing.T) {
// MockGithubClient doesn't support concurrent access
diff --git a/internal/entity/repository.go b/internal/entity/repository.go
index dcdcd40..f594785 100644
--- a/internal/entity/repository.go
+++ b/internal/entity/repository.go
@@ -18,7 +18,7 @@ type Repository struct {
Readers []string `yaml:"readers,omitempty"`
ExternalUserReaders []string `yaml:"externalUserReaders,omitempty"`
ExternalUserWriters []string `yaml:"externalUserWriters,omitempty"`
- IsPublic bool `yaml:"public,omitempty"`
+ Visibility string `yaml:"visibility,omitempty"`
AllowAutoMerge bool `yaml:"allow_auto_merge,omitempty"`
DeleteBranchOnMerge bool `yaml:"delete_branch_on_merge,omitempty"`
AllowUpdateBranch bool `yaml:"allow_update_branch,omitempty"`
@@ -64,6 +64,7 @@ func NewRepository(fs billy.Filesystem, filename string) (*Repository, error) {
}
repository := &Repository{}
+ repository.Spec.Visibility = "private" // default visibility
err = yaml.Unmarshal(filecontent, repository)
if err != nil {
return nil, err
@@ -204,6 +205,11 @@ func (r *Repository) Validate(filename string, teams map[string]*Team, externalU
return fmt.Errorf("invalid name: %s for repository filename %s", r.Name, filename)
}
+ visibility := r.Spec.Visibility
+ if visibility != "public" && visibility != "private" && visibility != "internal" {
+ return fmt.Errorf("invalid visibility: %s for repository filename %s", visibility, filename)
+ }
+
for _, writer := range r.Spec.Writers {
if _, ok := teams[writer]; !ok {
return fmt.Errorf("invalid writer: %s doesn't exist (check repository filename %s)", writer, filename)
diff --git a/internal/github_batch_executor.go b/internal/github_batch_executor.go
index 36c784e..42710a2 100644
--- a/internal/github_batch_executor.go
+++ b/internal/github_batch_executor.go
@@ -118,12 +118,13 @@ func (g *GithubBatchExecutor) DeleteTeam(ctx context.Context, errorCollector *ob
})
}
-func (g *GithubBatchExecutor) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, description string, writers []string, readers []string, boolProperties map[string]bool) {
+func (g *GithubBatchExecutor) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, description string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
g.commands = append(g.commands, &GithubCommandCreateRepository{
client: g.client,
dryrun: dryrun,
reponame: reponame,
description: description,
+ visibility: visibility,
readers: readers,
writers: writers,
boolProperties: boolProperties,
@@ -159,8 +160,8 @@ func (g *GithubBatchExecutor) UpdateRepositoryRemoveTeamAccess(ctx context.Conte
})
}
-func (g *GithubBatchExecutor) UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue bool) {
- g.commands = append(g.commands, &GithubCommandUpdateRepositoryUpdateBoolProperty{
+func (g *GithubBatchExecutor) UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue interface{}) {
+ g.commands = append(g.commands, &GithubCommandUpdateRepositoryUpdateProperty{
client: g.client,
dryrun: dryrun,
reponame: reponame,
@@ -322,13 +323,14 @@ type GithubCommandCreateRepository struct {
dryrun bool
reponame string
description string
+ visibility string
writers []string
readers []string
boolProperties map[string]bool
}
func (g *GithubCommandCreateRepository) Apply(ctx context.Context, errorCollector *observability.ErrorCollection) {
- g.client.CreateRepository(ctx, errorCollector, g.dryrun, g.reponame, g.description, g.writers, g.readers, g.boolProperties)
+ g.client.CreateRepository(ctx, errorCollector, g.dryrun, g.reponame, g.description, g.visibility, g.writers, g.readers, g.boolProperties)
}
type GithubCommandCreateTeam struct {
@@ -454,16 +456,16 @@ func (g *GithubCommandUpdateRepositoryRemoveInternalUser) Apply(ctx context.Cont
g.client.UpdateRepositoryRemoveInternalUser(ctx, errorCollector, g.dryrun, g.reponame, g.githubid)
}
-type GithubCommandUpdateRepositoryUpdateBoolProperty struct {
+type GithubCommandUpdateRepositoryUpdateProperty struct {
client engine.ReconciliatorExecutor
dryrun bool
reponame string
propertyName string
- propertyValue bool
+ propertyValue interface{}
}
-func (g *GithubCommandUpdateRepositoryUpdateBoolProperty) Apply(ctx context.Context, errorCollector *observability.ErrorCollection) {
- g.client.UpdateRepositoryUpdateBoolProperty(ctx, errorCollector, g.dryrun, g.reponame, g.propertyName, g.propertyValue)
+func (g *GithubCommandUpdateRepositoryUpdateProperty) Apply(ctx context.Context, errorCollector *observability.ErrorCollection) {
+ g.client.UpdateRepositoryUpdateProperty(ctx, errorCollector, g.dryrun, g.reponame, g.propertyName, g.propertyValue)
}
type GithubCommandUpdateTeamAddMember struct {
diff --git a/internal/goliac.go b/internal/goliac.go
index da42b59..4a10326 100644
--- a/internal/goliac.go
+++ b/internal/goliac.go
@@ -338,7 +338,7 @@ func (g *GoliacImpl) applyCommitsToGithub(ctx context.Context, errorCollector *o
var unmanaged *engine.UnmanagedResources
ga := NewGithubBatchExecutor(g.remote, g.repoconfig.MaxChangesets)
- reconciliator := engine.NewGoliacReconciliatorImpl(ga, g.repoconfig)
+ reconciliator := engine.NewGoliacReconciliatorImpl(g.remote.IsEnterprise(), ga, g.repoconfig)
commit, err := g.local.GetHeadCommit()
if err != nil {
diff --git a/internal/goliac_server.go b/internal/goliac_server.go
index c85d720..a4e0aa3 100644
--- a/internal/goliac_server.go
+++ b/internal/goliac_server.go
@@ -134,9 +134,9 @@ func (g *GoliacServerImpl) GetRepositories(app.GetRepositoriesParams) middleware
for _, r := range local.Repositories() {
repo := models.Repository{
- Name: r.Name,
- Public: r.Spec.IsPublic,
- Archived: r.Archived,
+ Name: r.Name,
+ Visibility: r.Spec.Visibility,
+ Archived: r.Archived,
}
repositories = append(repositories, &repo)
}
@@ -198,7 +198,7 @@ func (g *GoliacServerImpl) GetRepository(params app.GetRepositoryParams) middlew
repositoryDetails := models.RepositoryDetails{
Name: repository.Name,
- Public: repository.Spec.IsPublic,
+ Visibility: repository.Spec.Visibility,
AutoMergeAllowed: repository.Spec.AllowAutoMerge,
DeleteBranchOnMerge: repository.Spec.DeleteBranchOnMerge,
AllowUpdateBranch: repository.Spec.AllowUpdateBranch,
@@ -295,7 +295,7 @@ func (g *GoliacServerImpl) GetTeam(params app.GetTeamParams) middleware.Responde
r := models.Repository{
Name: reponame,
Archived: repo.Archived,
- Public: repo.Spec.IsPublic,
+ Visibility: repo.Spec.Visibility,
AutoMergeAllowed: repo.Spec.AllowAutoMerge,
DeleteBranchOnMerge: repo.Spec.DeleteBranchOnMerge,
AllowUpdateBranch: repo.Spec.AllowUpdateBranch,
@@ -432,18 +432,18 @@ func (g *GoliacServerImpl) GetCollaborator(params app.GetCollaboratorParams) mid
for _, r := range repo.Spec.ExternalUserReaders {
if r == params.CollaboratorID {
collaboratordetails.Repositories = append(collaboratordetails.Repositories, &models.Repository{
- Name: repo.Name,
- Public: repo.Spec.IsPublic,
- Archived: repo.Archived,
+ Name: repo.Name,
+ Visibility: repo.Spec.Visibility,
+ Archived: repo.Archived,
})
}
}
for _, r := range repo.Spec.ExternalUserWriters {
if r == params.CollaboratorID {
collaboratordetails.Repositories = append(collaboratordetails.Repositories, &models.Repository{
- Name: repo.Name,
- Public: repo.Spec.IsPublic,
- Archived: repo.Archived,
+ Name: repo.Name,
+ Visibility: repo.Spec.Visibility,
+ Archived: repo.Archived,
})
}
}
@@ -547,9 +547,9 @@ func (g *GoliacServerImpl) GetUser(params app.GetUserParams) middleware.Responde
for _, r := range userRepos {
repo := models.Repository{
- Name: r.Name,
- Public: r.Spec.IsPublic,
- Archived: r.Archived,
+ Name: r.Name,
+ Visibility: r.Spec.Visibility,
+ Archived: r.Archived,
}
userdetails.Repositories = append(userdetails.Repositories, &repo)
}
diff --git a/internal/goliac_test.go b/internal/goliac_test.go
index b71b1f9..aad14d4 100644
--- a/internal/goliac_test.go
+++ b/internal/goliac_test.go
@@ -434,12 +434,12 @@ func (e *GoliacRemoteExecutorMock) Teams(ctx context.Context, current bool) map[
func (e *GoliacRemoteExecutorMock) Repositories(ctx context.Context) map[string]*engine.GithubRepository {
return map[string]*engine.GithubRepository{
"src": {
- Name: "src", // this is the "teams" repository
- Id: 0,
- RefId: "MDEwOlJlcG9zaXRvcnkaMTMxNjExOQ==",
+ Name: "src", // this is the "teams" repository
+ Id: 0,
+ RefId: "MDEwOlJlcG9zaXRvcnkaMTMxNjExOQ==",
+ Visibility: "private",
BoolProperties: map[string]bool{
"archived": false,
- "private": true,
"allow_auto_merge": false,
"delete_branch_on_merge": true,
"allow_update_branch": false,
@@ -458,12 +458,12 @@ func (e *GoliacRemoteExecutorMock) Repositories(ctx context.Context) map[string]
},
},
"repo1": {
- Name: "repo1",
- Id: 1,
- RefId: "MDEwOlJlcG9zaXRvcnkaMTMxNjExOQ==",
+ Name: "repo1",
+ Id: 1,
+ RefId: "MDEwOlJlcG9zaXRvcnkaMTMxNjExOQ==",
+ Visibility: "private",
BoolProperties: map[string]bool{
"archived": false,
- "private": true,
"allow_auto_merge": false,
"delete_branch_on_merge": false,
"allow_update_branch": false,
@@ -471,12 +471,12 @@ func (e *GoliacRemoteExecutorMock) Repositories(ctx context.Context) map[string]
ExternalUsers: map[string]string{},
},
"repo2": {
- Name: "repo2",
- Id: 2,
- RefId: "MDEwOlJlcG9zaXRvcnkaNTcwNDA4Ng==",
+ Name: "repo2",
+ Id: 2,
+ RefId: "MDEwOlJlcG9zaXRvcnkaNTcwNDA4Ng==",
+ Visibility: "private",
BoolProperties: map[string]bool{
"archived": false,
- "private": true,
"allow_auto_merge": false,
"delete_branch_on_merge": false,
"allow_update_branch": false,
@@ -586,12 +586,12 @@ func (e *GoliacRemoteExecutorMock) DeleteTeam(ctx context.Context, errorCollecto
e.nbChanges++
}
-func (e *GoliacRemoteExecutorMock) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, writers []string, readers []string, boolProperties map[string]bool) {
- fmt.Println("*** CreateRepository", reponame, descrition, writers, readers, boolProperties)
+func (e *GoliacRemoteExecutorMock) CreateRepository(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, descrition string, visibility string, writers []string, readers []string, boolProperties map[string]bool) {
+ fmt.Println("*** CreateRepository", reponame, descrition, visibility, writers, readers, boolProperties)
e.nbChanges++
}
-func (e *GoliacRemoteExecutorMock) UpdateRepositoryUpdateBoolProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue bool) {
- fmt.Println("*** UpdateRepositoryUpdateBoolProperty", reponame, propertyName, propertyValue)
+func (e *GoliacRemoteExecutorMock) UpdateRepositoryUpdateProperty(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, propertyName string, propertyValue interface{}) {
+ fmt.Println("*** UpdateRepositoryUpdateProperty", reponame, propertyName, propertyValue)
e.nbChanges++
}
func (e *GoliacRemoteExecutorMock) UpdateRepositoryAddTeamAccess(ctx context.Context, errorCollector *observability.ErrorCollection, dryrun bool, reponame string, teamslug string, permission string) {
diff --git a/internal/scaffold.go b/internal/scaffold.go
index defcc2d..cf8caf3 100644
--- a/internal/scaffold.go
+++ b/internal/scaffold.go
@@ -273,7 +273,7 @@ func (s *Scaffold) generateTeams(ctx context.Context, fs billy.Filesystem, teams
if rRepo, ok := rRepos[r]; ok {
// basic repository properties
- lRepo.Spec.IsPublic = rRepo.BoolProperties["public"]
+ lRepo.Spec.Visibility = rRepo.Visibility
lRepo.Spec.AllowAutoMerge = rRepo.BoolProperties["allow_auto_merge"]
lRepo.Spec.DeleteBranchOnMerge = rRepo.BoolProperties["delete_branch_on_merge"]
lRepo.Spec.AllowUpdateBranch = rRepo.BoolProperties["allow_update_branch"]
@@ -530,6 +530,10 @@ destructive_operations:
usersync:
plugin: %s
+
+#visibility_rules:
+# forbid_public_repositories: false
+# forbid_public_repositories_exclusions: [] # reponame or regexp
`, adminteam, userplugin)
if err := writeFile(filepath.Join(rootpath, "goliac.yaml"), []byte(conf), fs); err != nil {
return err
diff --git a/swagger/index.yaml b/swagger/index.yaml
index 5691858..9253c9d 100644
--- a/swagger/index.yaml
+++ b/swagger/index.yaml
@@ -112,8 +112,8 @@ definitions:
name:
type: string
x-isnullable: false
- public:
- type: boolean
+ visibility:
+ type: string
x-isnullable: false
x-omitempty: false
autoMergeAllowed:
@@ -145,8 +145,8 @@ definitions:
name:
type: string
x-isnullable: false
- public:
- type: boolean
+ visibility:
+ type: string
x-isnullable: false
x-omitempty: false
archived:
diff --git a/swagger_gen/models/repository.go b/swagger_gen/models/repository.go
index 683aa14..c8bda54 100644
--- a/swagger_gen/models/repository.go
+++ b/swagger_gen/models/repository.go
@@ -32,8 +32,8 @@ type Repository struct {
// name
Name string `json:"name,omitempty"`
- // public
- Public bool `json:"public"`
+ // visibility
+ Visibility string `json:"visibility"`
}
// Validate validates this repository
diff --git a/swagger_gen/models/repository_details.go b/swagger_gen/models/repository_details.go
index cd23db5..39cd1bc 100644
--- a/swagger_gen/models/repository_details.go
+++ b/swagger_gen/models/repository_details.go
@@ -38,11 +38,11 @@ type RepositoryDetails struct {
// name
Name string `json:"name,omitempty"`
- // public
- Public bool `json:"public"`
-
// teams
Teams []*RepositoryDetailsTeamsItems0 `json:"teams"`
+
+ // visibility
+ Visibility string `json:"visibility"`
}
// Validate validates this repository details
diff --git a/swagger_gen/restapi/embedded_spec.go b/swagger_gen/restapi/embedded_spec.go
index fecbf18..b48c523 100644
--- a/swagger_gen/restapi/embedded_spec.go
+++ b/swagger_gen/restapi/embedded_spec.go
@@ -484,8 +484,8 @@ func init() {
"type": "string",
"x-isnullable": false
},
- "public": {
- "type": "boolean",
+ "visibility": {
+ "type": "string",
"x-isnullable": false,
"x-omitempty": false
}
@@ -534,11 +534,6 @@ func init() {
"type": "string",
"x-isnullable": false
},
- "public": {
- "type": "boolean",
- "x-isnullable": false,
- "x-omitempty": false
- },
"teams": {
"type": "array",
"items": {
@@ -554,6 +549,11 @@ func init() {
}
}
}
+ },
+ "visibility": {
+ "type": "string",
+ "x-isnullable": false,
+ "x-omitempty": false
}
}
},
@@ -1352,8 +1352,8 @@ func init() {
"type": "string",
"x-isnullable": false
},
- "public": {
- "type": "boolean",
+ "visibility": {
+ "type": "string",
"x-isnullable": false,
"x-omitempty": false
}
@@ -1392,16 +1392,16 @@ func init() {
"type": "string",
"x-isnullable": false
},
- "public": {
- "type": "boolean",
- "x-isnullable": false,
- "x-omitempty": false
- },
"teams": {
"type": "array",
"items": {
"$ref": "#/definitions/RepositoryDetailsTeamsItems0"
}
+ },
+ "visibility": {
+ "type": "string",
+ "x-isnullable": false,
+ "x-omitempty": false
}
}
},