Skip to content

Commit

Permalink
fix: install satellite by extracting electron builds
Browse files Browse the repository at this point in the history
This will avoid some OOM errors which happen on lower memory installations #90, and make updates quicker
  • Loading branch information
Julusian committed Feb 6, 2024
1 parent c1094a0 commit ecafab9
Show file tree
Hide file tree
Showing 10 changed files with 895 additions and 18 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ No images are provided for this, but the process has been written to be a single
As root, run the following:

```
curl https://raw.githubusercontent.com/bitfocus/companion-satellite/main/pi-image/install.sh | sh
curl https://raw.githubusercontent.com/bitfocus/companion-satellite/main/pi-image/install.sh | bash
```

After this, you can use `sudo satellite-update` to change the version it has installed. Note: this is currently not fully implemented.
Expand Down
2 changes: 1 addition & 1 deletion assets/linux/README
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
If you want to run satellite on a headless machine, consider using the install script

This can be run with:
$ curl https://raw.githubusercontent.com/bitfocus/companion-satellite/main/pi-image/install.sh | sh
$ curl https://raw.githubusercontent.com/bitfocus/companion-satellite/main/pi-image/install.sh | bash

The benefit of this approach is that it will setup and manage any required dependencies, udev rules for you, and provide you with an easy script to run to perform an update.

Expand Down
3 changes: 2 additions & 1 deletion pi-image/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
output-*
output-*
*/.yarn/
34 changes: 33 additions & 1 deletion pi-image/install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
#!/usr/bin/env bash
set -e

if [ ! "$BASH_VERSION" ] ; then
echo "You must use bash to run this script. If running this script from curl, make sure the final word is 'bash'" 1>&2
exit 1
fi

CURRENT_ARCH=$(dpkg --print-architecture)
if [[ "$CURRENT_ARCH" != "x64" && "$CURRENT_ARCH" != "amd64" && "$CURRENT_ARCH" != "arm64" ]]; then
echo "$CURRENT_ARCH is not a supported cpu architecture for running Companion Satellite."
echo "If you are running on an arm device (such as a Raspberry Pi), make sure to use an arm64 image."
exit 1
fi

echo "This will attempt to install Companion Satellite as a system service on this device."
echo "It is designed to be run on headless servers, but can be used on desktop machines if you are happy to not have the tray icon."
echo "A user called 'satellite' will be created to run the service, and various scripts will be installed to manage the service"
Expand All @@ -10,6 +22,10 @@ if [ $(/usr/bin/id -u) -ne 0 ]; then
exit 1
fi

# Install a specific stable build. It is advised to not use this, as attempting to install a build that doesn't
# exist can leave your system in a broken state that needs fixing manually
SATELLITE_BUILD="${SATELLITE_BUILD:-beta}"
# Development only: Allow building using a testing branch of this updater
SATELLITE_BRANCH="${SATELLITE_BRANCH:-main}"

# add a system user
Expand All @@ -36,8 +52,17 @@ cd /usr/local/src/companion-satellite
# configure git for future updates
git config --global pull.rebase false


# run the update script
./pi-image/update.sh $SATELLITE_BRANCH
if [ "$SATELLITE_BUILD" == "beta" ] || [ "$SATELLITE_BUILD" == "experimental" ]; then
./pi-image/update.sh beta
else
./pi-image/update.sh stable "$SATELLITE_BUILD"
fi
# ./pi-image/update.sh $SATELLITE_BRANCH

# install update script dependencies, as they were ignored
yarn --cwd "/usr/local/src/companion-satellite/update-prompt" install

# enable start on boot
systemctl enable satellite
Expand All @@ -49,5 +74,12 @@ cp ./pi-image/satellite-config /boot/satellite-config
# TODO - verify permissions
echo "export PATH=/opt/fnm/aliases/default/bin:\$PATH" >> /home/satellite/.bashrc

# check that a build of satellite was installed
if [ ! -d "/opt/companion-satellite" ]
then
echo "No Companion Satellite build was installed!\nIt should be possible to recover from this with \"sudo satellite-update\""
exit 9999 # die with error code 9999
fi

echo "Companion Satellite is installed!"
echo "You should edit the configuration file at \"/boot/satellite-config\" then can start it with \"sudo systemctl start satellite\" or \"sudo satellite-update\""
6 changes: 3 additions & 3 deletions pi-image/satellite.service
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Wants=network-online.target
[Service]
Type=simple
User=satellite
WorkingDirectory=/usr/local/src/companion-satellite
ExecStartPre=+/opt/fnm/aliases/default/bin/node /usr/local/src/companion-satellite/dist/fixup-pi-config.js /home/satellite/satellite-config.json
ExecStart=/opt/fnm/aliases/default/bin/node /usr/local/src/companion-satellite/dist/main.js /home/satellite/satellite-config.json
WorkingDirectory=/opt/companion-satellite
ExecStartPre=+/opt/fnm/aliases/default/bin/node /opt/companion-satellite/dist/fixup-pi-config.js /home/satellite/satellite-config.json
ExecStart=/opt/fnm/aliases/default/bin/node /opt/companion-satellite/dist/main.js /home/satellite/satellite-config.json
Restart=on-failure
KillSignal=SIGINT
TimeoutStopSec=60
Expand Down
1 change: 1 addition & 0 deletions pi-image/update-prompt/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
176 changes: 176 additions & 0 deletions pi-image/update-prompt/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// @ts-check
import semver from 'semver'
import inquirer from 'inquirer'
import fs from 'fs'

const ALLOWED_VERSIONS = '^1.5.0'

let currentVersion
try {
currentVersion = fs.readFileSync('/opt/companion-satellite/BUILD').toString().trim()
} catch (e) {
// Assume none installed
}

async function getLatestBuildsForBranch(branch, targetCount) {
targetCount *= 10 // HACK until the api changes
// eslint-disable-next-line no-undef
const data = await fetch(
`https://api.bitfocus.io/v1/product/companion-satellite/packages?branch=${branch}&limit=${targetCount}`
)
const jsonData = await data.json()

// TODO - make sure this is durable
let target = `${process.platform}-${process.arch}-tgz`
if (target === 'linux-x64-tgz') target = 'linux-tgz'

// console.log('searching for', target, 'in', data.data.packages)

// assume the builds are sorted by date already
const result = []
for (const pkg of jsonData.packages) {
if (pkg.target === target) {
try {
if (semver.satisfies(pkg.version, ALLOWED_VERSIONS)) {
result.push({
name: pkg.version,
uri: pkg.uri,
published: new Date(pkg.published),
})
}
} catch (e) {
// Not a semver tag, so ignore
}
}
}

return result
}

async function selectBuildOfType(type, targetBuild) {
const candidates = await getLatestBuildsForBranch(type, 1)
const selectedBuild = targetBuild ? candidates.find((c) => c.name == targetBuild) : candidates[0]
if (selectedBuild) {
if (selectedBuild.name === currentVersion) {
console.log(`The latest build of ${type} (${selectedBuild.name}) is already installed`)
} else {
console.log(`Selected ${type}: ${selectedBuild.name}`)
fs.writeFileSync('/tmp/satellite-version-selection', selectedBuild.uri)
fs.writeFileSync('/tmp/satellite-version-selection-name', selectedBuild.name)
}
} else {
console.error(`No matching ${type} build was found!`)
}
}
async function chooseOfType(type) {
const candidates = await getLatestBuildsForBranch(type, 10)

if (candidates.length === 0) {
console.error(`No ${type} build was found!`)
} else {
const selectedBuild = await inquirer.prompt([
{
type: 'list',
name: 'ref',
message: 'Which version do you want? ',
choices: [...candidates.map((c) => c.name), 'cancel'],
},
])

if (selectedBuild.ref && selectedBuild.ref !== 'cancel') {
if (selectedBuild.ref === currentVersion) {
const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: `Build "${currentVersion}" is already installed. Do you wish to reinstall it?`,
},
])
if (!confirm.confirm) {
return
}
}

const build = candidates.find((c) => c.name === selectedBuild.ref)
if (build) {
console.log(`Selected ${type}: ${build.name}`)
fs.writeFileSync('/tmp/satellite-version-selection', build.uri)
fs.writeFileSync('/tmp/satellite-version-selection-name', build.name)
} else {
console.error('Invalid selection!')
}
} else {
console.error('No version was selected!')
}
}
}

async function runPrompt() {
console.log('Warning: Downgrading to an older version can cause issues with the database not being compatible')

let isOnBeta = true

console.log(`You are currently on "${currentVersion || 'Unknown'}"`)

// TODO - restore this
// if (currentBranch) {
// console.log(`You are currently on branch: ${currentBranch}`)
// } else if (currentTag) {
// console.log(`You are currently on release: ${currentTag}`)
// } else {
// console.log('Unable to determine your current version')
// }

const answer = await inquirer.prompt([
{
type: 'list',
name: 'ref',
message: 'What version do you want? ',
choices: ['latest stable', 'latest beta', 'specific stable', 'specific beta', 'custom-url', 'cancel'],
default: isOnBeta ? 'latest beta' : 'latest stable',
},
])

if (answer.ref === 'custom-url') {
console.log(
'Warning: This must be an linux build of Companion for the correct architecture, or companion will not be able to launch afterwards'
)
const answer = await inquirer.prompt([
{
type: 'input',
name: 'url',
message: 'What build url?',
},
])

const confirm = await inquirer.prompt([
{
type: 'confirm',
name: 'confirm',
message: `Are you sure you to download the build "${answer.url}"?\nMake sure you trust the source.\nIf you don't know what you are doing you could break your SatellitePi installation`,
},
])
if (!confirm.confirm) {
return runPrompt()
} else {
fs.writeFileSync('/tmp/satellite-version-selection', answer.url)
fs.writeFileSync('/tmp/satellite-version-selection-name', '')
}
} else if (!answer.ref || answer.ref === 'cancel') {
console.error('No version was selected!')
} else if (answer.ref === 'latest beta') {
selectBuildOfType('beta')
} else if (answer.ref === 'latest stable') {
selectBuildOfType('stable')
} else if (answer.ref === 'specific beta') {
chooseOfType('beta')
} else if (answer.ref === 'specific stable') {
chooseOfType('stable')
}
}

if (process.argv[2]) {
selectBuildOfType(process.argv[2], process.argv[3])
} else {
runPrompt()
}
15 changes: 15 additions & 0 deletions pi-image/update-prompt/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "update-prompt",
"version": "1.0.0",
"main": "main.js",
"type": "module",
"license": "MIT",
"dependencies": {
"inquirer": "^9.2.14",
"semver": "^7.6.0"
},
"packageManager": "[email protected]",
"engines": {
"node": ">=18.18"
}
}
Loading

0 comments on commit ecafab9

Please sign in to comment.