Skip to content

Commit 2562806

Browse files
committed
feat: add a generic install.sh installer
1 parent c4de048 commit 2562806

File tree

4 files changed

+203
-9
lines changed

4 files changed

+203
-9
lines changed

.github/workflows/install-sh.yml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: install pop binaries
2+
3+
on:
4+
push:
5+
branches:
6+
- "main"
7+
paths:
8+
- 'install.sh'
9+
pull_request:
10+
branches:
11+
- "main"
12+
paths:
13+
- 'install.sh'
14+
15+
defaults:
16+
run:
17+
shell: bash
18+
19+
env:
20+
RUST_BACKTRACE: 1
21+
22+
concurrency:
23+
# Cancel any in-progress jobs for the same pull request or branch
24+
group: install-sh-${{ github.head_ref || github.ref }}
25+
cancel-in-progress: true
26+
27+
jobs:
28+
arch:
29+
runs-on: ubuntu-latest
30+
container: archlinux:latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- name: Install pop-cli
34+
run: ./install.sh
35+
- name: Run pop install
36+
run: |
37+
export PATH="${HOME}/.local/bin:$PATH"
38+
pop install -y
39+
debian:
40+
runs-on: ubuntu-latest
41+
container: debian
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: Install dependencies
45+
run: apt-get update && apt-get -y install curl
46+
- name: Install pop-cli
47+
run: ./install.sh
48+
- name: Run pop install
49+
run: |
50+
export PATH="${HOME}/.local/bin:$PATH"
51+
pop install -y
52+
macos:
53+
runs-on: macos-latest
54+
steps:
55+
- uses: actions/checkout@v4
56+
- name: Install pop-cli
57+
run: ./install.sh
58+
- name: Run pop install
59+
run: |
60+
export PATH="${HOME}/.local/bin:$PATH"
61+
pop install -y
62+
redhat:
63+
runs-on: ubuntu-latest
64+
container: redhat/ubi8
65+
steps:
66+
- uses: actions/checkout@v4
67+
- name: Install pop-cli
68+
run: ./install.sh
69+
- name: Run pop install
70+
run: |
71+
export PATH="${HOME}/.local/bin:$PATH"
72+
pop install -y
73+
ubuntu:
74+
runs-on: ubuntu-latest
75+
container: ubuntu
76+
steps:
77+
- uses: actions/checkout@v4
78+
- name: Install dependencies
79+
run: apt-get update && apt-get -y install curl
80+
- name: Install pop-cli
81+
run: ./install.sh
82+
- name: Run pop install
83+
run: |
84+
export PATH="${HOME}/.local/bin:$PATH"
85+
pop install -y

.github/workflows/install.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@ name: pop install
22

33
on:
44
push:
5-
branches: ["main"]
5+
branches:
6+
- "main"
67
paths:
78
- '.github/workflows/install.yml'
8-
- 'crates/pop-cli/commands/install/**'
9+
- 'crates/pop-cli/src/commands/install/**'
910
pull_request:
10-
branches: ["main"]
11+
branches:
12+
- "main"
1113
paths:
1214
- '.github/workflows/install.yml'
13-
- 'crates/pop-cli/commands/install/**'
15+
- 'crates/pop-cli/src/commands/install/**'
1416

1517
defaults:
1618
run:

crates/pop-cli/src/commands/install/mod.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use anyhow::Context;
1212
use clap::Args;
1313
use duct::cmd;
1414
use os_info::Type;
15+
use std::{fs::Permissions, os::unix::fs::PermissionsExt};
1516
use strum_macros::Display;
1617
use tokio::fs;
1718

@@ -275,7 +276,7 @@ async fn install_rustup(cli: &mut impl cli::traits::Cli) -> anyhow::Result<()> {
275276
Err(_) => {
276277
let spinner = cliclack::spinner();
277278
spinner.start("Installing rustup ...");
278-
run_external_script("https://sh.rustup.rs").await?;
279+
run_external_script("https://sh.rustup.rs", &["-y"]).await?;
279280
cli.outro("rustup installed!")?;
280281
cmd("source", vec!["~/.cargo/env"]).run()?;
281282
},
@@ -308,13 +309,14 @@ async fn install_homebrew(cli: &mut impl cli::traits::Cli) -> anyhow::Result<()>
308309
Err(_) =>
309310
run_external_script(
310311
"https://raw.githubusercontent.com/Homebrew/install/master/install.sh",
312+
&[],
311313
)
312314
.await?,
313315
}
314316
Ok(())
315317
}
316318

317-
async fn run_external_script(script_url: &str) -> anyhow::Result<()> {
319+
async fn run_external_script(script_url: &str, args: &[&str]) -> anyhow::Result<()> {
318320
let temp = tempfile::tempdir()?;
319321
let scripts_path = temp.path().join("install.sh");
320322
let client = reqwest::Client::new();
@@ -326,10 +328,17 @@ async fn run_external_script(script_url: &str) -> anyhow::Result<()> {
326328
.error_for_status()?
327329
.text()
328330
.await?;
329-
fs::write(scripts_path.as_path(), script).await?;
330-
tokio::process::Command::new("bash").arg(scripts_path).status().await?;
331+
fs::write(&scripts_path, script).await?;
332+
fs::set_permissions(&scripts_path, Permissions::from_mode(0o755)).await?;
333+
let mut command = tokio::process::Command::new(scripts_path);
334+
command.args(args);
335+
let status = command.status().await?;
331336
temp.close()?;
332-
Ok(())
337+
if !status.success() {
338+
Err(anyhow::anyhow!("Failed to install external script: `{} {:?}`", script_url, args))
339+
} else {
340+
Ok(())
341+
}
333342
}
334343

335344
#[cfg(test)]

install.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/bin/bash
2+
# install.sh - Installer for pop-cli
3+
4+
# Users can install pop-cli with this script by running:
5+
# curl -s https://raw.githubusercontent.com/r0gue-io/pop-cli/main/install.sh | bash
6+
7+
set -e
8+
9+
# Configuration
10+
REPO="r0gue-io/pop-cli"
11+
PACKAGE_NAME="pop"
12+
INSTALL_DIR="${HOME}/.local/bin"
13+
14+
# Detect OS
15+
OS=$(uname -s)
16+
case "$OS" in
17+
Linux*) OS_TYPE="unknown-linux-gnu";;
18+
Darwin*) OS_TYPE="apple-darwin";;
19+
*)
20+
echo "❌ Unsupported operating system: $OS"
21+
exit 1
22+
;;
23+
esac
24+
25+
# Detect architecture
26+
ARCH=$(uname -m)
27+
case "$ARCH" in
28+
x86_64) ARCH_TYPE="x86_64";;
29+
aarch64|arm64) ARCH_TYPE="aarch64";;
30+
*)
31+
echo "❌ Unsupported architecture: $ARCH"
32+
exit 1
33+
;;
34+
esac
35+
36+
# Construct target triple
37+
TARGET="${ARCH_TYPE}-${OS_TYPE}"
38+
39+
echo "Detected target: $TARGET"
40+
41+
# Get latest release
42+
echo "Fetching latest release..."
43+
LATEST_RELEASE=$(curl -s "https://api.github.com/repos/${REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
44+
45+
if [ -z "$LATEST_RELEASE" ]; then
46+
echo "❌ Failed to fetch latest release"
47+
exit 1
48+
fi
49+
50+
echo "Latest version: ${LATEST_RELEASE}"
51+
52+
# Construct download URL
53+
PACKAGE="${PACKAGE_NAME}-${TARGET}.tar.gz"
54+
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${LATEST_RELEASE}/${PACKAGE}"
55+
56+
# Download and extract
57+
echo "Downloading ${PACKAGE}..."
58+
TMP_DIR=$(mktemp -d)
59+
cd "$TMP_DIR"
60+
61+
if ! curl -L -f -o "${PACKAGE}" "${DOWNLOAD_URL}"; then
62+
echo "❌ Failed to download ${PACKAGE}"
63+
echo "URL: ${DOWNLOAD_URL}"
64+
rm -rf "$TMP_DIR"
65+
exit 1
66+
fi
67+
68+
echo "Extracting binary..."
69+
tar -xzf "${PACKAGE}"
70+
71+
# Create install directory if it doesn't exist
72+
mkdir -p "${INSTALL_DIR}"
73+
74+
# Install binary
75+
echo "Installing ${PACKAGE_NAME} to ${INSTALL_DIR}..."
76+
mv pop "${INSTALL_DIR}/"
77+
chmod +x "${INSTALL_DIR}/pop"
78+
79+
# Cleanup
80+
cd - > /dev/null
81+
rm -rf "$TMP_DIR"
82+
83+
echo "${PACKAGE_NAME} ${LATEST_RELEASE} installed successfully to ${INSTALL_DIR}/pop"
84+
85+
# Check if install directory is in PATH
86+
if [[ ":$PATH:" != *":${INSTALL_DIR}:"* ]]; then
87+
echo ""
88+
echo "⚠️ ${INSTALL_DIR} is not in your PATH."
89+
echo " Add it to your PATH by running:"
90+
echo ""
91+
echo " export PATH=\"${INSTALL_DIR}:\$PATH\""
92+
echo ""
93+
echo " To make this permanent, add the above line to your shell profile:"
94+
echo " (~/.bashrc, ~/.zshrc, or ~/.profile)"
95+
else
96+
echo ""
97+
echo "Run 'pop --version' to verify the installation."
98+
fi

0 commit comments

Comments
 (0)