8000 Merge branch 'main' into telemetry · coder/coder@fcd6d08 · GitHub
[go: up one dir, main page]

Skip to content

Commit fcd6d08

Browse files
committed
Merge branch 'main' into telemetry
2 parents 5293285 + 10dc9e3 commit fcd6d08

File tree

150 files changed

+4728
-2569
lines changed
  • provisioner/terraform
  • scripts
  • site
  • Some content is hidden

    Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

    150 files changed

    +4728
    -2569
    lines changed

    .goreleaser.yaml

    Lines changed: 2 additions & 0 deletions
    Original file line numberDiff line numberDiff line change
    @@ -93,6 +93,8 @@ nfpms:
    9393
    type: "config|noreplace"
    9494
    - src: coder.service
    9595
    dst: /usr/lib/systemd/system/coder.service
    96+
    scripts:
    97+
    preinstall: preinstall.sh
    9698

    9799
    # Image templates are empty on snapshots to avoid lengthy builds for development.
    98100
    dockers:

    README.md

    Lines changed: 11 additions & 7 deletions
    Original file line numberDiff line numberDiff line change
    @@ -33,7 +33,7 @@ Coder creates remote development machines so your team can develop from anywhere
    3333
    > **Note**:
    3434
    > Coder is in an alpha state. [Report issues here](https://github.com/coder/coder/issues/new).
    3535
    36-
    There are a few ways to install Coder: [install script](./docs/install.md#installsh) (macOS, Linux), [docker-compose](./docs/install.md#docker-compose), or [manually](./docs/install.md#manual) via the latest release (macOS, Windows, and Linux).
    36+
    There are a few ways to install Coder: [install script](https://coder.com/docs/coder-oss/latest/install#installsh) (macOS, Linux), [docker-compose](https://coder.com/docs/coder-oss/latest/install#docker-compose), or [manually](https://coder.com/docs/coder-oss/latest/install#manual) via the latest release (macOS, Windows, and Linux).
    3737

    3838
    If you use the install script, you can preview what occurs during the install process:
    3939

    @@ -47,21 +47,25 @@ To install, run:
    4747
    curl -fsSL https://coder.com/install.sh | sh
    4848
    ```
    4949

    50-
    Once installed, you can run a temporary deployment in dev mode (all data is in-memory and destroyed on exit):
    50+
    Once installed, you can start a production deployment with a single command:
    5151

    5252
    ```sh
    53-
    coder server --dev
    53+
    # Automatically sets up an external access URL on *.try.coder.app
    54+
    coder server --tunnel
    55+
    56+
    # Requires a PostgreSQL instance and external access URL
    57+
    coder server --postgres-url <url> --access-url <url>
    5458
    ```
    5559

    56-
    Use `coder --help` to get a complete list of flags and environment variables. Use our [quickstart guide](./docs/quickstart.md) for a full walkthrough.
    60+
    Use `coder --help` to get a complete list of flags and environment variables. Use our [quickstart guide](https://coder.com/docs/coder-oss/latest/quickstart) for a full walkthrough.
    5761

    5862
    ## Documentation
    5963

    60-
    Visit our docs [here](./docs/index.md).
    64+
    Visit our docs [here](https://coder.com/docs/coder-oss).
    6165

    6266
    ## Comparison
    6367

    64-
    Please file [an issue](https://github.com/coder/coder/issues/new) if any information is out of date. Also refer to: [What Coder is not](./docs/about.md#what-coder-is-not).
    68+
    Please file [an issue](https://github.com/coder/coder/issues/new) if any information is out of date. Also refer to: [What Coder is not](https://coder.com/docs/coder-oss/latest/about#what-coder-is-not).
    6569

    6670
    | Tool | Type | Delivery Model | Cost | Environments |
    6771
    | :---------------------------------------------------------- | :------- | :----------------- | :---------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
    @@ -82,6 +86,6 @@ Join our community on [Discord](https://discord.gg/coder) and [Twitter](https://
    8286

    8387
    ## Contributing
    8488

    85-
    Read the [contributing docs](./docs/CONTRIBUTING.md).
    89+
    Read the [contributing docs](https://coder.com/docs/coder-oss/latest/CONTRIBUTING).
    8690

    8791
    Find our list of contributors [here](./docs/CONTRIBUTORS.md).

    cli/autostart.go

    Lines changed: 123 additions & 34 deletions
    Original file line numberDiff line numberDiff line change
    @@ -2,32 +2,41 @@ package cli
    22

    33
    import (
    44
    "fmt"
    5-
    "os"
    5+
    "strings"
    66
    "time"
    77

    88
    "github.com/spf13/cobra"
    9+
    "golang.org/x/xerrors"
    910

    1011
    "github.com/coder/coder/coderd/autobuild/schedule"
    12+
    "github.com/coder/coder/coderd/util/ptr"
    13+
    "github.com/coder/coder/coderd/util/tz"
    1114
    "github.com/coder/coder/codersdk"
    1215
    )
    1316

    1417
    const autostartDescriptionLong = `To have your workspace build automatically at a regular time you can enable autostart.
    15-
    When enabling autostart, provide the minute, hour, and day(s) of week.
    16-
    The default schedule is at 09:00 in your local timezone (TZ env, UTC by default).
    18+
    When enabling autostart, enter a schedule in the format: <start-time> [day-of-week] [location].
    19+
    * Start-time (required) is accepted either in 12-hour (hh:mm{am|pm}) format, or 24-hour format hh:mm.
    20+
    * Day-of-week (optional) allows specifying in the cron format, e.g. 1,3,5 or Mon-Fri.
    21+
    Aliases such as @daily are not supported.
    22+
    Default: * (every day)
    23+
    * Location (optional) must be a valid location in the IANA timezone database.
    24+
    If omitted, we will fall back to either the TZ environment variable or /etc/localtime.
    25+
    You can check your corresponding location by visiting https://ipinfo.io - it shows in the demo widget on the right.
    1726
    `
    1827

    1928
    func autostart() *cobra.Command {
    2029
    autostartCmd := &cobra.Command{
    2130
    Annotations: workspaceCommand,
    22-
    Use: "autostart enable <workspace>",
    31+
    Use: "autostart set <workspace> <start-time> [day-of-week] [location]",
    2332
    Short: "schedule a workspace to automatically start at a regular time",
    2433
    Long: autostartDescriptionLong,
    25-
    Example: "coder autostart enable my-workspace --minute 30 --hour 9 --days 1-5 --tz Europe/Dublin",
    34+
    Example: "coder autostart set my-workspace 9:30AM Mon-Fri Europe/Dublin",
    2635
    }
    2736

    2837
    autostartCmd.AddCommand(autostartShow())
    29-
    autostartCmd.AddCommand(autostartEnable())
    30-
    autostartCmd.AddCommand(autostartDisable())
    38+
    autostartCmd.AddCommand(autostartSet())
    39+
    autostartCmd.AddCommand(autostartUnset())
    3140

    3241
    return autostartCmd
    3342
    }
    @@ -60,13 +69,12 @@ func autostartShow() *cobra.Command {
    6069
    }
    6170

    6271
    next := validSchedule.Next(time.Now())
    63-
    loc, _ := time.LoadLocation(validSchedule.Timezone())
    6472

    6573
    _, _ = fmt.Fprintf(cmd.OutOrStdout(),
    6674
    "schedule: %s\ntimezone: %s\nnext: %s\n",
    6775
    validSchedule.Cron(),
    68-
    validSchedule.Timezone(),
    69-
    next.In(loc),
    76+
    validSchedule.Location(),
    77+
    next.In(validSchedule.Location()),
    7078
    )
    7179

    7280
    return nil
    @@ -75,23 +83,17 @@ func autostartShow() *cobra.Command {
    7583
    return cmd
    7684
    }
    7785

    78-
    func autostartEnable() *cobra.Command {
    79-
    // yes some of these are technically numbers but the cron library will do that work
    80-
    var autostartMinute string
    81-
    var autostartHour string
    82-
    var autostartDayOfWeek string
    83-
    var autostartTimezone string
    86+
    func autostartSet() *cobra.Command {
    8487
    cmd := &cobra.Command{
    85-
    Use: "enable <workspace_name> <schedule>",
    86-
    Args: cobra.ExactArgs(1),
    88+
    Use: "set <workspace_name> <start-time> [day-of-week] [location]",
    89+
    Args: cobra.RangeArgs(2, 4),
    8790
    RunE: func(cmd *cobra.Command, args []string) error {
    8891
    client, err := createClient(cmd)
    8992
    if err != nil {
    9093
    return err
    9194
    }
    9295

    93-
    spec := fmt.Sprintf("CRON_TZ=%s %s %s * * %s", autostartTimezone, autostartMinute, autostartHour, autostartDayOfWeek)
    94-
    validSchedule, err := schedule.Weekly(spec)
    96+
    sched, err := parseCLISchedule(args[1:]...)
    9597
    if err != nil {
    9698
    return err
    9799
    }
    @@ -102,32 +104,30 @@ func autostartEnable() *cobra.Command {
    102104
    }
    103105

    104106
    err = client.UpdateWorkspaceAutostart(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceAutostartRequest{
    105-
    Schedule: &spec,
    107+
    Schedule: ptr.Ref(sched.String()),
    106108
    })
    107109
    if err != nil {
    108110
    return err
    109111
    }
    110112

    111-
    _, _ = fmt.Fprintf(cmd.OutOrStdout(), "\nThe %s workspace will automatically start at %s.\n\n", workspace.Name, validSchedule.Next(time.Now()))
    112-
    113+
    schedNext := sched.Next(time.Now())
    114+
    _, _ = fmt.Fprintf(cmd.OutOrStdout(),
    115+
    "%s will automatically start at %s %s (%s)\n",
    116+
    workspace.Name,
    117+
    schedNext.In(sched.Location()).Format(time.Kitchen),
    118+
    sched.DaysOfWeek(),
    119+
    sched.Location().String(),
    120+
    )
    113121
    return nil
    114122
    },
    115123
    }
    116124

    117-
    cmd.Flags().StringVar(&autostartMinute, "minute", "0", "autostart minute")
    118-
    cmd.Flags().StringVar(&autostartHour, "hour", "9", "autostart hour")
    119-
    cmd.Flags().StringVar(&autostartDayOfWeek, "days", "1-5", "autostart day(s) of week")
    120-
    tzEnv := os.Getenv("TZ")
    121-
    if tzEnv == "" {
    122-
    tzEnv = "UTC"
    123-
    }
    124-
    cmd.Flags().StringVar(&autostartTimezone, "tz", tzEnv, "autostart timezone")
    125125
    return cmd
    126126
    }
    127127

    128-
    func autostartDisable() *cobra.Command {
    128+
    func autostartUnset() *cobra.Command {
    129129
    return &cobra.Command{
    130-
    Use: "disable <workspace_name>",
    130+
    Use: "unset <workspace_name>",
    131131
    Args: cobra.ExactArgs(1),
    132132
    RunE: func(cmd *cobra.Command, args []string) error {
    133133
    client, err := createClient(cmd)
    @@ -147,9 +147,98 @@ func autostartDisable() *cobra.Command {
    147147
    return err
    148148
    }
    149149

    150-
    _, _ = fmt.Fprintf(cmd.OutOrStdout(), "\nThe %s workspace will no longer automatically start.\n\n", workspace.Name)
    150+
    _, _ = fmt.Fprintf(cmd.OutOrStdout(), "%s will no longer automatically start.\n", workspace.Name)
    151151

    152152
    return nil
    153153
    },
    154154
    }
    155155
    }
    156+
    157+
    var errInvalidScheduleFormat = xerrors.New("Schedule must be in the format Mon-Fri 09:00AM America/Chicago")
    158+
    var errInvalidTimeFormat = xerrors.New("Start time must be in the format hh:mm[am|pm] or HH:MM")
    159+
    var errUnsupportedTimezone = xerrors.New("The location you provided looks like a timezone. Check https://ipinfo.io for your location.")
    160+
    161+
    // parseCLISchedule parses a schedule in the format HH:MM{AM|PM} [DOW] [LOCATION]
    162+
    func parseCLISchedule(parts ...string) (*schedule.Schedule, error) {
    163+
    // If the user was careful and quoted the schedule, un-quote it.
    164+
    // In the case that only time was specified, this will be a no-op.
    165+
    if len(parts) == 1 {
    166+
    parts = strings.Fields(parts[0])
    167+
    }
    168+
    var loc *time.Location
    169+
    dayOfWeek := "*"
    170+
    t, err := parseTime(parts[0])
    171+
    if err != nil {
    172+
    return nil, err
    173+
    }
    174+
    hour, minute := t.Hour(), t.Minute()
    175+
    176+
    // Any additional parts get ignored.
    177+
    switch len(parts) {
    178+
    case 3:
    179+
    dayOfWeek = parts[1]
    180+
    loc, err = time.LoadLocation(parts[2])
    181+
    if err != nil {
    182+
    _, err = time.Parse("MST", parts[2])
    183+
    if err == nil {
    184+
    return nil, errUnsupportedTimezone
    185+
    }
    186+
    return nil, xerrors.Errorf("Invalid timezone %q specified: a valid IANA timezone is required", parts[2])
    187+
    }
    188+
    case 2:
    189+
    // Did they provide day-of-week or location?
    190+
    if maybeLoc, err := time.LoadLocation(parts[1]); err != nil {
    191+
    // Assume day-of-week.
    192+
    dayOfWeek = parts[1]
    193+
    } else {
    194+
    loc = maybeLoc
    195+
    }
    196+
    case 1: // already handled
    197+
    default:
    198+
    return nil, errInvalidScheduleFormat
    199+
    }
    200+
    201+
    // If location was not specified, attempt to automatically determine it as a last resort.
    202+
    if loc == nil {
    203+
    loc, err = tz.TimezoneIANA()
    204+
    if err != nil {
    205+
    return nil, xerrors.Errorf("Could not automatically determine your timezone")
    206+
    }
    207+
    }
    208+
    209+
    sched, err := schedule.Weekly(fmt.Sprintf(
    210+
    "CRON_TZ=%s %d %d * * %s",
    211+
    loc.String(),
    212+
    minute,
    213+
    hour,
    214+
    dayOfWeek,
    215+
    ))
    216+
    if err != nil {
    217+
    // This will either be an invalid dayOfWeek or an invalid timezone.
    218+
    return nil, xerrors.Errorf("Invalid schedule: %w", err)
    219+
    }
    220+
    221+
    return sched, nil
    222+
    }
    223+
    224+
    func parseTime(s string) (time.Time, error) {
    225+
    // Try a number of possible layouts.
    226+
    for _, layout := range []string{
    227+
    time.Kitchen, // 03:04PM
    228+
    "03:04pm",
    229+
    "3:04PM",
    230+
    "3:04pm",
    231+
    "15:04",
    232+
    "1504",
    233+
    "03PM",
    234+
    "03pm",
    235+
    "3PM",
    236+
    "3pm",
    237+
    } {
    238+
    t, err := time.Parse(layout, s)
    239+
    if err == nil {
    240+
    return t, nil
    241+
    }
    242+
    }
    243+
    return time.Time{}, errInvalidTimeFormat
    244+
    }

    0 commit comments

    Comments
     (0)
    0