Skip to content

Commit

Permalink
feat: first iteration of the CLI (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
akoenig authored Mar 27, 2024
1 parent 5beaabf commit e41d1be
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 5 deletions.
22 changes: 22 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: "Build CLI"
on:
release:
types: [created]

permissions:
contents: write
packages: write

jobs:
release-linux-amd64:
name: release linux/amd64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: wangyoucao577/go-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: linux
goarch: amd64
project_path: ./cli
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cli/actions
17 changes: 17 additions & 0 deletions cli/.github/workflows/deploy-to-fly.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Fly!
uses: superfly/flyctl-actions/[email protected]
run: flyctl deploy --remote-only
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
17 changes: 17 additions & 0 deletions cli/core/domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package core

type Secret struct {
Description string `yaml:"description"`
}

type meta struct {
Id string `yaml:"id"`
Name string `yaml:"name"`
Description string `yaml:"description"`
Secrets map[string]Secret `yaml:"secrets"`
}

type Workflow struct {
Meta meta
Contents string
}
32 changes: 32 additions & 0 deletions cli/core/github.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package core

import (
"fmt"
"io"
"net/http"
)

func FetchWorkflowFileContents(id *string) (*string, error) {
response, error := http.Get("https://gist.githubusercontent.com/akoenig/c8173bfdb87f8809a9ab731bfed99a6f/raw/81cea0b7f6621ced4c34a49a7e679a07c5a7ceed/test.yaml")
// response, error := http.Get("https://api.github.com/repos/openformation/actions/contents/workflows/" + *id + ".yml")

if error != nil {
return nil, error
}

if response.StatusCode == 404 {
return nil, fmt.Errorf("the given workflow doesn't exist")
}

defer response.Body.Close()

body, error := io.ReadAll(response.Body)

if error != nil {
return nil, fmt.Errorf("reading the response from GitHub failed")
}

contents := string(body)

return &contents, nil
}
49 changes: 49 additions & 0 deletions cli/core/installer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package core

import (
"errors"
"fmt"
"os"
"path"
)

func InstallWorkflow(workflow *Workflow) error {
cwd, error := os.Getwd()

if error != nil {
return fmt.Errorf("failed to get the current working directory")
}

pathOfWorkflowFiles := path.Join(cwd, ".github", "workflows")
pathOfWorkflowFile := path.Join(pathOfWorkflowFiles, fmt.Sprintf("%s.yaml", workflow.Meta.Id))

{
_, error := os.Stat(pathOfWorkflowFile)

if errors.Is(error, os.ErrExist) {
return fmt.Errorf("the workflow already exists")
} else if !errors.Is(error, os.ErrNotExist) {
return fmt.Errorf("checking if the workflow already exists failed")
}
}

{
error := os.MkdirAll(pathOfWorkflowFiles, os.ModePerm)

if error != nil {
return fmt.Errorf("creating the directory for the workflow files failed")
}

}

{
error := os.WriteFile(pathOfWorkflowFile, []byte(workflow.Contents), os.ModePerm)

if error != nil {
return fmt.Errorf("writing the workflow file failed")
}

}

return nil
}
26 changes: 26 additions & 0 deletions cli/core/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package core

import (
"strings"

"github.com/adrg/frontmatter"
)

func ParseWorkflowFile(rawContents *string) (*Workflow, error) {
meta := meta{}

rest, error := frontmatter.Parse(strings.NewReader(*rawContents), &meta)

if error != nil {
return nil, error
}

contents := string(rest)

workflow := Workflow{
Meta: meta,
Contents: contents,
}

return &workflow, nil
}
16 changes: 16 additions & 0 deletions cli/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module openformation/actions

go 1.22.1

require (
github.com/adrg/frontmatter v0.2.0
github.com/fatih/color v1.16.0
)

require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/sys v0.14.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)
19 changes: 19 additions & 0 deletions cli/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/adrg/frontmatter v0.2.0 h1:/DgnNe82o03riBd1S+ZDjd43wAmC6W35q67NHeLkPd4=
github.com/adrg/frontmatter v0.2.0/go.mod h1:93rQCj3z3ZlwyxxpQioRKC1wDLto4aXHrbqIsnH9wmE=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
66 changes: 66 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package main

import (
"flag"
"fmt"
"openformation/actions/core"
"os"

"github.com/fatih/color"
)

func handleError(error error) {
if error != nil {
output := color.New(color.FgRed)

output.Println()
output.Println(fmt.Sprintf("\n ❌ An error occurred while installing the workflow: %s \n", error.Error()))

os.Exit(1)
}
}

func main() {
id := flag.String("id", "", "The ID of the workflow you want to install.")

flag.Parse()

if *id == "" {
flag.PrintDefaults()

os.Exit(1)
}

output := color.New(color.FgHiCyan)
output.Println(fmt.Sprintf("\n 🚀 Installing workflow '%s' ...", *id))

contents, error := core.FetchWorkflowFileContents(id)

handleError(error)

workflow, error := core.ParseWorkflowFile(contents)

handleError(error)

error = core.InstallWorkflow(workflow)

handleError(error)

output.Add(color.FgGreen).Println("\n ✅ Workflow installed successfully! Have fun! 🎉")
output.Println()

if workflow.Meta.Secrets != nil {
output.Add(color.FgRed).Println("\n Attention!")
output.Add(color.Reset).Println("\n This workflow requires you to add the following secrets. Head over to your repository settings to add them:")
output.Println()

for key, secret := range workflow.Meta.Secrets {
output.Add(color.FgYellow).Print(fmt.Sprintf(" %s: ", key))
output.Add(color.Reset).Printf("%s\n", secret.Description)
}

output.Println()

output.Add(color.ResetBlinking)
}
}
6 changes: 3 additions & 3 deletions devbox.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"$schema": "https://raw.githubusercontent.com/jetpack-io/devbox/0.10.1/.schema/devbox.schema.json",
"packages": []
}
"$schema": "https://raw.githubusercontent.com/jetpack-io/devbox/0.10.1/.schema/devbox.schema.json",
"packages": ["[email protected]"]
}
53 changes: 53 additions & 0 deletions devbox.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"lockfile_version": "1",
"packages": {
"[email protected]": {
"last_modified": "2024-03-22T11:26:23Z",
"resolved": "github:NixOS/nixpkgs/a3ed7406349a9335cb4c2a71369b697cecd9d351#go",
"source": "devbox-search",
"version": "1.22.1",
"systems": {
"aarch64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/n1k6wf8q10q7k0863gb78b1rf0j07r7r-go-1.22.1",
"default": true
}
],
"store_path": "/nix/store/n1k6wf8q10q7k0863gb78b1rf0j07r7r-go-1.22.1"
},
"aarch64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/fl6cjlp5bvykfz1kxrw687zxzld25pn7-go-1.22.1",
"default": true
}
],
"store_path": "/nix/store/fl6cjlp5bvykfz1kxrw687zxzld25pn7-go-1.22.1"
},
"x86_64-darwin": {
"outputs": [
{
"name": "out",
"path": "/nix/store/xgdp7gnf6vzr2ick2ip1lhq4cww65p7w-go-1.22.1",
"default": true
}
],
"store_path": "/nix/store/xgdp7gnf6vzr2ick2ip1lhq4cww65p7w-go-1.22.1"
},
"x86_64-linux": {
"outputs": [
{
"name": "out",
"path": "/nix/store/bp39dh48cdqp89hk5mpdi1lxdf0mjl7x-go-1.22.1",
"default": true
}
],
"store_path": "/nix/store/bp39dh48cdqp89hk5mpdi1lxdf0mjl7x-go-1.22.1"
}
}
}
}
}
3 changes: 1 addition & 2 deletions workflows/deployment/fly-io.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ name: "Deploy to fly.io"
description: "Deploys your application to fly.io"
secrets:
FLY_API_TOKEN:
description: "Your fly.io token which can be generated [here](https://fly.io/user/personal_access_tokens)".
required: true
description: "Your fly.io token which can be generated [here](https://fly.io/user/personal_access_tokens)"
---
on:
push:
Expand Down

0 comments on commit e41d1be

Please sign in to comment.