From d52308036eae2c53224cb0cb8e3d56ca395b0446 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 25 Sep 2024 11:44:02 -0700 Subject: [PATCH 1/5] [nix] Add detsys installer --- internal/boxcli/featureflag/detsys.go | 3 +++ internal/boxcli/featureflag/feature.go | 7 ++++++ internal/boxcli/setup.go | 8 ++++++- internal/nix/install.go | 31 +++++++++++++++++++++----- 4 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 internal/boxcli/featureflag/detsys.go diff --git a/internal/boxcli/featureflag/detsys.go b/internal/boxcli/featureflag/detsys.go new file mode 100644 index 00000000000..93fb1d1fc66 --- /dev/null +++ b/internal/boxcli/featureflag/detsys.go @@ -0,0 +1,3 @@ +package featureflag + +var UseDetSysInstaller = cicdOnly("DETSYS_INSTALLER") diff --git a/internal/boxcli/featureflag/feature.go b/internal/boxcli/featureflag/feature.go index 52d8c344102..d3b5a5321dc 100644 --- a/internal/boxcli/featureflag/feature.go +++ b/internal/boxcli/featureflag/feature.go @@ -43,6 +43,13 @@ func enable(name string) *feature { return features[name] } +func cicdOnly(name string) *feature { + if os.Getenv("CI") != "" || os.Getenv("CIRCLECI") != "" || os.Getenv("GITHUB_ACTIONS") != "" { + enable(name) + } + return disable(name) +} + var logMap = map[string]bool{} func (f *feature) Enabled() bool { diff --git a/internal/boxcli/setup.go b/internal/boxcli/setup.go index c20f50e3032..0e6a6ea838b 100644 --- a/internal/boxcli/setup.go +++ b/internal/boxcli/setup.go @@ -29,13 +29,19 @@ func setupCmd() *cobra.Command { }, } - installNixCommand.Flags().Bool(nixDaemonFlag, false, "Install Nix in multi-user mode.") + installNixCommand.Flags().Bool( + nixDaemonFlag, + false, + "Install Nix in multi-user mode. This flag is not supported if you are using DetSys installer", + ) setupCommand.AddCommand(installNixCommand) return setupCommand } func runInstallNixCmd(cmd *cobra.Command) error { if nix.BinaryInstalled() { + // TODO: If existing installation is not detsys, but new installation is detsys can we detect + // that and replace it? ux.Finfof( cmd.ErrOrStderr(), "Nix is already installed. If this is incorrect "+ diff --git a/internal/nix/install.go b/internal/nix/install.go index ddebb1b4901..b0591c9e277 100644 --- a/internal/nix/install.go +++ b/internal/nix/install.go @@ -16,6 +16,7 @@ import ( "github.com/mattn/go-isatty" "github.com/pkg/errors" + "go.jetpack.io/devbox/internal/boxcli/featureflag" "go.jetpack.io/devbox/internal/boxcli/usererr" "go.jetpack.io/devbox/internal/build" "go.jetpack.io/devbox/internal/cmdutil" @@ -39,11 +40,20 @@ func Install(writer io.Writer, daemon *bool) error { defer r.Close() installScript := "curl -L https://releases.nixos.org/nix/nix-2.18.1/install | sh -s" - if daemon != nil { - if *daemon { - installScript += " -- --daemon" - } else { - installScript += " -- --no-daemon" + if featureflag.UseDetSysInstaller.Enabled() { + // Should we pin version? Or just trust detsys + installScript = "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install" + if isLinuxWithoutSystemd() { + installScript += " linux --init none" + } + installScript += " --no-confirm" + } else { + if daemon != nil { + if *daemon { + installScript += " -- --daemon" + } else { + installScript += " -- --no-daemon" + } } } @@ -169,3 +179,14 @@ func EnsureNixInstalled(writer io.Writer, withDaemonFunc func() *bool) (err erro fmt.Fprintln(writer, "Nix installed successfully. Devbox is ready to use!") return nil } + +func isLinuxWithoutSystemd() bool { + if build.OS() != build.OSLinux { + return false + } + // My best interpretation of https://github.com/DeterminateSystems/nix-installer/blob/66ad2759a3ecb6da345373e3c413c25303305e25/src/action/common/configure_init_service.rs#L108-L118 + if _, err := os.Stat("/run/systemd/system"); errors.Is(err, os.ErrNotExist) { + return true + } + return !cmdutil.Exists("systemctl") +} From dcff55714e403c13de1266c3d0923125bb780f01 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 25 Sep 2024 11:45:11 -0700 Subject: [PATCH 2/5] Simplify --- internal/nix/install.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/internal/nix/install.go b/internal/nix/install.go index b0591c9e277..634dff69a84 100644 --- a/internal/nix/install.go +++ b/internal/nix/install.go @@ -47,13 +47,11 @@ func Install(writer io.Writer, daemon *bool) error { installScript += " linux --init none" } installScript += " --no-confirm" - } else { - if daemon != nil { - if *daemon { - installScript += " -- --daemon" - } else { - installScript += " -- --no-daemon" - } + } else if daemon != nil { + if *daemon { + installScript += " -- --daemon" + } else { + installScript += " -- --no-daemon" } } From 988cdf023ecd54c51f26c4385097ca0ca3ad01c4 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 25 Sep 2024 13:35:46 -0700 Subject: [PATCH 3/5] Use cicd matrix --- .github/workflows/cli-tests.yaml | 2 ++ internal/boxcli/featureflag/detsys.go | 2 +- internal/boxcli/featureflag/feature.go | 7 ------- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cli-tests.yaml b/.github/workflows/cli-tests.yaml index 635f66dd219..0365fccbcb4 100644 --- a/.github/workflows/cli-tests.yaml +++ b/.github/workflows/cli-tests.yaml @@ -183,6 +183,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-13] + use-detsys: [true, false] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -197,6 +198,7 @@ jobs: - name: Install nix and devbox packages run: | export NIX_INSTALLER_NO_CHANNEL_ADD=1 + export DEVBOX_FEATURE_DETSYS_INSTALLER=${{ matrix.use-detsys }} # Setup github authentication to ensure Github's rate limits are not hit. # If this works, we can consider refactoring this into a reusable github action helper. diff --git a/internal/boxcli/featureflag/detsys.go b/internal/boxcli/featureflag/detsys.go index 93fb1d1fc66..bfc8b457486 100644 --- a/internal/boxcli/featureflag/detsys.go +++ b/internal/boxcli/featureflag/detsys.go @@ -1,3 +1,3 @@ package featureflag -var UseDetSysInstaller = cicdOnly("DETSYS_INSTALLER") +var UseDetSysInstaller = disable("DETSYS_INSTALLER") diff --git a/internal/boxcli/featureflag/feature.go b/internal/boxcli/featureflag/feature.go index d3b5a5321dc..52d8c344102 100644 --- a/internal/boxcli/featureflag/feature.go +++ b/internal/boxcli/featureflag/feature.go @@ -43,13 +43,6 @@ func enable(name string) *feature { return features[name] } -func cicdOnly(name string) *feature { - if os.Getenv("CI") != "" || os.Getenv("CIRCLECI") != "" || os.Getenv("GITHUB_ACTIONS") != "" { - enable(name) - } - return disable(name) -} - var logMap = map[string]bool{} func (f *feature) Enabled() bool { From 09362de58b0809776bd2d88f43ca22f8eb367742 Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 25 Sep 2024 15:22:14 -0700 Subject: [PATCH 4/5] Show warning if no systemd --- internal/boxcli/setup.go | 2 +- internal/nix/install.go | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/boxcli/setup.go b/internal/boxcli/setup.go index 0e6a6ea838b..279b7c45c60 100644 --- a/internal/boxcli/setup.go +++ b/internal/boxcli/setup.go @@ -49,7 +49,7 @@ func runInstallNixCmd(cmd *cobra.Command) error { ) return nil } - return nix.Install(cmd.ErrOrStderr(), nixDaemonFlagVal(cmd)()) + return nix.Install(cmd.ErrOrStderr(), nixDaemonFlagVal(cmd)) } // ensureNixInstalled verifies that nix is installed and that it is of a supported version diff --git a/internal/nix/install.go b/internal/nix/install.go index e08fe2a973d..a64a07ef453 100644 --- a/internal/nix/install.go +++ b/internal/nix/install.go @@ -29,7 +29,7 @@ const rootError = "warning: installing Nix as root is not supported by this scri // Install runs the install script for Nix. daemon has 3 states // nil is unset. false is --no-daemon. true is --daemon. -func Install(writer io.Writer, daemon *bool) error { +func Install(writer io.Writer, daemon func() *bool) error { if isRoot() && build.OS() == build.OSWSL { return usererr.New("Nix cannot be installed as root on WSL. Please run as a normal user with sudo access.") } @@ -44,11 +44,15 @@ func Install(writer io.Writer, daemon *bool) error { // Should we pin version? Or just trust detsys installScript = "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install" if isLinuxWithoutSystemd() { + ux.Fwarningf( + writer, + "Could not detect systemd on your system. Installing Nix in root only mode (--init none).\n", + ) installScript += " linux --init none" } installScript += " --no-confirm" } else if daemon != nil { - if *daemon { + if *daemon() { installScript += " -- --daemon" } else { installScript += " -- --no-daemon" @@ -165,7 +169,7 @@ func EnsureNixInstalled(writer io.Writer, withDaemonFunc func() *bool) (err erro fmt.Scanln() //nolint:errcheck } - if err = Install(writer, withDaemonFunc()); err != nil { + if err = Install(writer, withDaemonFunc); err != nil { return err } From 50cc11fc8b9a7eb4944c87f1e15a7c782565d8ad Mon Sep 17 00:00:00 2001 From: Mike Landau Date: Wed, 25 Sep 2024 16:09:43 -0700 Subject: [PATCH 5/5] Fix npe --- internal/nix/install.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/nix/install.go b/internal/nix/install.go index a64a07ef453..32b0a483650 100644 --- a/internal/nix/install.go +++ b/internal/nix/install.go @@ -29,7 +29,7 @@ const rootError = "warning: installing Nix as root is not supported by this scri // Install runs the install script for Nix. daemon has 3 states // nil is unset. false is --no-daemon. true is --daemon. -func Install(writer io.Writer, daemon func() *bool) error { +func Install(writer io.Writer, daemonFn func() *bool) error { if isRoot() && build.OS() == build.OSWSL { return usererr.New("Nix cannot be installed as root on WSL. Please run as a normal user with sudo access.") } @@ -51,8 +51,8 @@ func Install(writer io.Writer, daemon func() *bool) error { installScript += " linux --init none" } installScript += " --no-confirm" - } else if daemon != nil { - if *daemon() { + } else if daemon := daemonFn(); daemon != nil { + if *daemon { installScript += " -- --daemon" } else { installScript += " -- --no-daemon"