From 5e9d044b70ebf62a47a005631399a81a4bc9df54 Mon Sep 17 00:00:00 2001 From: Carlos Mecha Date: Thu, 28 Jun 2018 15:33:45 -0700 Subject: [PATCH 1/3] Archive repositories --- operations/README.md | 11 +++++ .../archive-integration-repository/main.go | 45 +++++++++++++++++++ operations/github.go | 37 +++++++++++++++ operations/integrationrepo.go | 20 +++++++++ 4 files changed, 113 insertions(+) create mode 100644 operations/cmd/archive-integration-repository/main.go diff --git a/operations/README.md b/operations/README.md index 38d949f43..cc02ad366 100644 --- a/operations/README.md +++ b/operations/README.md @@ -49,6 +49,17 @@ Options: - `--monorepoPath=`: Local path where the monorepo lives. Default to `.`. - `--tmpPath=`: Temporal folder. Default to `/tmp/integrations`. +## archive-integration-repository + +Archives the repository of the integration: +1. Removes all webhooks. +1. Archives the repository. + +Options: +- `--verbose` +- `--integration=` +- `--tmpPath=`: Temporal folder. Default to `/tmp/integrations`. + ## libgit2 Install libgit2 v27 following [this script](ci/install-libgit2). This is also required diff --git a/operations/cmd/archive-integration-repository/main.go b/operations/cmd/archive-integration-repository/main.go new file mode 100644 index 000000000..6284d15a7 --- /dev/null +++ b/operations/cmd/archive-integration-repository/main.go @@ -0,0 +1,45 @@ +package main + +import ( + "flag" + "os" + "path" + + "github.com/segmentio/analytics.js-integrations/operations" +) + +const organization = "segment-integrations" + +var integrationName string +var tmpPath string + +func init() { + flag.BoolVar(&operations.Verbose, "verbose", false, "prints more stuff") + flag.StringVar(&integrationName, "integration", "", "integration name") + flag.StringVar(&tmpPath, "tmpPath", "/tmp/integrations", "path where the integration code is going to be stored") +} + +func main() { + + operations.GetAuthToken() + + flag.Parse() + if integrationName == "" { + operations.Log("No integration provided") + flag.Usage() + os.Exit(1) + } + + github := operations.NewGitHubClient() + integration, err := operations.OpenIntegrationRepo(github, organization, integrationName, path.Join(tmpPath, integrationName)) + if err != nil { + os.Exit(1) + } + + operations.Log("Archiving %s", integration.RepositoryName) + + if err := integration.Archive(github); err != nil { + os.Exit(1) + } + +} diff --git a/operations/github.go b/operations/github.go index 4d524d91c..4881802d9 100644 --- a/operations/github.go +++ b/operations/github.go @@ -567,3 +567,40 @@ func (g *GitHub) UpdateTopics(topics []string, project Project) error { return nil } + +// DeleteAllWebHooks retrieves and deletes all webhooks for the project +func (g *GitHub) DeleteAllWebHooks(project Project) error { + ops := github.ListOptions{PerPage: 50} + hooks, _, err := g.V3.Repositories.ListHooks(context.Background(), project.Organization, project.RepositoryName, &ops) + if err != nil { + LogError(err, "Error listing hooks") + return err + } + + for _, hook := range hooks { + if _, err := g.V3.Repositories.DeleteHook(context.Background(), project.Organization, project.RepositoryName, *hook.ID); err != nil { + LogError(err, "Error removing hook %d", *hook.ID) + return err + } + } + + return nil +} + +// ArchiveRepository patches the repo and archives it +func (g *GitHub) ArchiveRepository(project Project) error { + if project.IsArchived { + return nil + } + + repo := github.Repository{ + Archived: github.Bool(true), + } + + if _, _, err := g.V3.Repositories.Edit(context.Background(), project.Organization, project.RepositoryName, &repo); err != nil { + LogError(err, "Error archiving repository %s", project.RepositoryName) + return err + } + + return nil +} diff --git a/operations/integrationrepo.go b/operations/integrationrepo.go index 0f3254b7c..733856742 100644 --- a/operations/integrationrepo.go +++ b/operations/integrationrepo.go @@ -1,6 +1,7 @@ package operations import ( + "errors" "fmt" "io/ioutil" "path" @@ -417,3 +418,22 @@ func (i *IntegrationRepo) updateIssueTemplate(monorepo Monorepo) error { return writeFileWithTemplate(file, i.issueTmpl, info) } + +// Archive archives the repo and removes webhooks. +func (i *IntegrationRepo) Archive(github *GitHub) error { + if i.IsArchived { + return nil + } + + if !i.IsMigrated() { + err := errors.New("The integration has not been migrated. Migrate the integration and then archive the repository") + LogError(err, "Unable to archive %s", i.Name) + return err + } + + if err := github.DeleteAllWebHooks(i.Project); err != nil { + return err + } + + return github.ArchiveRepository(i.Project) +} From ff8af5e859fa63f7436fd8f119fc6cd5ccc8a21d Mon Sep 17 00:00:00 2001 From: Carlos Mecha Date: Thu, 28 Jun 2018 15:50:43 -0700 Subject: [PATCH 2/3] Avoid running all tests in CI --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 415cab023..ecd49e426 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,13 @@ else $(eval export INTEGRATIONS := $(shell $(OPERATIONS_PREFIX)list-updated-integrations)) endif +# For now, we won't allow to run all tests in CI +ifneq ($(CI)$(INTEGRATIONS),true) $(KARMA) start $(KARMA_FLAGS) $(KARMA_CONF) --single-run; +else + @echo Nothing to test +endif + test-all: install $(KARMA) start $(KARMA_FLAGS) $(KARMA_CONF) --single-run; From 16f124dada54838f223ecff39cf32184915e0652 Mon Sep 17 00:00:00 2001 From: Carlos Mecha Date: Thu, 28 Jun 2018 16:06:56 -0700 Subject: [PATCH 3/3] Add boneyard operation --- operations/README.md | 9 ++++ .../boneyard-integration-repository/main.go | 46 +++++++++++++++++++ operations/github.go | 18 ++++++++ operations/integrationrepo.go | 11 +++++ 4 files changed, 84 insertions(+) create mode 100644 operations/cmd/boneyard-integration-repository/main.go diff --git a/operations/README.md b/operations/README.md index cc02ad366..baa9e4f4f 100644 --- a/operations/README.md +++ b/operations/README.md @@ -60,6 +60,15 @@ Options: - `--integration=` - `--tmpPath=`: Temporal folder. Default to `/tmp/integrations`. +## boneyard-integration-repository + +Moves the repository to the boneyard organization. + +Options: +- `--verbose` +- `--integration=` +- `--tmpPath=`: Temporal folder. Default to `/tmp/integrations`. + ## libgit2 Install libgit2 v27 following [this script](ci/install-libgit2). This is also required diff --git a/operations/cmd/boneyard-integration-repository/main.go b/operations/cmd/boneyard-integration-repository/main.go new file mode 100644 index 000000000..85795b749 --- /dev/null +++ b/operations/cmd/boneyard-integration-repository/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "os" + "path" + + "github.com/segmentio/analytics.js-integrations/operations" +) + +const organization = "segment-integrations" +const boneyard = "segment-boneyard" + +var integrationName string +var tmpPath string + +func init() { + flag.BoolVar(&operations.Verbose, "verbose", false, "prints more stuff") + flag.StringVar(&integrationName, "integration", "", "integration name") + flag.StringVar(&tmpPath, "tmpPath", "/tmp/integrations", "path where the integration code is going to be stored") +} + +func main() { + + operations.GetAuthToken() + + flag.Parse() + if integrationName == "" { + operations.Log("No integration provided") + flag.Usage() + os.Exit(1) + } + + github := operations.NewGitHubClient() + integration, err := operations.OpenIntegrationRepo(github, organization, integrationName, path.Join(tmpPath, integrationName)) + if err != nil { + os.Exit(1) + } + + operations.Log("Archiving %s", integration.RepositoryName) + + if err := integration.MoveToBoneyard(github, boneyard); err != nil { + os.Exit(1) + } + +} diff --git a/operations/github.go b/operations/github.go index 4881802d9..c60dff6e5 100644 --- a/operations/github.go +++ b/operations/github.go @@ -604,3 +604,21 @@ func (g *GitHub) ArchiveRepository(project Project) error { return nil } + +// Transfer moves the repository to another organization +func (g *GitHub) Transfer(project Project, organization string) error { + if project.Organization == organization { + return nil + } + + transfer := github.TransferRequest{ + NewOwner: organization, + } + + if _, _, err := g.V3.Repositories.Transfer(context.Background(), project.Organization, project.RepositoryName, transfer); err != nil { + LogError(err, "Error transfering repository %s", project.RepositoryName) + return err + } + + return nil +} diff --git a/operations/integrationrepo.go b/operations/integrationrepo.go index 733856742..b36d6e173 100644 --- a/operations/integrationrepo.go +++ b/operations/integrationrepo.go @@ -437,3 +437,14 @@ func (i *IntegrationRepo) Archive(github *GitHub) error { return github.ArchiveRepository(i.Project) } + +// MoveToBoneyard moves the repo to the boneyard organization only if it was archived and migrated. +func (i *IntegrationRepo) MoveToBoneyard(github *GitHub, boneyard string) error { + if !i.IsMigrated() || !i.IsArchived { + err := errors.New("The integration has not been migrated or archived. Migrate and archive the integration and then try again") + LogError(err, "Unable to move %s", i.Name) + return err + } + + return github.Transfer(i.Project, boneyard) +}