Skip to content

Commit 29d8726

Browse files
authored
Deploy done (#17)
1 parent 73fa4dc commit 29d8726

7 files changed

Lines changed: 171 additions & 11 deletions

File tree

clients/api/client.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,17 @@ func (c *Client) GetApplicationResources(applicationID string) (*GetApplicationR
239239
}
240240
return &resp, nil
241241
}
242+
243+
// CreateApplicationVersion creates a new version of an application
244+
func (c *Client) CreateApplicationVersion(applicationID string) (*CreateApplicationVersionResponse, error) {
245+
req := CreateApplicationVersionRequest{
246+
ApplicationID: applicationID,
247+
}
248+
249+
var resp CreateApplicationVersionResponse
250+
err := c.doRequest("POST", "/applications/versions", req, &resp)
251+
if err != nil {
252+
return nil, err
253+
}
254+
return &resp, nil
255+
}

clients/api/structs.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,13 @@ type ResourceItem struct {
9999
type GetApplicationResourcesResponse struct {
100100
Resources []ResourceItem `json:"resources"`
101101
}
102+
103+
// CreateApplicationVersionRequest represents the request body for POST /applications/versions
104+
type CreateApplicationVersionRequest struct {
105+
ApplicationID string `json:"applicationId"`
106+
}
107+
108+
// CreateApplicationVersionResponse represents the response from POST /applications/versions
109+
type CreateApplicationVersionResponse struct {
110+
VersionID string `json:"versionId"`
111+
}

clients/git/client.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,46 @@ func GetRepoRoot() (string, error) {
108108

109109
return strings.TrimSpace(string(output)), nil
110110
}
111+
112+
// IsGitRepository checks if the current directory is a git repository
113+
func IsGitRepository() bool {
114+
cmd := exec.Command("git", "rev-parse", "--git-dir")
115+
err := cmd.Run()
116+
return err == nil
117+
}
118+
119+
// HasUncommittedChanges checks if there are uncommitted changes in the repository
120+
func HasUncommittedChanges() (bool, error) {
121+
// Check for staged and unstaged changes
122+
cmd := exec.Command("git", "status", "--porcelain")
123+
output, err := cmd.Output()
124+
if err != nil {
125+
return false, err
126+
}
127+
128+
return len(strings.TrimSpace(string(output))) > 0, nil
129+
}
130+
131+
// Add stages all changes
132+
func Add() error {
133+
cmd := exec.Command("git", "add", ".")
134+
cmd.Stdout = os.Stdout
135+
cmd.Stderr = os.Stderr
136+
return cmd.Run()
137+
}
138+
139+
// Commit commits staged changes with the given message
140+
func Commit(message string) error {
141+
cmd := exec.Command("git", "commit", "-m", message)
142+
cmd.Stdout = os.Stdout
143+
cmd.Stderr = os.Stderr
144+
return cmd.Run()
145+
}
146+
147+
// PushToMain pushes commits to the remote repository on main branch
148+
func PushToMain() error {
149+
cmd := exec.Command("git", "push")
150+
cmd.Stdout = os.Stdout
151+
cmd.Stderr = os.Stderr
152+
return cmd.Run()
153+
}

cmd/app/app.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ func init() {
1818
Cmd.AddCommand(generateEnvCmd)
1919
Cmd.AddCommand(generateResourcesCmd)
2020
Cmd.AddCommand(startCmd)
21+
Cmd.AddCommand(deployCmd)
2122
}

cmd/app/deploy.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package app
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/charmbracelet/huh"
8+
"github.com/major-technology/cli/clients/api"
9+
"github.com/major-technology/cli/clients/git"
10+
"github.com/major-technology/cli/singletons"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
// deployCmd represents the deploy command
15+
var deployCmd = &cobra.Command{
16+
Use: "deploy",
17+
Short: "Deploy a new version of the application",
18+
Long: `Creates a new version by committing and pushing changes, then deploying to the platform.`,
19+
Run: func(cobraCmd *cobra.Command, args []string) {
20+
cobra.CheckErr(runDeploy(cobraCmd))
21+
},
22+
}
23+
24+
func runDeploy(cobraCmd *cobra.Command) error {
25+
// Check if we're in a git repository
26+
if !git.IsGitRepository() {
27+
return fmt.Errorf("not in a git repository")
28+
}
29+
30+
// Check for uncommitted changes
31+
hasChanges, err := git.HasUncommittedChanges()
32+
if err != nil {
33+
return fmt.Errorf("failed to check for uncommitted changes: %w", err)
34+
}
35+
36+
if hasChanges {
37+
cobraCmd.Println("📝 Uncommitted changes detected")
38+
39+
// Prompt for commit message
40+
var commitMessage string
41+
form := huh.NewForm(
42+
huh.NewGroup(
43+
huh.NewText().
44+
Title("Commit Message").
45+
Description("Enter a commit message for your changes").
46+
Value(&commitMessage).
47+
Validate(func(s string) error {
48+
if strings.TrimSpace(s) == "" {
49+
return fmt.Errorf("commit message is required")
50+
}
51+
return nil
52+
}),
53+
),
54+
)
55+
56+
if err := form.Run(); err != nil {
57+
return fmt.Errorf("failed to collect commit message: %w", err)
58+
}
59+
60+
// Stage all changes
61+
cobraCmd.Println("\nStaging changes...")
62+
if err := git.Add(); err != nil {
63+
return fmt.Errorf("failed to stage changes: %w", err)
64+
}
65+
cobraCmd.Println("✓ Changes staged")
66+
67+
// Commit changes
68+
cobraCmd.Println("Committing changes...")
69+
if err := git.Commit(commitMessage); err != nil {
70+
return fmt.Errorf("failed to commit changes: %w", err)
71+
}
72+
cobraCmd.Println("✓ Changes committed")
73+
74+
// Push to remote
75+
cobraCmd.Println("Pushing to remote...")
76+
if err := git.PushToMain(); err != nil {
77+
return fmt.Errorf("failed to push changes: %w", err)
78+
}
79+
cobraCmd.Println("✓ Changes pushed to remote")
80+
} else {
81+
cobraCmd.Println("✓ No uncommitted changes")
82+
}
83+
84+
// Get application ID
85+
cobraCmd.Println("\nDeploying new version...")
86+
applicationID, err := getApplicationID()
87+
if err != nil {
88+
return fmt.Errorf("failed to get application ID: %w", err)
89+
}
90+
91+
// Call API to create new version
92+
apiClient := singletons.GetAPIClient()
93+
resp, err := apiClient.CreateApplicationVersion(applicationID)
94+
if ok := api.CheckErr(cobraCmd, err); !ok {
95+
return err
96+
}
97+
98+
cobraCmd.Printf("\n✓ Version deployed successfully!\n")
99+
cobraCmd.Printf(" Version ID: %s\n", resp.VersionID)
100+
101+
return nil
102+
}

go.mod

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ go 1.24.2
44

55
require (
66
github.com/charmbracelet/huh v0.8.0
7-
github.com/google/go-github/v74 v74.0.0
87
github.com/pkg/errors v0.9.1
98
github.com/spf13/cobra v1.10.1
109
github.com/spf13/viper v1.21.0
1110
github.com/zalando/go-keyring v0.2.6
12-
golang.org/x/oauth2 v0.32.0
1311
)
1412

1513
require (
@@ -31,7 +29,7 @@ require (
3129
github.com/fsnotify/fsnotify v1.9.0 // indirect
3230
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
3331
github.com/godbus/dbus/v5 v5.1.0 // indirect
34-
github.com/google/go-querystring v1.1.0 // indirect
32+
github.com/google/go-cmp v0.7.0 // indirect
3533
github.com/inconshreveable/mousetrap v1.1.0 // indirect
3634
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
3735
github.com/mattn/go-isatty v0.0.20 // indirect

go.sum

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,8 @@ github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9L
5757
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
5858
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
5959
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
60-
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
6160
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
6261
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
63-
github.com/google/go-github/v74 v74.0.0 h1:yZcddTUn8DPbj11GxnMrNiAnXH14gNs559AsUpNpPgM=
64-
github.com/google/go-github/v74 v74.0.0/go.mod h1:ubn/YdyftV80VPSI26nSJvaEsTOnsjrxG3o9kJhcyak=
65-
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
66-
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
6762
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
6863
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
6964
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
@@ -129,8 +124,6 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
129124
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
130125
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
131126
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
132-
golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY=
133-
golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
134127
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
135128
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
136129
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -139,7 +132,6 @@ golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
139132
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
140133
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
141134
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
142-
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
143135
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
144136
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
145137
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

0 commit comments

Comments
 (0)