Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEXT_CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
### CLI

### Bundles
* `bundle run` now prints the modern job run URL (`/jobs/<id>/runs/<id>`) so that non-admin users permitted to view the run are taken to the run instead of the workspace homepage.

### Dependency updates

Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/deploy/spark-jar-task/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run jar_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Spark Jar Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Spark Jar Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
4 changes: 2 additions & 2 deletions acceptance/bundle/integration_whl/base/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand All @@ -57,7 +57,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/integration_whl/custom_params/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job --python-params param1,param2
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand All @@ -57,7 +57,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand All @@ -26,7 +26,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand All @@ -54,7 +54,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
4 changes: 2 additions & 2 deletions acceptance/bundle/integration_whl/serverless/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "My Wheel Job" RUNNING
[TIMESTAMP] "My Wheel Job" TERMINATED SUCCESS
Expand All @@ -28,7 +28,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "My Wheel Job" RUNNING
[TIMESTAMP] "My Wheel Job" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job With Environments [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job With Environments [UNIQUE_NAME]" TERMINATED SUCCESS
Expand All @@ -17,7 +17,7 @@ Got arguments:
['my_test_code', 'one', 'two']

>>> [CLI] bundle run some_other_job --python-params=param1,param2
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job With Environments [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job With Environments [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "My Wheel Job" RUNNING
[TIMESTAMP] "My Wheel Job" TERMINATED SUCCESS
Expand All @@ -28,7 +28,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "My Wheel Job" RUNNING
[TIMESTAMP] "My Wheel Job" TERMINATED SUCCESS
Expand Down
2 changes: 1 addition & 1 deletion acceptance/bundle/integration_whl/wrapper/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[SOME_OTHER_JOB_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[SOME_OTHER_JOB_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run some_other_job --python-params param1,param2
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" RUNNING
[TIMESTAMP] "[default] Test Wheel Job [UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run foo
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[FOO_ID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[FOO_ID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "test-job-with-cluster-[UNIQUE_NAME]" RUNNING
[TIMESTAMP] "test-job-with-cluster-[UNIQUE_NAME]" TERMINATED SUCCESS
Expand Down
4 changes: 2 additions & 2 deletions acceptance/bundle/run/basic/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run foo
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "foo" RUNNING
[TIMESTAMP] "foo" TERMINATED SUCCESS
Expand All @@ -26,7 +26,7 @@ Exit code: 1

=== resource key with parameters
>>> [CLI] bundle run foo -- arg1 arg2
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "foo" RUNNING
[TIMESTAMP] "foo" TERMINATED SUCCESS
Expand Down
8 changes: 4 additions & 4 deletions acceptance/bundle/run/jobs/partial_run/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run my_job --only task_1
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "my_job" RUNNING
[TIMESTAMP] "my_job" TERMINATED SUCCESS
Expand All @@ -33,7 +33,7 @@ Hello from notebook2!
}

>>> [CLI] bundle run my_job --only task_1,task_2
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "my_job" RUNNING
[TIMESTAMP] "my_job" TERMINATED SUCCESS
Expand Down Expand Up @@ -61,7 +61,7 @@ Hello from notebook2!
}

>>> [CLI] bundle run my_job
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "my_job" RUNNING
[TIMESTAMP] "my_job" TERMINATED SUCCESS
Expand Down Expand Up @@ -91,7 +91,7 @@ Error: task "non_existent_task" not found in job "my_job"
Error: task "non_existent_task" not found in job "my_job"

>>> [CLI] bundle run my_job --only task1.table1,task2>,task3>table3
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "my_job" RUNNING
[TIMESTAMP] "my_job" TERMINATED SUCCESS
Expand Down
4 changes: 2 additions & 2 deletions acceptance/bundle/run/state-wiped/output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Updating deployment state...
Deployment complete!

>>> [CLI] bundle run foo
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "foo" RUNNING
[TIMESTAMP] "foo" TERMINATED SUCCESS
Expand All @@ -19,7 +19,7 @@ Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
>>> rm -fr .databricks

>>> [CLI] bundle run foo
Run URL: [DATABRICKS_URL]/?o=[NUMID]#job/[NUMID]/run/[NUMID]
Run URL: [DATABRICKS_URL]/jobs/[NUMID]/runs/[NUMID]?o=[NUMID]

[TIMESTAMP] "foo" RUNNING
[TIMESTAMP] "foo" TERMINATED SUCCESS
51 changes: 48 additions & 3 deletions bundle/run/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import (
"encoding/json"
"errors"
"fmt"
"net/url"
"strconv"
"strings"
"time"

"github.com/databricks/cli/bundle"
Expand All @@ -14,6 +16,7 @@ import (
"github.com/databricks/cli/bundle/run/progress"
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/cli/libs/log"
"github.com/databricks/cli/libs/workspaceurls"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -96,8 +99,9 @@ func (m *jobRunMonitor) onProgress(info *jobs.Run) {

// First time we see this run.
if m.prevState == nil {
log.Infof(m.ctx, "Run available at %s", info.RunPageUrl)
cmdio.Log(m.ctx, progress.NewJobRunUrlEvent(info.RunPageUrl))
runURL := runPageURL(m.ctx, info.RunPageUrl)
log.Infof(m.ctx, "Run available at %s", runURL)
cmdio.Log(m.ctx, progress.NewJobRunUrlEvent(runURL))
}

// No state change: do not log.
Expand All @@ -122,6 +126,47 @@ func (m *jobRunMonitor) onProgress(info *jobs.Run) {
log.Info(m.ctx, event.String())
}

// runPageURL converts the legacy run URL returned by the Jobs API
//
// https://<host>/?o=<id>#job/<jobID>/run/<runID>
//
// into the modern path form
//
// https://<host>/jobs/<jobID>/runs/<runID>?o=<id>
//
// so that non-admin users permitted to view the run are not redirected to the
// workspace homepage. See https://github.com/databricks/cli/issues/5142. The
// workspace selector query param (o) is preserved as-is. The conversion is
// cosmetic, so the original URL is returned on the rare chance the format is
// unexpected.
func runPageURL(ctx context.Context, raw string) string {
u, err := url.Parse(raw)
if err != nil {
log.Debugf(ctx, "could not parse run URL %q: %v", raw, err)
return raw
}

jobID, runID, ok := parseLegacyRunFragment(u.Fragment)
if !ok {
log.Debugf(ctx, "unexpected run URL fragment %q", u.Fragment)
return raw
}

u.Fragment = ""
u.Path = "/" + workspaceurls.JobRunPath(jobID, runID)
return u.String()
}

// parseLegacyRunFragment extracts the job and run IDs from a legacy run URL
// fragment of the form "job/<jobID>/run/<runID>".
func parseLegacyRunFragment(fragment string) (jobID, runID string, ok bool) {
parts := strings.Split(fragment, "/")
if len(parts) != 4 || parts[0] != "job" || parts[2] != "run" || parts[1] == "" || parts[3] == "" {
return "", "", false
}
return parts[1], parts[3], true
}

func (r *jobRunner) Run(ctx context.Context, opts *Options) (output.RunOutput, error) {
jobID, err := strconv.ParseInt(r.job.ID, 10, 64)
if err != nil {
Expand Down Expand Up @@ -160,7 +205,7 @@ func (r *jobRunner) Run(ctx context.Context, opts *Options) (output.RunOutput, e
if err != nil {
return nil, err
}
cmdio.Log(ctx, progress.NewJobRunUrlEvent(details.RunPageUrl))
cmdio.Log(ctx, progress.NewJobRunUrlEvent(runPageURL(ctx, details.RunPageUrl)))
return nil, nil
}

Expand Down
48 changes: 48 additions & 0 deletions bundle/run/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/databricks/cli/libs/cmdio"
"github.com/databricks/databricks-sdk-go/experimental/mocks"
"github.com/databricks/databricks-sdk-go/service/jobs"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -291,3 +292,50 @@ func TestJobRunnerRestartForContinuousUnpausedJobs(t *testing.T) {
_, err := runner.Restart(ctx, &Options{})
require.NoError(t, err)
}

func TestRunPageURL(t *testing.T) {
ctx := t.Context()
tests := []struct {
name string
raw string
expected string
}{
{
"legacy fragment form preserves workspace selector",
"https://myworkspace.databricks.test/?o=900800700600#job/123/run/456",
"https://myworkspace.databricks.test/jobs/123/runs/456?o=900800700600",
},
{
"no workspace selector",
"https://myworkspace.databricks.test/#job/123/run/456",
"https://myworkspace.databricks.test/jobs/123/runs/456",
},
{
"http host with port",
"http://127.0.0.1:8080/?o=900800700600#job/1/run/2",
"http://127.0.0.1:8080/jobs/1/runs/2?o=900800700600",
},
// Unexpected formats are returned unchanged because the conversion is cosmetic.
{
"already modern path is left as-is",
"https://myworkspace.databricks.test/jobs/123/runs/456?o=900800700600",
"https://myworkspace.databricks.test/jobs/123/runs/456?o=900800700600",
},
{
"incomplete fragment is left as-is",
"https://myworkspace.databricks.test/?o=900800700600#job/123",
"https://myworkspace.databricks.test/?o=900800700600#job/123",
},
{
"empty job id is left as-is",
"https://myworkspace.databricks.test/?o=900800700600#job//run/456",
"https://myworkspace.databricks.test/?o=900800700600#job//run/456",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.expected, runPageURL(ctx, tt.raw))
})
}
}
Loading
Loading