Update .local/share/chezmoi/home/dot_local/bin/executable_install-program

This commit is contained in:
Brian Zalewski 2022-12-02 23:07:52 +00:00
parent 41eb0d434d
commit c9362d6b60

View file

@ -2,6 +2,78 @@
const execSync = require('child_process').execSync const execSync = require('child_process').execSync
// Log symbols
const figuresDefault = {
bullet: '●',
circle: '◯',
cross: '✖',
lozenge: '◆',
play: '▶',
pointer: '',
square: '◼',
star: '★',
tick: '✔'
}
const figuresFallback = {
bullet: '■',
circle: '□',
cross: '×',
lozenge: '♦',
play: '►',
pointer: '>',
square: '■',
star: '✶',
tick: '√'
}
function isUnicodeSupported() {
if (process.platform !== 'win32') {
// Linux console (kernel)
return process.env.TERM !== 'linux'
}
return (
Boolean(process.env.CI) ||
// Windows Terminal
Boolean(process.env.WT_SESSION) ||
// ConEmu and cmder
process.env.ConEmuTask === '{cmd::Cmder}' ||
process.env.TERM_PROGRAM === 'vscode' ||
process.env.TERM === 'xterm-256color' ||
process.env.TERM === 'alacritty'
)
}
const figures = isUnicodeSupported() ? figuresDefault : figuresFallback
function log(type, label, msg) {
let icon, labelStyle, message
if (type === 'info') {
icon = chalk.cyanBright(this.figures.pointer)
labelStyle = chalk.bold.underline
message = chalk.bold(msg)
} else if (type === 'star') {
icon = chalk.yellowBright(this.figures.star)
labelStyle = chalk.bold.underline
message = chalk.bold(msg)
} else if (type === 'success') {
icon = chalk.greenBright(this.figures.play)
labelStyle = chalk.bold.underline
chalk.bold(msg)
} else if (type === 'warn') {
icon = `${chalk.yellowBright(this.figures.lozenge)} ${chalk.bold.black.bgYellowBright(' WARNING ')}`
labelStyle = chalk.bold.underline
chalk.yellowBright(msg)
} else if (type === 'error') {
icon = `${chalk.redBright(this.figures.cross)} ${chalk.black.bold.bgRedBright(' ERROR ')} + ' '}`
labelStyle = chalk.bold.underline
message = chalk.redBright(msg)
}
const outputMessage = `${icon} ${labelStyle(label)} ${message}`
console.log(outputMessage)
}
$.log = (entry) => { $.log = (entry) => {
if (entry.kind === 'cmd' && entry.cmd.substring(0, 4) === 'logg') { if (entry.kind === 'cmd' && entry.cmd.substring(0, 4) === 'logg') {
//execSync(entry.cmd, {stdio: 'inherit', shell: true}) //execSync(entry.cmd, {stdio: 'inherit', shell: true})
@ -29,7 +101,7 @@ async function downloadInstallData() {
const text = await response.text() const text = await response.text()
return YAML.parse(text) return YAML.parse(text)
} else { } else {
await $`logg error 'Failed to download the installation map'` log('error', 'Install Data', `Failed to download the installation map`)
} }
} }
@ -37,9 +109,9 @@ async function downloadInstallData() {
async function generateInstallOrders() { async function generateInstallOrders() {
const packagesToInstall = process.argv.slice(3); const packagesToInstall = process.argv.slice(3);
const installerPreference = await OSTypeInstallerKey() const installerPreference = await OSTypeInstallerKey()
await $`logg info 'Installer preference category detected as ${installerPreference}'` log('info', 'Install Orders', `Installer preference category detected as ${installerPreference}`)
const preferenceOrder = installData.installerPreference[installerPreference]; const preferenceOrder = installData.installerPreference[installerPreference];
await $`logg info 'Preference order acquired:'` log('info', 'Install Orders', `Preference order acquired:`)
console.log(preferenceOrder) console.log(preferenceOrder)
const softwarePackages = installData.softwarePackages; const softwarePackages = installData.softwarePackages;
for (let pkg of packagesToInstall) { for (let pkg of packagesToInstall) {
@ -51,7 +123,7 @@ async function generateInstallOrders() {
} else if (softwarePackages[pkg]) { } else if (softwarePackages[pkg]) {
packageKey = pkg packageKey = pkg
} else { } else {
await $`logg warn 'The package \`${pkg}\` was not found in the installation map'` log('warn', 'Install Orders', `The package \`${pkg}\` was not found in the installation map`)
continue; continue;
} }
for (let preference of preferenceOrder) { for (let preference of preferenceOrder) {
@ -97,7 +169,7 @@ async function updateInstallMaps(preference, packages, scopedPreference, pkg, pa
if (!installOrders[preference]) { if (!installOrders[preference]) {
installOrders[preference] = []; installOrders[preference] = [];
} }
await $`logg info 'Found a match for the package \`${pkg}\` (${packageKey} via ${scopedPreference})'` log('info', 'Install Orders', `Found a match for the package \`${pkg}\` (${packageKey} via ${scopedPreference})`)
const newPackages = packages[scopedPreference]; const newPackages = packages[scopedPreference];
installOrders[preference] = installOrders[preference].concat( installOrders[preference] = installOrders[preference].concat(
typeof newPackages === "string" ? [newPackages] : newPackages typeof newPackages === "string" ? [newPackages] : newPackages
@ -178,8 +250,8 @@ async function releaseID() {
async function afterInstall(packageManager) { async function afterInstall(packageManager) {
if (packageManager === 'appimage') { if (packageManager === 'appimage') {
} else if (packageManager === 'ansible') { } else if (packageManager === 'ansible') {
await $`logg info 'Ensuring temporary passwordless sudo privileges used by Ansible are removed'` log('info', 'Post-Install', `Ensuring temporary passwordless sudo privileges used by Ansible are removed`)
await $`echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR ANSIBLE INSTALL" | sudo tee -a /etc/sudoers` await $`sudo sed -i '/# TEMPORARY FOR ANSIBLE INSTALL/d' /etc/sudoers`
} else if (packageManager === 'apk') { } else if (packageManager === 'apk') {
} else if (packageManager === 'apt') { } else if (packageManager === 'apt') {
} else if (packageManager === 'basher') { } else if (packageManager === 'basher') {
@ -214,7 +286,7 @@ async function afterInstall(packageManager) {
async function beforeInstall(packageManager) { async function beforeInstall(packageManager) {
if (packageManager === 'appimage') { if (packageManager === 'appimage') {
} else if (packageManager === 'ansible') { } else if (packageManager === 'ansible') {
await $`logg info 'Temporarily enabling passwordless sudo for Ansible role installations'` log('info', 'Pre-Install', `Temporarily enabling passwordless sudo for Ansible role installations`)
await $`sudo echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR ANSIBLE INSTALL" > /etc/sudoers` await $`sudo echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR ANSIBLE INSTALL" > /etc/sudoers`
} else if (packageManager === 'apk') { } else if (packageManager === 'apk') {
} else if (packageManager === 'apt') { } else if (packageManager === 'apt') {
@ -250,9 +322,10 @@ async function beforeInstall(packageManager) {
try { try {
await $`docker run --rm hello-world` await $`docker run --rm hello-world`
} catch (e) { } catch (e) {
await $`logg warn 'The command \`docker run --rm hello-world\` failed'` log('warn', `The command \`docker run --rm hello-world\` failed`)
try { try {
const promises = [$`test -d /Applications/Docker.app`, $`logg info 'Attempting to open \`/Applications/Docker.app\` (Docker Desktop for macOS). This should take about 30 seconds.'`, $`open /Applications/Docker.app`] log('info', 'Package Manager', 'Attempting to open \`/Applications/Docker.app\` (Docker Desktop for macOS). This should take about 30 seconds.')
const promises = [$`test -d /Applications/Docker.app`, $`open /Applications/Docker.app`]
await Promise.all(promises) await Promise.all(promises)
const gum = which.sync('gum', { nothrow: true }) const gum = which.sync('gum', { nothrow: true })
if (gum) { if (gum) {
@ -261,7 +334,7 @@ async function beforeInstall(packageManager) {
await $`sleep 30` await $`sleep 30`
} }
} catch (e) { } catch (e) {
await $`logg warn 'Docker Desktop appears to not be installed!'` log('warn', 'Package Manager', `Docker Desktop appears to not be installed!`)
} }
} }
} }
@ -274,13 +347,13 @@ async function beforeInstall(packageManager) {
async function ensureInstalled(bin, callback) { async function ensureInstalled(bin, callback) {
const installed = which.sync(bin, { nothrow: true }) const installed = which.sync(bin, { nothrow: true })
if (installed) { if (installed) {
await $`logg info '\`${bin}\` is available'` log('info', `\`${bin}\` is available`)
} else { } else {
await $`logg warn '\`${bin}\` is not installed!'` log('warn', `\`${bin}\` is not installed!`)
if (callback) { if (callback) {
await callback await callback
} else { } else {
await $`logg error 'There does not appear to be an installation method available for \`${bin}\`'` log('error', `There does not appear to be an installation method available for \`${bin}\``)
} }
} }
} }
@ -290,13 +363,13 @@ async function ensurePackageManagerAnsible() {
await $`pipx inject ansible PyObjC PyObjC-core docker lxml netaddr pexpect python-vagrant pywinrm requests-credssp watchdog` await $`pipx inject ansible PyObjC PyObjC-core docker lxml netaddr pexpect python-vagrant pywinrm requests-credssp watchdog`
await $`mkdir -p "$HOME/.cache/megabyte-labs"` await $`mkdir -p "$HOME/.cache/megabyte-labs"`
await $`touch "$HOME/.cache/megabyte-labs/ansible-installed"` await $`touch "$HOME/.cache/megabyte-labs/ansible-installed"`
await $`logg info 'Ansible and its supporting packages are now installed via pipx'` log('info', `Ansible and its supporting packages are now installed via pipx`)
} }
// Ensure the package manager is available // Ensure the package manager is available
let packageManagerInstalled = {}; let packageManagerInstalled = {};
async function ensurePackageManager(packageManager) { async function ensurePackageManager(packageManager) {
await $`logg info 'Ensuring \`${packageManager}\` is set up'` log('info', `Ensuring \`${packageManager}\` is set up`)
if (packageManagerInstalled[packageManager]) { if (packageManagerInstalled[packageManager]) {
return; return;
} else { } else {
@ -320,7 +393,7 @@ async function ensurePackageManager(packageManager) {
await $`test -f "$HOME/.cache/megabyte-labs/ansible-installed"` await $`test -f "$HOME/.cache/megabyte-labs/ansible-installed"`
const ansible = which.sync('ansible', { nothrow: true }) const ansible = which.sync('ansible', { nothrow: true })
if (ansible) { if (ansible) {
await $`logg info '\`ansible\` and its supporting packages appear to be installed'` log('info', `\`ansible\` and its supporting packages appear to be installed`)
} else { } else {
await ensurePackageManagerAnsible() await ensurePackageManagerAnsible()
} }
@ -349,11 +422,11 @@ async function ensurePackageManager(packageManager) {
if command -v sudo > /dev/null && sudo -n true; then if command -v sudo > /dev/null && sudo -n true; then
echo | bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo | bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
else else
logg info 'Homebrew is not installed. Password may be required.' log('info', 'Package Manager', 'Homebrew is not installed. Password may be required.')
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?" bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
if [ -n "$BREW_EXIT_CODE" ]; then if [ -n "$BREW_EXIT_CODE" ]; then
if command -v brew > /dev/null; then if command -v brew > /dev/null; then
logg warn 'Homebrew was installed but part of the installation failed. Attempting to fix..' log('warn', 'Package Manager', 'Homebrew was installed but part of the installation failed. Attempting to fix..')
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d" BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
for BREW_DIR in $BREW_DIRS; do for BREW_DIR in $BREW_DIRS; do
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
@ -384,16 +457,16 @@ async function ensurePackageManager(packageManager) {
const dnf = which.sync('dnf', { nothrow: true }) const dnf = which.sync('dnf', { nothrow: true })
const yum = which.sync('yum', { nothrow: true }) const yum = which.sync('yum', { nothrow: true })
if (dnf) { if (dnf) {
await $`logg info '\`dnf\` is available'` log('info', 'Package Manager', `\`dnf\` is available`)
} else if (yum) { } else if (yum) {
await $`logg info '\`yum\` is available'` log('info', 'Package Manager', `\`yum\` is available`)
} else { } else {
await $`logg error 'Both \`dnf\` and \`yum\` are not available'` log('error', 'Package Manager', `Both \`dnf\` and \`yum\` are not available`)
} }
} else if (packageManager === 'flatpak') { } else if (packageManager === 'flatpak') {
const flatpak = which.sync('flatpak', { nothrow: true }) const flatpak = which.sync('flatpak', { nothrow: true })
if (flatpak) { if (flatpak) {
await $`logg info '\`flatpak\` is available'` log('info', 'Package Manager', `\`flatpak\` is available`)
} else { } else {
const apk = which.sync('apk', { nothrow: true }) const apk = which.sync('apk', { nothrow: true })
const apt = which.sync('apt', { nothrow: true }) const apt = which.sync('apt', { nothrow: true })
@ -426,9 +499,9 @@ async function ensurePackageManager(packageManager) {
if (flatpakPost) { if (flatpakPost) {
await $`flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo` await $`flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`
} else { } else {
await $`logg error '\`flatpak\` failed to install!'` log('error', 'Package Manager', `\`flatpak\` failed to install!`)
} }
await $`logg info '\`flatpak\` was installed. It may require a reboot to function correctly.'` log('info', 'Package Manager', `\`flatpak\` was installed. It may require a reboot to function correctly.`)
} }
} else if (packageManager === 'gem') { } else if (packageManager === 'gem') {
await ensureInstalled('gem', $`brew install ruby`) await ensureInstalled('gem', $`brew install ruby`)
@ -447,7 +520,7 @@ async function ensurePackageManager(packageManager) {
const node = which('node', { nothrow: true }) const node = which('node', { nothrow: true })
const volta = which('volta', { nothrow: true }) const volta = which('volta', { nothrow: true })
if (npm && node && volta) { if (npm && node && volta) {
await $`logg info '\`npm\`, \`node\`, and \`volta\` are available'` log('info', 'Package Manager', `\`npm\`, \`node\`, and \`volta\` are available`)
} else { } else {
if (!volta) { if (!volta) {
await $`brew install volta` await $`brew install volta`
@ -558,7 +631,7 @@ async function installPackageList(packageManager, packages) {
if (packageManager === 'appimage') { if (packageManager === 'appimage') {
} else if (packageManager === 'ansible') { } else if (packageManager === 'ansible') {
for (const role of packages) { for (const role of packages) {
execSync('gum spin --spinner dot --title "Installing ' + role + ' via Ansible" -- ansible localhost -m setup -m include_role -a name=' + role + ' -e ansible_user="$USER"', , {stdio: 'inherit', shell: true}) execSync('gum spin --spinner dot --title "Installing ' + role + ' via Ansible" -- ansible localhost --skip-tags brew -m setup -m include_role -a name=' + role + ' -e ansible_user="$USER"', {stdio: 'inherit', shell: true})
} }
} else if (packageManager === 'apk') { } else if (packageManager === 'apk') {
await $`sudo apk add ${packages}` await $`sudo apk add ${packages}`
@ -634,34 +707,34 @@ async function installPackageList(packageManager, packages) {
await $`sudo zypper install -y ${packages}` await $`sudo zypper install -y ${packages}`
} }
} catch (e) { } catch (e) {
await $`logg error 'Possibly encountered an error while installing via \`${packageManager}\`'` log('error', 'Package Install', `Possibly encountered an error while installing via \`${packageManager}\``)
await $`logg info 'Error was encountered while installing: ${pkg}'` log('info', 'Package Install', `Error was encountered while installing: ${pkg}`)
await $`logg info 'Proceeding with the installation..'` log('info', 'Package Install', `Proceeding with the installation..`)
} }
} }
// main process // main process
async function main() { async function main() {
await $`logg info 'Fetching the latest version of the installation map'` log('info', `Fetching the latest version of the installation map`)
installData = await downloadInstallData(); installData = await downloadInstallData();
await $`logg info 'Calculating the install orders'` log('info', 'Install Orders', `Calculating the install orders`)
await generateInstallOrders(); await generateInstallOrders();
await $`logg info 'Ensuring any package managers that will be used are installed / configured'` log('info', `Ensuring any package managers that will be used are installed / configured`)
const packageManagers = Object.keys(installOrders); const packageManagers = Object.keys(installOrders);
for (const packageManager of packageManagers) { for (const packageManager of packageManagers) {
await ensurePackageManager(packageManager); await ensurePackageManager(packageManager);
} }
await $`logg info 'The install orders were generated:'` log('info', 'Install Orders', `The install orders were generated:`)
console.log(installOrders) console.log(installOrders)
await $`logg info 'Running package manager pre-installation steps'` log('info', 'Package Manager', `Running package manager pre-installation steps`)
for (const packageManager of packageManagers) { for (const packageManager of packageManagers) {
await beforeInstall(packageManager); await beforeInstall(packageManager);
} }
await $`logg info 'Running package-specific pre-installation steps'` log('info', 'Package Pre-Install', `Running package-specific pre-installation steps`)
for (const script of installOrdersPre) { for (const script of installOrdersPre) {
await $`${script}`; await $`${script}`;
} }
await $`logg info 'Installing the packages'` log('info', 'Package Install', `Installing the packages`)
for (const packageManager of packageManagers) { for (const packageManager of packageManagers) {
const asyncOrders = []; const asyncOrders = [];
asyncOrders.push( asyncOrders.push(
@ -671,15 +744,15 @@ async function main() {
); );
await Promise.all(asyncOrders); await Promise.all(asyncOrders);
} }
await $`logg info 'Running package-specific post-installation steps'` log('info', 'Package Post-Install', `Running package-specific post-installation steps`)
for (const script of installOrdersPost) { for (const script of installOrdersPost) {
await $`${script}`; await $`${script}`;
} }
await $`logg info 'Running package manager post-installation steps'` log('info', 'Post-Install Package Manager', `Running package manager post-installation steps`)
for (const packageManager of packageManagers) { for (const packageManager of packageManagers) {
await afterInstall(packageManager); await afterInstall(packageManager);
} }
await $`logg success 'Done!'` log('success', 'Installation Complete', `Done!`)
} }
// Start the main process // Start the main process