diff --git a/cli/util.go b/cli/util.go index aac8888b97..c7c75ae1c0 100644 --- a/cli/util.go +++ b/cli/util.go @@ -16,11 +16,11 @@ var errInvalidTimeFormat = xerrors.New("Start time must be in the format hh:mm[a var errUnsupportedTimezone = xerrors.New("The location you provided looks like a timezone. Check https://ipinfo.io for your location.") // durationDisplay formats a duration for easier display: -// * Durations of 24 hours or greater are displays as Xd -// * Durations less than 1 minute are displayed as <1m -// * Duration is truncated to the nearest minute -// * Empty minutes and seconds are truncated -// * The returned string is the absolute value. Use sign() +// - Durations of 24 hours or greater are displays as Xd +// - Durations less than 1 minute are displayed as <1m +// - Duration is truncated to the nearest minute +// - Empty minutes and seconds are truncated +// - The returned string is the absolute value. Use sign() // if you need to indicate if the duration is positive or // negative. func durationDisplay(d time.Duration) string { @@ -114,7 +114,7 @@ func parseCLISchedule(parts ...string) (*schedule.Schedule, error) { if loc == nil { loc, err = tz.TimezoneIANA() if err != nil { - return nil, xerrors.Errorf("Could not automatically determine your timezone") + loc = time.UTC } } diff --git a/coderd/util/tz/tz_linux.go b/coderd/util/tz/tz_linux.go index 06d7bfe648..0f4d0d7c73 100644 --- a/coderd/util/tz/tz_linux.go +++ b/coderd/util/tz/tz_linux.go @@ -33,7 +33,6 @@ func TimezoneIANA() (*time.Location, error) { if err != nil { return nil, xerrors.Errorf("read location of %s: %w", etcLocaltime, err) } - stripped := strings.Replace(lp, zoneInfoPath, "", -1) stripped = strings.TrimPrefix(stripped, string(filepath.Separator)) loc, err = time.LoadLocation(stripped) diff --git a/coderd/util/tz/tz_test.go b/coderd/util/tz/tz_test.go index 35f64843e4..cc7d9b69b4 100644 --- a/coderd/util/tz/tz_test.go +++ b/coderd/util/tz/tz_test.go @@ -2,6 +2,7 @@ package tz_test import ( "os" + "runtime" "testing" "github.com/stretchr/testify/assert" @@ -25,6 +26,11 @@ func Test_TimezoneIANA(t *testing.T) { //nolint:paralleltest // UnsetEnv t.Run("NoEnv", func(t *testing.T) { + _, err := os.Stat("/etc/localtime") + if runtime.GOOS == "linux" && err != nil { + // Not all Linux operating systems are guaranteed to have localtime! + t.Skip("localtime doesn't exist!") + } oldEnv, found := os.LookupEnv("TZ") if found { require.NoError(t, os.Unsetenv("TZ")) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index c9abc3d0d1..6d3a749ac5 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -4,6 +4,9 @@ Coder requires Go 1.18+, Node 14+, and GNU Make. +> **Note**: +> Use [Nix](https://nix.dev/) for a one-command setup: `nix-shell` + ### Development workflow Use the following `make` commands and scripts in development: diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..a9a9007753 --- /dev/null +++ b/flake.lock @@ -0,0 +1,94 @@ +{ + "nodes": { + "drpc": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1655479430, + "narHash": "sha256-ZQgJFlrddH2uQDQepDFYy3C+Ik/geMQgGWkLVhA9wss=", + "owner": "storj", + "repo": "drpc", + "rev": "0a6ae7bccab6f01ca6390a7a5bf9abeee71624d2", + "type": "github" + }, + "original": { + "owner": "storj", + "ref": "v0.0.32", + "repo": "drpc", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1634851050, + "narHash": "sha256-N83GlSGPJJdcqhUxSCS/WwW5pksYf3VP1M13cDRTSVA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c91f3de5adaf1de973b797ef7485e441a65b8935", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1659877975, + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1635797866, + "narHash": "sha256-e3vqt720wyb1PPNcGXej8wwip2/tgO1JsSGYK1NptSw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6751e7428f20328fed076acfcbb340d0f4aa0c07", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1659803779, + "narHash": "sha256-+5zkHlbcbFyN5f3buO1RAZ9pH1wXLxCesUJ0vFmLr9Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "f44884060cb94240efbe55620f38a8ec8d9af601", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "drpc": "drpc", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs_2" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..d3ce80f956 --- /dev/null +++ b/flake.nix @@ -0,0 +1,51 @@ +{ + description = "Development environments on your infrastructure"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + drpc.url = "github:storj/drpc/v0.0.32"; + }; + + outputs = { self, nixpkgs, flake-utils, drpc }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + { + formatter = pkgs.nixpkgs-fmt; + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + bat + drpc.defaultPackage.${system} + exa + git + go-migrate + go_1_19 + golangci-lint + gopls + gotestsum + helm + jq + nfpm + nodePackages.typescript + nodePackages.typescript-language-server + nodejs + openssh + openssl + postgresql + protoc-gen-go + ripgrep + shellcheck + shfmt + sqlc + terraform + typos + yarn + zip + zstd + ]; + }; + } + ); +} diff --git a/provisionersdk/agent_test.go b/provisionersdk/agent_test.go index 43fe411954..305813719f 100644 --- a/provisionersdk/agent_test.go +++ b/provisionersdk/agent_test.go @@ -46,6 +46,9 @@ func TestAgentScript(t *testing.T) { } script = strings.ReplaceAll(script, "${ACCESS_URL}", srvURL.String()+"/") script = strings.ReplaceAll(script, "${AUTH_TYPE}", "token") + // In certain distributions "echo" is a part of coreutils, and determines + // it's functionality based on the exec path name. + script = strings.ReplaceAll(script, "BINARY_NAME=coder", "BINARY_NAME=echo") // This is intentionally ran in single quotes to mimic how a customer may // embed our script. Our scripts should not include any single quotes. // nolint:gosec diff --git a/scripts/build_go_slim.sh b/scripts/build_go_slim.sh index 21d70b9918..753b719872 100755 --- a/scripts/build_go_slim.sh +++ b/scripts/build_go_slim.sh @@ -58,7 +58,7 @@ done # Check dependencies dependencies go if [[ $compress != 0 ]]; then - dependencies shasum tar zstd + dependencies openssl tar zstd if [[ $compress != [0-9]* ]] || [[ $compress -gt 22 ]] || [[ $compress -lt 1 ]]; then error "Invalid value for compress, must in in the range of [1, 22]" @@ -114,7 +114,7 @@ if [[ $compress != 0 ]]; then sha_file=coder.sha1 sha_dest="$dest_dir/$sha_file" log "--- Generating SHA1 for coder-slim binaries ($sha_dest)" - shasum -b -a 1 coder-* | tee $sha_file + openssl dgst -r -sha1 coder-* | tee $sha_file echo "$sha_dest" log log diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000000..a3a8864c7d --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +(import + ( + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/b4a34015c698c7793d592d66adbab377907a2be8.tar.gz"; + sha256 = "1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7"; + } + ) + { + src = ./.; + }).shellNix