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 f654dd5
Show file tree
Hide file tree
Showing 21 changed files with 1,452 additions and 97 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ jobs:
-
name: Make agents executable
run: |
sudo chmod -R +x ./bin/**/connect-client
sudo chmod -R +x ./bin/**/connect-client*
-
name: Agent build artifacts
uses: actions/upload-artifact@v3
Expand Down Expand Up @@ -353,7 +353,7 @@ jobs:
-
name: Make agents executable
run: |
chmod -R +x ./bin/**/connect-client
chmod -R +x ./bin/**/connect-client*
-
name: Restore Cache UX node_modules
id: node_modules
Expand Down Expand Up @@ -389,7 +389,7 @@ jobs:
-
name: Make agents executable
run: |
chmod -R +x ./bin/**/connect-client
chmod -R +x ./bin/**/connect-client*
-
name: Run Windows CLI Tests
env:
Expand Down Expand Up @@ -434,7 +434,7 @@ jobs:
-
name: Make agents executable
run: |
chmod -R +x ./bin/**/connect-client
chmod -R +x ./bin/**/connect-client*
-
name: Run MacOs CLI Tests
env:
Expand Down Expand Up @@ -539,7 +539,7 @@ jobs:
-
name: Make agents executable
run: |
chmod -R +x ./bin/**/connect-client
chmod -R +x ./bin/**/connect-client*
-
name: Cache docker image (restore)
id: cache-linux-amd64-image
Expand Down
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
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 f654dd5

Please sign in to comment.