Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into tdstein/release
Browse files Browse the repository at this point in the history
  • Loading branch information
tdstein committed Sep 26, 2023
2 parents 53f6783 + 497ed81 commit e47aff9
Show file tree
Hide file tree
Showing 25 changed files with 1,461 additions and 101 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ on:
push:
branches:
- tdstein/release
workflow_call:
jobs:
release:
package:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
Expand All @@ -16,6 +17,4 @@ jobs:
- run: just build
- uses: actions/upload-artifact@v3
with:
path: |
bin/**/*.bin
bin/**/*.exe
path: bin
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -650,7 +650,7 @@ jobs:
-
name: Make agents executable
run: |
chmod -R +x ./bin/**/connect-client*
chmod -R +x ./bin/**/connect-client
# these are required to run docker on amd64 and arm64 platforms
-
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: Release
on:
push:
branches:
- tdstein/release
jobs:
package:
uses: ./.github/workflows/package.yaml
9 changes: 6 additions & 3 deletions cmd/connect-client/commands/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,8 @@ func (cmd *CreateBundleCmd) Run(args *cli_types.CommonArgs, ctx *cli_types.CLICo
if err != nil {
return err
}
return publish.CreateBundleFromDirectory(&cmd.PublishArgs, cmd.BundleFile, ctx.Logger)
publisher := publish.New(&cmd.PublishArgs)
return publisher.CreateBundleFromDirectory(cmd.BundleFile, ctx.Logger)
}

type WriteManifestCmd struct {
Expand All @@ -228,7 +229,8 @@ func (cmd *WriteManifestCmd) Run(args *cli_types.CommonArgs, ctx *cli_types.CLIC
if err != nil {
return err
}
return publish.WriteManifestFromDirectory(&cmd.PublishArgs, ctx.Logger)
publisher := publish.New(&cmd.PublishArgs)
return publisher.WriteManifestFromDirectory(ctx.Logger)
}

type PublishCmd struct {
Expand All @@ -240,7 +242,8 @@ func (cmd *PublishCmd) Run(args *cli_types.CommonArgs, ctx *cli_types.CLIContext
if err != nil {
return err
}
return publish.PublishDirectory(&cmd.PublishArgs, ctx.Accounts, ctx.Logger)
publisher := publish.New(&cmd.PublishArgs)
return publisher.PublishDirectory(ctx.Accounts, ctx.Logger)
}

type PublishUICmd struct {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/alecthomas/kong v0.7.1
github.com/chmike/securecookie v1.3.4
github.com/gobwas/glob v0.2.3
github.com/gorilla/mux v1.8.0
github.com/iriri/minimal/gitignore v0.3.2
github.com/mitchellh/mapstructure v1.5.0
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
Expand All @@ -17,7 +18,6 @@ require (

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
Expand Down
75 changes: 50 additions & 25 deletions internal/publish/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,40 @@ import (
"github.com/rstudio/connect-client/internal/util"
)

func CreateBundleFromDirectory(cmd *cli_types.PublishArgs, dest util.Path, log logging.Logger) error {
type Publisher struct {
args *cli_types.PublishArgs
}

func New(args *cli_types.PublishArgs) *Publisher {
return &Publisher{
args: args,
}
}

func (p *Publisher) CreateBundleFromDirectory(dest util.Path, log logging.Logger) error {
bundleFile, err := dest.Create()
if err != nil {
return err
}
defer bundleFile.Close()
bundler, err := bundles.NewBundler(cmd.State.SourceDir, &cmd.State.Manifest, cmd.Exclude, nil, log)
bundler, err := bundles.NewBundler(p.args.State.SourceDir, &p.args.State.Manifest, p.args.Exclude, nil, log)
if err != nil {
return err
}
_, err = bundler.CreateBundle(bundleFile)
return err
}

func WriteManifestFromDirectory(cmd *cli_types.PublishArgs, log logging.Logger) error {
bundler, err := bundles.NewBundler(cmd.State.SourceDir, &cmd.State.Manifest, cmd.Exclude, nil, log)
func (p *Publisher) WriteManifestFromDirectory(log logging.Logger) error {
bundler, err := bundles.NewBundler(p.args.State.SourceDir, &p.args.State.Manifest, p.args.Exclude, nil, log)
if err != nil {
return err
}
manifest, err := bundler.CreateManifest()
if err != nil {
return err
}
manifestPath := cmd.State.SourceDir.Join(bundles.ManifestFilename)
manifestPath := p.args.State.SourceDir.Join(bundles.ManifestFilename)
log.Info("Writing manifest", "path", manifestPath)
manifestJSON, err := manifest.ToJSON()
if err != nil {
Expand All @@ -62,7 +72,7 @@ type appInfo struct {
DirectURL string `json:"direct-url"`
}

func logAppInfo(accountURL string, contentID types.ContentID, log logging.Logger) error {
func (p *Publisher) logAppInfo(accountURL string, contentID types.ContentID, log logging.Logger) error {
appInfo := appInfo{
DashboardURL: fmt.Sprintf("%s/connect/#/apps/%s", accountURL, contentID),
DirectURL: fmt.Sprintf("%s/content/%s", accountURL, contentID),
Expand All @@ -82,25 +92,29 @@ func logAppInfo(accountURL string, contentID types.ContentID, log logging.Logger
return err
}

func PublishManifestFiles(cmd *cli_types.PublishArgs, lister accounts.AccountList, log logging.Logger) error {
bundler, err := bundles.NewBundlerForManifest(cmd.State.SourceDir, &cmd.State.Manifest, log)
func (p *Publisher) PublishManifestFiles(lister accounts.AccountList, log logging.Logger) error {
bundler, err := bundles.NewBundlerForManifest(p.args.State.SourceDir, &p.args.State.Manifest, log)
if err != nil {
return err
}
return publish(cmd, bundler, lister, log)
return p.publish(bundler, lister, log)
}

func PublishDirectory(cmd *cli_types.PublishArgs, lister accounts.AccountList, log logging.Logger) error {
log.Info("Publishing from directory", "path", cmd.State.SourceDir)
bundler, err := bundles.NewBundler(cmd.State.SourceDir, &cmd.State.Manifest, cmd.Exclude, nil, log)
func (p *Publisher) PublishDirectory(lister accounts.AccountList, log logging.Logger) error {
log.Info("Publishing from directory", "path", p.args.State.SourceDir)
bundler, err := bundles.NewBundler(p.args.State.SourceDir, &p.args.State.Manifest, p.args.Exclude, nil, log)
if err != nil {
return err
}
return publish(cmd, bundler, lister, log)
return p.publish(bundler, lister, log)
}

func publish(cmd *cli_types.PublishArgs, bundler bundles.Bundler, lister accounts.AccountList, log logging.Logger) error {
account, err := lister.GetAccountByName(cmd.State.Target.AccountName)
func (p *Publisher) publish(
bundler bundles.Bundler,
lister accounts.AccountList,
log logging.Logger) error {

account, err := lister.GetAccountByName(p.args.State.Target.AccountName)
if err != nil {
return err
}
Expand All @@ -110,7 +124,7 @@ func publish(cmd *cli_types.PublishArgs, bundler bundles.Bundler, lister account
if err != nil {
return err
}
err = publishWithClient(cmd, bundler, account, client, log)
err = p.publishWithClient(bundler, account, client, log)
if err != nil {
log.Failure(err)
}
Expand All @@ -121,7 +135,13 @@ type DeploymentNotFoundDetails struct {
ContentID types.ContentID
}

func withLog[T any](op events.Operation, msg string, label string, log logging.Logger, fn func() (T, error)) (value T, err error) {
func withLog[T any](
op events.Operation,
msg string,
label string,
log logging.Logger,
fn func() (T, error)) (value T, err error) {

log = log.WithArgs(logging.LogKeyOp, op)
log.Start(msg)
value, err = fn()
Expand All @@ -135,7 +155,12 @@ func withLog[T any](op events.Operation, msg string, label string, log logging.L
return value, nil
}

func publishWithClient(cmd *cli_types.PublishArgs, bundler bundles.Bundler, account *accounts.Account, client clients.APIClient, log logging.Logger) error {
func (p *Publisher) publishWithClient(
bundler bundles.Bundler,
account *accounts.Account,
client clients.APIClient,
log logging.Logger) error {

log.Start("Starting deployment to server",
logging.LogKeyOp, events.PublishOp,
"server", account.URL,
Expand All @@ -160,10 +185,10 @@ func publishWithClient(cmd *cli_types.PublishArgs, bundler bundles.Bundler, acco
}

var contentID types.ContentID
if cmd.State.Target.ContentId != "" && !cmd.New {
contentID = cmd.State.Target.ContentId
if p.args.State.Target.ContentId != "" && !p.args.New {
contentID = p.args.State.Target.ContentId
_, err := withLog(events.PublishCreateDeploymentOp, "Updating deployment", "content_id", log, func() (any, error) {
return contentID, client.UpdateDeployment(contentID, cmd.State.Connect.Content)
return contentID, client.UpdateDeployment(contentID, p.args.State.Connect.Content)
})
if err != nil {
httpErr, ok := err.(*clients.HTTPError)
Expand All @@ -177,7 +202,7 @@ func publishWithClient(cmd *cli_types.PublishArgs, bundler bundles.Bundler, acco
}
} else {
contentID, err = withLog(events.PublishCreateDeploymentOp, "Creating deployment", "content_id", log, func() (types.ContentID, error) {
return client.CreateDeployment(cmd.State.Connect.Content)
return client.CreateDeployment(p.args.State.Connect.Content)
})
if err != nil {
return err
Expand All @@ -192,7 +217,7 @@ func publishWithClient(cmd *cli_types.PublishArgs, bundler bundles.Bundler, acco
return err
}

cmd.State.Target = state.TargetID{
p.args.State.Target = state.TargetID{
ServerType: account.ServerType,
AccountName: account.Name,
ServerURL: account.URL,
Expand All @@ -210,11 +235,11 @@ func publishWithClient(cmd *cli_types.PublishArgs, bundler bundles.Bundler, acco
return err
}

taskLogger := log.WithArgs("source", "serverLog")
taskLogger := log.WithArgs("source", "serverp.log")
err = client.WaitForTask(taskID, taskLogger)
if err != nil {
return err
}
log = log.WithArgs(logging.LogKeyOp, events.AgentOp)
return logAppInfo(account.URL, contentID, log)
return p.logAppInfo(account.URL, contentID, log)
}
13 changes: 9 additions & 4 deletions internal/publish/publish_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ func (s *PublishSuite) TestCreateBundle() {
State: state.NewDeployment(),
}
cmd.State.SourceDir = s.cwd
err := CreateBundleFromDirectory(cmd, dest, s.log)
publisher := New(cmd)
err := publisher.CreateBundleFromDirectory(dest, s.log)
s.NoError(err)
s.True(dest.Exists())
}
Expand All @@ -70,7 +71,8 @@ func (s *PublishSuite) TestCreateBundleFailCreate() {
State: state.NewDeployment(),
}
cmd.State.SourceDir = s.cwd
err := CreateBundleFromDirectory(cmd, dest, s.log)
publisher := New(cmd)
err := publisher.CreateBundleFromDirectory(dest, s.log)
s.ErrorIs(err, testError)
}

Expand All @@ -83,7 +85,8 @@ func (s *PublishSuite) TestWriteManifest() {
}
cmd.State.SourceDir = s.cwd

err := WriteManifestFromDirectory(cmd, s.log)
publisher := New(cmd)
err := publisher.WriteManifestFromDirectory(s.log)
s.NoError(err)
s.True(manifestPath.Exists())

Expand Down Expand Up @@ -143,7 +146,9 @@ func (s *PublishSuite) publishWithClient(createErr, uploadErr, deployErr, waitEr
client.On("UploadBundle", myContentID, mock.Anything).Return(myBundleID, uploadErr)
client.On("DeployBundle", myContentID, myBundleID).Return(myTaskID, deployErr)
client.On("WaitForTask", myTaskID, mock.Anything).Return(waitErr)
err = publishWithClient(cmd, bundler, account, client, s.log)

publisher := New(cmd)
err = publisher.publishWithClient(bundler, account, client, s.log)
if expectedErr == nil {
s.NoError(err)
} else {
Expand Down
46 changes: 46 additions & 0 deletions internal/services/api/post_publish.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package api

// Copyright (C) 2023 by Posit Software, PBC.

import (
"encoding/json"
"net/http"

"github.com/rstudio/connect-client/internal/accounts"
"github.com/rstudio/connect-client/internal/cli_types"
"github.com/rstudio/connect-client/internal/logging"
"github.com/rstudio/connect-client/internal/state"
)

type PublishReponse struct {
LocalID state.LocalDeploymentID `json:"local_id"` // Unique ID of this publishing operation. Only valid for this run of the agent.
}

type ManifestFilesPublisher interface {
PublishManifestFiles(lister accounts.AccountList, log logging.Logger) error
}

func PostPublishHandlerFunc(publisher ManifestFilesPublisher, publishArgs *cli_types.PublishArgs, lister accounts.AccountList, log logging.Logger) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
localID, err := state.NewLocalID()
if err != nil {
InternalError(w, req, log, err)
return
}
publishArgs.State.LocalID = localID
response := PublishReponse{
LocalID: localID,
}
w.Header().Set("content-type", "application/json")
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(response)

go func() {
log = log.WithArgs("local_id", localID)
err := publisher.PublishManifestFiles(lister, log)
if err != nil {
log.Error("Deployment failed", "error", err.Error())
}
}()
}
}
Loading

0 comments on commit e47aff9

Please sign in to comment.