Skip to content

refactor: bring back updated install.sh with patches #9583

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

Merged
merged 5 commits into from
Sep 7, 2023
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
81 changes: 81 additions & 0 deletions docs/install/install.sh.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,87 @@ manually via `coder server` or as a system package.
By default, the Coder server runs on `http://127.0.0.1:3000` and uses a
[public tunnel](../admin/configure.md#tunnel) for workspace connections.

## PATH conflicts

It's possible to end up in situations where you have multiple `coder` binaries
in your `PATH`, and your system may use a version that you don't intend. Your
`PATH` is a variable that tells your shell where to look for programs to run.

You can check where all of the versions are by running `which -a coder`.

For example, a common conflict on macOS might be between a version installed by
Homebrew, and a version installed manually to the /usr/local/bin directory.

```console
$ which -a coder
/usr/local/bin/coder
/opt/homebrew/bin/coder
```

Whichever binary comes first in this list will be used when running `coder`
commands.

### Reordering your PATH

If you use bash or zsh, you can update your `PATH` like this:

```shell
# You might want to add this line to the end of your ~/.bashrc or ~/.zshrc file!
export PATH="/opt/homebrew/bin:$PATH"
```

If you use fish, you can update your `PATH` like this:

```shell
# You might want to add this line to the end of your ~/.config/fish/config.fish file!
fish_add_path "/opt/homebrew/bin"
```

> ℹ If you ran install.sh with a `--prefix` flag, you can replace
> `/opt/homebrew` with whatever value you used there. Make sure to leave the
> `/bin` at the end!

Now we can observe that the order has changed:

```console
$ which -a coder
/opt/homebrew/bin/coder
/usr/local/bin/coder
```

### Removing unneeded binaries

If you want to uninstall a version of `coder` that you installed with a package
manager, you can run whichever one of these commands applies:

```shell
# On macOS, with Homebrew installed
brew uninstall coder
```

```shell
# On Debian/Ubuntu based systems
sudo dpkg -r coder
```

```shell
# On Fedora/RHEL-like systems
sudo rpm -e coder
```

```shell
# On Alpine
sudo apk del coder
```

If the conflicting binary is not installed by your system package manager, you
can just delete it.

```shell
# You might not need `sudo`, depending on the location
sudo rm /usr/local/bin/coder
```

## Next steps

- [Configuring Coder](../admin/configure.md)
Expand Down
116 changes: 88 additions & 28 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,35 @@ echo_standalone_postinstall() {

cath <<EOF

Standalone release has been installed into $STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME
Coder has been installed to

$STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME

EOF

if [ "$STANDALONE_INSTALL_PREFIX" != /usr/local ]; then
CODER_COMMAND="$(command -v "$STANDALONE_BINARY_NAME" || true)"

if [ -z "${CODER_COMMAND}" ]; then
cath <<EOF
Extend your path to use Coder:
PATH="$STANDALONE_INSTALL_PREFIX/bin:\$PATH"

$ PATH="$STANDALONE_INSTALL_PREFIX/bin:\$PATH"

EOF
fi
cath <<EOF
Run Coder:
$STANDALONE_BINARY_NAME server
elif [ "$CODER_COMMAND" != "$STANDALONE_BINARY_LOCATION" ]; then
echo_path_conflict "$CODER_COMMAND"
else
cath <<EOF
To run a Coder server:

$ $STANDALONE_BINARY_NAME server

To connect to a Coder deployment:

$ $STANDALONE_BINARY_NAME login <deployment url>

EOF
fi
}

echo_brew_postinstall() {
Expand All @@ -124,9 +137,23 @@ echo_brew_postinstall() {
return
fi

BREW_PREFIX="$(brew --prefix)"

cath <<EOF
brew formula has been installed.

Coder has been installed to

$BREW_PREFIX/bin/coder

EOF

CODER_COMMAND="$(command -v "coder" || true)"

if [ "$CODER_COMMAND" != "$BREW_PREFIX/bin/coder" ]; then
echo_path_conflict "$CODER_COMMAND"
fi

cath <<EOF
To run a Coder server:

$ coder server
Expand Down Expand Up @@ -157,7 +184,6 @@ To run a Coder server:
# Or just run the server directly
$ coder server

Default URL: http://127.0.0.1:3000
Configuring Coder: https://coder.com/docs/v2/latest/admin/configure

To connect to a Coder deployment:
Expand All @@ -169,28 +195,45 @@ EOF

echo_dryrun_postinstall() {
cath <<EOF

Dry-run complete.

To install Coder, re-run this script without the --dry-run flag.

EOF
}

echo_path_conflict() {
cath <<EOF
There is another binary in your PATH that conflicts with the binary we've installed.

$1

This is likely because of an existing installation of Coder. See our documentation for suggestions on how to resolve this.

https://coder.com/docs/v2/latest/install/install.sh#path-conflicts

EOF
}

main() {
TERRAFORM_VERSION="1.3.4"

if [ "${TRACE-}" ]; then
set -x
fi

unset \
DRY_RUN \
METHOD \
OPTIONAL \
ALL_FLAGS \
RSH_ARGS \
EDGE \
RSH
RSH \
WITH_TERRAFORM

ALL_FLAGS=""

while [ "$#" -gt 0 ]; do
case "$1" in
-*)
Expand Down Expand Up @@ -245,7 +288,7 @@ main() {
exit 0
;;
--with-terraform)
METHOD=with_terraform
WITH_TERRAFORM=1
;;
--)
shift
Expand Down Expand Up @@ -275,8 +318,29 @@ main() {
return
fi

# These can be overridden for testing but shouldn't normally be used as it can
# result in a broken coder.
OS=${OS:-$(os)}
ARCH=${ARCH:-$(arch)}
TERRAFORM_ARCH=${TERRAFORM_ARCH:-$(terraform_arch)}

# We can't reasonably support installing specific versions of Coder through
# Homebrew, so if we're on macOS and the `--version` flag was set, we should
# "detect" standalone to be the appropriate installation method. This check
# needs to occur before we set `VERSION` to a default of the latest release.
if [ "$OS" = "darwin" ] && [ "${VERSION-}" ]; then
METHOD=standalone
fi

# If we've been provided a flag which is specific to the standalone installation
# method, we should "detect" standalone to be the appropriate installation method.
# This check needs to occur before we set these variables with defaults.
if [ "${STANDALONE_INSTALL_PREFIX-}" ] || [ "${STANDALONE_BINARY_NAME-}" ]; then
METHOD=standalone
fi

METHOD="${METHOD-detect}"
if [ "$METHOD" != detect ] && [ "$METHOD" != with_terraform ] && [ "$METHOD" != standalone ]; then
if [ "$METHOD" != detect ] && [ "$METHOD" != standalone ]; then
echoerr "Unknown install method \"$METHOD\""
echoerr "Run with --help to see usage."
exit 1
Expand All @@ -285,15 +349,10 @@ main() {
# These are used by the various install_* functions that make use of GitHub
# releases in order to download and unpack the right release.
CACHE_DIR=$(echo_cache_dir)
STANDALONE_INSTALL_PREFIX=${STANDALONE_INSTALL_PREFIX:-/usr/local}
TERRAFORM_INSTALL_PREFIX=${TERRAFORM_INSTALL_PREFIX:-/usr/local}
STANDALONE_INSTALL_PREFIX=${STANDALONE_INSTALL_PREFIX:-/usr/local}
STANDALONE_BINARY_NAME=${STANDALONE_BINARY_NAME:-coder}
VERSION=${VERSION:-$(echo_latest_version)}
# These can be overridden for testing but shouldn't normally be used as it can
# result in a broken coder.
OS=${OS:-$(os)}
ARCH=${ARCH:-$(arch)}
TERRAFORM_ARCH=${TERRAFORM_ARCH:-$(terraform_arch)}

distro_name

Expand All @@ -302,6 +361,11 @@ main() {
echoh
fi

# Start by installing Terraform, if requested
if [ "${WITH_TERRAFORM-}" = 1 ]; then
with_terraform
fi

# Standalone installs by pulling pre-built releases from GitHub.
if [ "$METHOD" = standalone ]; then
if has_standalone; then
Expand All @@ -313,10 +377,6 @@ main() {
exit 1
fi
fi
if [ "$METHOD" = with_terraform ]; then
# Install terraform then continue the script
with_terraform
fi

# DISTRO can be overridden for testing but shouldn't normally be used as it
# can result in a broken coder.
Expand Down Expand Up @@ -429,7 +489,7 @@ with_terraform() {
install_macos() {
# If there is no `brew` binary available, just default to installing standalone
if command_exists brew; then
echoh "Installing v$VERSION of the coder formula from coder/coder."
echoh "Installing coder with Homebrew from the coder/coder tap."
echoh

sh_c brew install coder/coder/coder
Expand Down Expand Up @@ -505,16 +565,16 @@ install_standalone() {
"$sh_c" unzip -d "$CACHE_DIR" -o "$CACHE_DIR/coder_${VERSION}_${OS}_${ARCH}.zip"
fi

COPY_LOCATION="$STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME"
STANDALONE_BINARY_LOCATION="$STANDALONE_INSTALL_PREFIX/bin/$STANDALONE_BINARY_NAME"

# Remove the file if it already exists to
# avoid https://github.com/coder/coder/issues/2086
if [ -f "$COPY_LOCATION" ]; then
"$sh_c" rm "$COPY_LOCATION"
if [ -f "$STANDALONE_BINARY_LOCATION" ]; then
"$sh_c" rm "$STANDALONE_BINARY_LOCATION"
fi

# Copy the binary to the correct location.
"$sh_c" cp "$CACHE_DIR/coder" "$COPY_LOCATION"
"$sh_c" cp "$CACHE_DIR/coder" "$STANDALONE_BINARY_LOCATION"

echo_standalone_postinstall
}
Expand Down
38 changes: 15 additions & 23 deletions site/e2e/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,45 +263,37 @@ export const downloadCoderVersion = async (
return binaryPath;
}

// Runs our public install script using our options to
// install the binary!
// Run our official install script to install the binary
await new Promise<void>((resolve, reject) => {
const cp = spawn(
"sh",
path.join(__dirname, "../../install.sh"),
[
"-c",
[
"curl",
"-L",
"https://coder.com/install.sh",
"|",
"sh",
"-s",
"--",
"--version",
version,
"--method",
"standalone",
"--prefix",
tempDir,
"--binary-name",
binaryName,
].join(" "),
"--version",
version,
"--method",
"standalone",
"--prefix",
tempDir,
"--binary-name",
binaryName,
],
{
env: {
...process.env,
XDG_CACHE_HOME: "/tmp/coder-e2e-cache",
TRACE: "1", // tells install.sh to `set -x`, helpful if something goes wrong
},
},
);
// eslint-disable-next-line no-console -- Needed for debugging
cp.stderr.on("data", (data) => console.log(data.toString()));
cp.stderr.on("data", (data) => console.error(data.toString()));
// eslint-disable-next-line no-console -- Needed for debugging
cp.stdout.on("data", (data) => console.log(data.toString()));
cp.on("close", (code) => {
if (code === 0) {
resolve();
} else {
reject(new Error("curl failed with code " + code));
reject(new Error("install.sh failed with code " + code));
}
});
});
Expand Down