Skip to content

Commit

Permalink
feat: first official release
Browse files Browse the repository at this point in the history
  • Loading branch information
Sébastien HOUZÉ committed Aug 19, 2019
1 parent 6cc4a4c commit c463cee
Show file tree
Hide file tree
Showing 9 changed files with 730 additions and 2 deletions.
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,38 @@
# github
The (unofficial) Github command line client (based on Api V3)
# An (unofficial) Github command line client

This command line client is based on Github API V3.

## What it does

You can manipulate following Github resources:

- deployment
- deployment_status
- release

## What it will (probably) never do

Managing resources like pull requests, issues or repositories life cycle and settings.

Some very good tools like [hub](https://github.com/github/hub) or [terraform's github provider](https://www.terraform.io/docs/providers/github/index.html) are already great at doing that.

## Why another Github client?

The goal is to have a convenient, lightweight tool to use inside github [actions v2](https://github.com/features/actions) workflows.

Some use cases that motivated the creation of this tool were:

```shell
# Append some deploy button inside a release note
printf "%s\nDEPLOY_BUTTON_CODE" $(github release get ID | jq .body) | \
github release edit ID --body -

# Create a production deployment and corresponding status
DEPLOYMENT_ID=$(
github deployment create \
--environment production \
--task deploy:migration \
$GITHUB_REF
)
github deployment_status create $DEPLOYMENT_ID in_progress
```
128 changes: 128 additions & 0 deletions cmd/deployment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package cmd

import (
"encoding/json"
"fmt"
"log"
"os"
"strconv"

"github.com/google/go-github/v27/github"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var deployment = &cobra.Command{
Use: "deployment",
Short: "Deployment",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
os.Exit(0)
},
}

var deploymentGetCmd = &cobra.Command{
Use: "get ID",
Short: "Get a deployment",
Aliases: []string{"g"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
deploymentID, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatal(err)
}

deployment, _, err := client.Repositories.GetDeployment(ctx, owner, repository, deploymentID)
if err != nil {
log.Fatal(err)
}

json, err := json.MarshalIndent(deployment, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", json)
},
}

var deploymentListCmd = &cobra.Command{
Use: "list",
Short: "List deployments",
Aliases: []string{"ls"},
Run: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.PersistentFlags())
var deploymentsListOptions github.DeploymentsListOptions
err := viper.Unmarshal(&deploymentsListOptions)
if err != nil {
log.Fatal(err)
}

var listOptions github.ListOptions
err = viper.Unmarshal(&listOptions)
if err != nil {
log.Fatal(err)
}

deploymentsListOptions.ListOptions = listOptions

deployments, _, err := client.Repositories.ListDeployments(ctx, owner, repository, &deploymentsListOptions)
if err != nil {
log.Fatal(err)
}

json, err := json.MarshalIndent(deployments, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", json)
},
}

var deploymentCreateCmd = &cobra.Command{
Use: "create REF",
Short: "Create a deployment",
Aliases: []string{"c"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.PersistentFlags())

var deploymentRequest github.DeploymentRequest
err := viper.Unmarshal(&deploymentRequest)
deploymentRequest.Ref = &args[0]
if err != nil {
log.Fatal(err)
}

deployment, _, err := client.Repositories.CreateDeployment(ctx, owner, repository, &deploymentRequest)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Successfully created deployment: %v\n", deployment.GetID())
},
}

func init() {
deployment.Aliases = []string{"d"}

deployment.AddCommand(deploymentCreateCmd)
deploymentCreateCmd.PersistentFlags().StringP("task", "t", "deploy", "Specifies a task to execute (e.g., deploy or deploy:migrations).")
deploymentCreateCmd.PersistentFlags().BoolP("autoMerge", "a", true, "Attempts to automatically merge the default branch into the requested ref, if it's behind the default branch.")
deploymentCreateCmd.PersistentFlags().StringSliceP("requiredContexts", "c", []string{}, "The status contexts to verify against commit status checks. If you omit this parameter, GitHub verifies all unique contexts before creating a deployment. To bypass checking entirely, pass an empty array. Defaults to all unique contexts.")
deploymentCreateCmd.PersistentFlags().StringP("payload", "p", "", "JSON payload with extra information about the deployment.")
deploymentCreateCmd.PersistentFlags().StringP("environment", "e", "production", "Name for the target deployment environment (e.g., production, staging, qa).")
deploymentCreateCmd.PersistentFlags().StringP("description", "d", "", "Short description of the deployment.")
deploymentCreateCmd.PersistentFlags().Bool("transientEnvironment", false, "Specifies if the given environment is specific to the deployment and will no longer exist at some point in the future.")
deploymentCreateCmd.PersistentFlags().BoolP("productionEnvironment", "i", true, "Specifies if the given environment is one that end-users directly interact with. Default: true when environment is production and false otherwise.")

deployment.AddCommand(deploymentGetCmd)

deployment.AddCommand(deploymentListCmd)
deploymentListCmd.PersistentFlags().StringP("sha", "s", "", "sha of the deployment")
deploymentListCmd.PersistentFlags().StringP("ref", "", "", "list deployments for a given ref.")
deploymentListCmd.PersistentFlags().StringP("task", "t", "", "list deployments for a given task.")
deploymentListCmd.PersistentFlags().StringP("environment", "e", "", "list deployments for a given environment.")
deploymentListCmd.PersistentFlags().IntP("page", "p", 1, "for paginated result sets, page of results to retrieve.")
deploymentListCmd.PersistentFlags().IntP("perPage", "l", 10, "for paginated result sets, the number of results to include per page.")

rootCmd.AddCommand(deployment)
}
153 changes: 153 additions & 0 deletions cmd/deployment_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package cmd

import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"strconv"

"github.com/google/go-github/v27/github"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var deploymentStatus = &cobra.Command{
Use: "deployment_status",
Short: "Deployment Status",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
os.Exit(0)
},
}

var deploymentStatusListCmd = &cobra.Command{
Use: "list ID",
Short: "List deployment statuses",
Aliases: []string{"ls"},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
deploymentID, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatal(err)
}
pFlags := cmd.PersistentFlags()
page, err := pFlags.GetInt("page")
if err != nil {
log.Fatal(err)
}
perPage, err := pFlags.GetInt("perPage")
if err != nil {
log.Fatal(err)
}
listOptions := github.ListOptions{Page: page, PerPage: perPage}

deploymentStatuses, _, err := client.Repositories.ListDeploymentStatuses(ctx, owner, repository, deploymentID, &listOptions)
if err != nil {
log.Fatal(err)
}

json, err := json.MarshalIndent(deploymentStatuses, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", json)
},
}

var deploymentStatusGetCmd = &cobra.Command{
Use: "create DEPLOYMENT_ID DEPLOYMENT_STATUS_ID",
Short: "Get a single deployment status",
Aliases: []string{"g"},
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
deploymentID, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatal(err)
}

deploymentStatusID, err := strconv.ParseInt(args[1], 10, 64)
if err != nil {
log.Fatal(err)
}

deploymentStatus, _, err := client.Repositories.GetDeploymentStatus(ctx, owner, repository, deploymentID, deploymentStatusID)
if err != nil {
log.Fatal(err)
}

json, err := json.MarshalIndent(deploymentStatus, "", " ")
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", json)
},
}

func isValidState(state string) error {
switch state {
case
"error",
"failure",
"inactive",
"in_progress",
"queued",
"pending":
return nil
}

return errors.New("invalid state: should be one of error, failure, inactive, in_progress, queued or pending")
}

var deploymentStatusCreateCmd = &cobra.Command{
Use: "create DEPLOYMENT_ID STATE",
Short: "Create a deployment status",
Aliases: []string{"c"},
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
deploymentID, err := strconv.ParseInt(args[0], 10, 64)
if err != nil {
log.Fatal(err)
}

err = isValidState(args[1])
if err != nil {
log.Fatal(err)
}
state := args[1]

viper.BindPFlags(cmd.PersistentFlags())
var deploymentStatusRequest github.DeploymentStatusRequest
err = viper.Unmarshal(&deploymentStatusRequest)
deploymentStatusRequest.State = &state
if err != nil {
log.Fatal(err)
}

deploymentStatus, _, err := client.Repositories.CreateDeploymentStatus(ctx, owner, repository, deploymentID, &deploymentStatusRequest)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v\n", deploymentStatus.GetID())
},
}

func init() {
deploymentStatus.AddCommand(deploymentStatusGetCmd)

deploymentStatus.AddCommand(deploymentStatusListCmd)
deploymentStatusListCmd.PersistentFlags().IntP("page", "p", 1, "for paginated result sets, page of results to retrieve.")
deploymentStatusListCmd.PersistentFlags().IntP("perPage", "l", 10, "for paginated result sets, the number of results to include per page.")

deploymentStatus.AddCommand(deploymentStatusCreateCmd)
deploymentStatusCreateCmd.PersistentFlags().String("logURL", "", "The full URL of the deployment's output.")
deploymentStatusCreateCmd.PersistentFlags().StringP("description", "d", "", "A short description of the status. The maximum description length is 140 characters.")
deploymentStatusCreateCmd.PersistentFlags().StringP("environment", "e", "", "Name for the target deployment environment, which can be changed when setting a deploy status. For example, production, staging, or qa.")
deploymentStatusCreateCmd.PersistentFlags().StringP("environmentURL", "u", "", "for paginated result sets, page of results to retrieve.")
deploymentStatusCreateCmd.PersistentFlags().BoolP("autoInactive", "a", true, "Adds a new inactive status to all prior non-transient, non-production environment deployments with the same repository and environment name as the created status's deployment. An inactive status is only added to deployments that had a success state.")

deploymentStatus.Aliases = []string{"ds"}

rootCmd.AddCommand(deploymentStatus)
}
Loading

0 comments on commit c463cee

Please sign in to comment.