Skip to content

Commit

Permalink
initial commit on generating git issues on public repos
Browse files Browse the repository at this point in the history
  • Loading branch information
nawazkh committed Aug 2, 2023
1 parent 1567f68 commit 8441437
Show file tree
Hide file tree
Showing 6 changed files with 303 additions and 0 deletions.
41 changes: 41 additions & 0 deletions hack/tools/update_providers/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Go compiler
GO := go

# Name of your binary
BINARY_NAME := openGitIssues

# Directories
SRC_DIR := ./
BUILD_DIR := ./build
BIN_DIR := ./bin

# Source files
SRCS := $(shell find $(SRC_DIR) -name '*.go')

# TODO: update this in your local testing
# Variables
REPOSROOT := "/Users/nawazhussain/msftcode"

.PHONY: all build clean test

all: build

build: $(BIN_DIR)/$(BINARY_NAME)

$(BIN_DIR)/$(BINARY_NAME): $(SRCS)
@echo "Building $(BINARY_NAME)..."
@mkdir -p $(BUILD_DIR)
@mkdir -p $(BIN_DIR)
$(GO) build -o $(BUILD_DIR)/$(BINARY_NAME) $(SRC_DIR)
@mv $(BUILD_DIR)/$(BINARY_NAME) $(BIN_DIR)
@echo "Build complete."

clean:
@echo "Cleaning..."
@rm -rf $(BUILD_DIR)
@rm -rf $(BIN_DIR)
@echo "Clean complete."

test: clean all
@echo "Running \"${BINARY_NAME}\""
@./${BIN_DIR}/${BINARY_NAME} --dryRun="true" --token=${GITHUB_ISSUE_OPENER_TOKEN} --file ./repos.txt --title "Testing testing" --body issue_body.md
56 changes: 56 additions & 0 deletions hack/tools/update_providers/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# open_issues

`openGitIssues` is a go utility intended to open git issues on provider repos.

## Pre-requisites

- Create a github token which has a access to the following scopes.
- `repo:status` - Grants access to commit status on public and private repositories.
- `repo_deployment` - Grants access to deployment statuses on public and private repositories.
- `public_repo` - Grants access to public repositories
- [repos.txt](./repos.txt) is populated with list of public(or private) repositories
- If the issue is to be created against `https://github.com/my-org/public-repo`, _repos.txt_ should contain `my-org/public-repo`.
- Add a new repo at a new line in the file.
- decide upon the title of the issue to be opened.
- [issue_body.md](./issue_body.md) should have description of the issue in a markdown format.

## How to run the tool

- build the utility.

```go
go build open_issues.go
```

- run the utility

```bash
./openGitIssues --token $GITHUB_ISSUE_OPENER_TOKEN --dryRun="false" --file repos.txt --title "This is a test issue" --body issue_body.md
```

- dry run the utility to see the repos where the issues will be created.

```bash
> ./openGitIssues --token $GITHUB_ISSUE_OPENER_TOKEN --dryRun="true" --file repos.txt --title "This is a test issue" --body issue_body.md

###############################################
Dry run is enabled. No issues will be created.
###############################################

Creating issues for the following repositories:
kubernetes-sigs/cluster-api-provider-azure
```

## Sample output

```bash
./openGitIssues --token $GITHUB_ISSUE_OPENER_TOKEN --file repos.txt --title "This is a test issue" --body issue_body.md
Creating issues for the following repositories:
myorg/myrepo

Shall I continue creating issues? (y/n)
y

Issue created for repository 'myorg/myrepo'
URL: https://github.com/myorg/myrepo/issues/xxxx
```
3 changes: 3 additions & 0 deletions hack/tools/update_providers/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module update_capi_providers

go 1.20
22 changes: 22 additions & 0 deletions hack/tools/update_providers/issue_body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- body -->
CAPI `v1.5.0-beta.0` has been released and is ready for testing.
Looking forward to your feedback before CAPI 1.5.0 release, the 25th July 2023!

## For quick reference

- [CAPI v1.5.0-beta.0 release notes](https://github.com/kubernetes-sigs/cluster-api/releases/tag/v1.5.0-beta.0)
- [Shortcut to CAPI git issues](https://github.com/kubernetes-sigs/cluster-api/issues)

## Following are the planned dates for the upcoming releases

|Release|Expected Date|
|-----|-----|
|v1.5.0-beta.x | Tuesday 5th July 2023|
|release-1.5 branch created (Begin [Code Freeze])|Tuesday 11th July 2023|
|v1.5.0-rc.0 released|Tuesday 11th July 2023|
| release-1.5 jobs created | Tuesday 11th July 2023 |
| v1.5.0-rc.x released | Tuesday 18th July 2023 |
| v1.5.0 released | Tuesday 25th July 2023 |
<!-- body -->

<!-- [List of CAPI providers](https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/release/release-tasks.md#communicate-beta-to-providers) -->
166 changes: 166 additions & 0 deletions hack/tools/update_providers/open_issues.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package main

import (
"bufio"
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"strings"
)

const baseURL = "https://api.github.com"

type Issue struct {
Title string `json:"title"`
Body string `json:"body"`
}

type IssueResponse struct {
HTMLURL string `json:"html_url"`
}

func main() {
token := flag.String("token", "", "GitHub personal access token")
repoFile := flag.String("file", "", "Path to the text file containing the list of repositories")
issueTitle := flag.String("title", "", "Issue title")
issueFile := flag.String("body", "", "Path to the markdown file containing the issue body")
dryRun := flag.String("dryRun", "", "Dry run")
flag.Parse()

if *token == "" {
fmt.Println("GitHub personal access token is required.")
os.Exit(1)
}

if *repoFile == "" {
fmt.Println("Path to the text file containing the list of repositories is required.")
os.Exit(1)
}

if *issueTitle == "" {
fmt.Println("Issue title is required.")
os.Exit(1)
}

issueBody := ""
if *issueFile != "" {
fileContent, err := os.ReadFile(*issueFile)
if err != nil {
fmt.Printf("Failed to read file: %s\n", err)
os.Exit(1)
}
issueBody = string(fileContent)
}

repoList, err := readLines(*repoFile)
if err != nil {
fmt.Printf("Failed to read repository list: %s\n", err)
os.Exit(1)
}

if *dryRun == "true" {
fmt.Printf("\n")
fmt.Println("###############################################")
fmt.Println("Dry run is enabled. No issues will be created.")
fmt.Println("###############################################")
fmt.Printf("\n")
}

fmt.Println("\n\nCreating issues for the following repositories:")
fmt.Println(strings.Join(repoList, "\n"))
fmt.Printf("\n")

if *dryRun != "true" {
fmt.Println("Shall I continue creating issues? (y/n)")
var response string
fmt.Scanln(&response)
if response != "y" {
fmt.Println("Aborting...")
os.Exit(0)
}
}
fmt.Printf("\n")

for _, repo := range repoList {
issue := Issue{
Title: *issueTitle,
Body: issueBody,
}

issueJSON, err := json.Marshal(issue)
if err != nil {
fmt.Printf("Failed to marshal issue: %s\n", err)
os.Exit(1)
}

url := fmt.Sprintf("%s/repos/%s/issues", baseURL, repo)
if *dryRun == "true" {
continue
}

req, err := http.NewRequest("POST", url, bytes.NewBuffer(issueJSON))
// fmt.Println("Request will be sent at:", req.URL)
if err != nil {
fmt.Printf("Failed to create request: %s\n", err)
os.Exit(1)
}

req.Header.Set("Accept", "application/vnd.github+json")
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", *token))
req.Header.Set("X-Github-Api-Version", "2022-11-28")
req.Header.Set("User-Agent", "open_git_issues")
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("Failed to send request: %s\n", err)
os.Exit(1)
}

defer resp.Body.Close()
if resp.StatusCode != http.StatusCreated {
fmt.Printf("Failed to create issue for repository '%s'\nStatus code: %d\nStatus:%s\n\n\n", repo, resp.StatusCode, resp.Status)
} else {
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
fmt.Printf("Failed to read response body: %s\n", err)
os.Exit(1)
}

var issueResponse IssueResponse
err = json.Unmarshal(responseBody, &issueResponse)
if err != nil {
fmt.Printf("Failed to unmarshal issue response: %s\n", err)
os.Exit(1)
}

fmt.Printf("\nIssue created for repository '%s'\nURL: %s\n", repo, issueResponse.HTMLURL)
}
}
}

// readLines reads a text file and returns a slice of lines.
func readLines(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()

var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
lines = append(lines, line)
}

return lines, scanner.Err()
}
15 changes: 15 additions & 0 deletions hack/tools/update_providers/repos.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
kubernetes-sigs/cluster-api-addon-provider-helm
kubernetes-sigs/cluster-api-provider-aws
kubernetes-sigs/cluster-api-provider-azure
kubernetes-sigs/cluster-api-provider-cloudstack
kubernetes-sigs/cluster-api-provider-digitalocean
kubernetes-sigs/cluster-api-provider-gcp
kubernetes-sigs/cluster-api-provider-kubemark
kubernetes-sigs/cluster-api-provider-kubevirt
kubernetes-sigs/cluster-api-provider-ibmcloud
kubernetes-sigs/cluster-api-provider-nested
oracle/cluster-api-provider-oci
kubernetes-sigs/cluster-api-provider-openstack
kubernetes-sigs/cluster-api-operator
kubernetes-sigs/cluster-api-provider-packet
kubernetes-sigs/cluster-api-provider-vsphere

0 comments on commit 8441437

Please sign in to comment.