-
Notifications
You must be signed in to change notification settings - Fork 894
cli: streamline autostart ux #2251
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
7c7a290
8983ef9
84f1a12
bad0ac2
68187d8
bcb1e8c
2556ba2
0884e0c
377b708
25ef437
4bab79f
e6921a7
9e76791
6a82f77
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,12 +15,12 @@ import ( | |
) | ||
|
||
const autostartDescriptionLong = `To have your workspace build automatically at a regular time you can enable autostart. | ||
When enabling autostart, enter a schedule in the format: [day-of-week] start-time [location]. | ||
* Start-time (required) is accepted either in 12-hour (hh:mm{am|pm}) format, or 24-hour format {hh:mm}. | ||
When enabling autostart, enter a schedule in the format: start-time [day-of-week] [timezone]. | ||
* Start-time (required) is accepted either in 12-hour (hh:mm{am|pm}) format, or 24-hour format hh:mm. | ||
* Day-of-week (optional) allows specifying in the cron format, e.g. 1,3,5 or Mon-Fri. | ||
Aliases such as @daily are not supported. | ||
Default: * (every day) | ||
* Location (optional) must be a valid location in the IANA timezone database. | ||
* Timezone (optional) must be a valid location in the IANA timezone database. | ||
If omitted, we will fall back to either the TZ environment variable or /etc/localtime. | ||
You can check your corresponding location by visiting https://ipinfo.io - it shows in the demo widget on the right. | ||
` | ||
|
@@ -85,8 +85,8 @@ func autostartShow() *cobra.Command { | |
|
||
func autostartSet() *cobra.Command { | ||
cmd := &cobra.Command{ | ||
Use: "set <workspace_name> ", | ||
Args: cobra.MinimumNArgs(2), | ||
Use: "set <workspace_name> <start-time> [day-of-week] [timezone]", | ||
Args: cobra.RangeArgs(2, 4), | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
client, err := createClient(cmd) | ||
if err != nil { | ||
|
@@ -112,10 +112,10 @@ func autostartSet() *cobra.Command { | |
|
||
schedNext := sched.Next(time.Now()) | ||
_, _ = fmt.Fprintf(cmd.OutOrStdout(), | ||
"%s will automatically start %s at %s (%s)\n", | ||
"%s will automatically start at %s %s (%s)\n", | ||
workspace.Name, | ||
sched.DaysOfWeek(), | ||
schedNext.In(sched.Location()).Format(time.Kitchen), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we always want to show am/pm here, even if 24h was used to define it? Or perhaps vary depending on defaults for the users system or selected location? Or perhaps we should have a user preference down the line? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sounds like an internationalization problem to me, which I'm going to place inside a tin can and kick down the road for later. 😅 But yes, yes we should. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think preference is very location-dependent. It would be unfortunate to add more state for am/pm. |
||
sched.DaysOfWeek(), | ||
sched.Location().String(), | ||
) | ||
return nil | ||
|
@@ -157,66 +157,53 @@ func autostartUnset() *cobra.Command { | |
var errInvalidScheduleFormat = xerrors.New("Schedule must be in the format Mon-Fri 09:00AM America/Chicago") | ||
var errInvalidTimeFormat = xerrors.New("Start time must be in the format hh:mm[am|pm] or HH:MM") | ||
|
||
// parseCLISchedule parses a schedule in the format Mon-Fri 09:00AM America/Chicago. | ||
// parseCLISchedule parses a schedule in the format HH:MM{AM|PM} [DOW] [LOCATION] | ||
func parseCLISchedule(parts ...string) (*schedule.Schedule, error) { | ||
// If the user was careful and quoted the schedule, un-quote it. | ||
// In the case that only time was specified, this will be a no-op. | ||
if len(parts) == 1 { | ||
parts = strings.Fields(parts[0]) | ||
} | ||
timezone := "" | ||
var loc *time.Location | ||
dayOfWeek := "*" | ||
var hour, minute int | ||
t, err := parseTime(parts[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
hour, minute := t.Hour(), t.Minute() | ||
|
||
// Any additional parts get ignored. | ||
switch len(parts) { | ||
case 1: | ||
t, err := parseTime(parts[0]) | ||
case 3: | ||
dayOfWeek = parts[1] | ||
loc, err = time.LoadLocation(parts[2]) | ||
if err != nil { | ||
return nil, err | ||
return nil, xerrors.Errorf("Invalid timezone %q specified: a valid IANA timezone is required", parts[2]) | ||
} | ||
hour, minute = t.Hour(), t.Minute() | ||
case 2: | ||
if !strings.Contains(parts[0], ":") { | ||
// DOW + Time | ||
t, err := parseTime(parts[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
hour, minute = t.Hour(), t.Minute() | ||
dayOfWeek = parts[0] | ||
// Did they provide day-of-week or location? | ||
if maybeLoc, err := time.LoadLocation(parts[1]); err != nil { | ||
// Assume day-of-week. | ||
dayOfWeek = parts[1] | ||
} else { | ||
// Time + TZ | ||
t, err := parseTime(parts[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
hour, minute = t.Hour(), t.Minute() | ||
timezone = parts[1] | ||
} | ||
case 3: | ||
// DOW + Time + TZ | ||
t, err := parseTime(parts[1]) | ||
if err != nil { | ||
return nil, err | ||
loc = maybeLoc | ||
} | ||
hour, minute = t.Hour(), t.Minute() | ||
dayOfWeek = parts[0] | ||
timezone = parts[2] | ||
case 1: // already handled | ||
default: | ||
return nil, errInvalidScheduleFormat | ||
} | ||
|
||
// If timezone was not specified, attempt to automatically determine it as a last resort. | ||
if timezone == "" { | ||
loc, err := tz.TimezoneIANA() | ||
// If location was not specified, attempt to automatically determine it as a last resort. | ||
if loc == nil { | ||
loc, err = tz.TimezoneIANA() | ||
if err != nil { | ||
return nil, xerrors.Errorf("Could not automatically determine your timezone.") | ||
return nil, xerrors.Errorf("Could not automatically determine your timezone") | ||
} | ||
timezone = loc.String() | ||
} | ||
|
||
sched, err := schedule.Weekly(fmt.Sprintf( | ||
"CRON_TZ=%s %d %d * * %s", | ||
timezone, | ||
loc.String(), | ||
minute, | ||
hour, | ||
dayOfWeek, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This help is ❤️.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is excellent.