Skip to content

Commit

Permalink
Merge pull request #56 from maxfierke/mf-pnpm_support
Browse files Browse the repository at this point in the history
Support pnpm
  • Loading branch information
maxfierke committed Apr 28, 2024
2 parents 039483f + fd33c31 commit dda0e8d
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 89 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ jobs:
release:
needs: [build_linux_amd64, build_linux_aarch64, build_macos_amd64, build_macos_arm64]
runs-on: ubuntu-latest
if: ${{ !startsWith(github.ref, 'refs/tags/v0.0.0') && !contains(github.ref, 'dev') }}

steps:
- name: Determine version
id: version
Expand Down Expand Up @@ -209,7 +211,7 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
draft: false
prerelease: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'pre') || contains(github.ref, 'rc') }}
files: |
dist-linux-aarch64/*.zip
dist-linux-amd64/*.zip
Expand Down
10 changes: 6 additions & 4 deletions src/mstrap/bootstrappers/default_bootstrapper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ module MStrap
end

def runtime_impls(project)
if project.runtimes.empty?
config.runtimes
else
if project_runtimes = project.runtimes
# Just the ones specified in the config, including empty
config.runtimes.select do |_, runtime|
project.runtimes.includes?(runtime.language_name)
project_runtimes.includes?(runtime.language_name)
end
else
# Default to all, if unspecified
config.runtimes
end
end
end
Expand Down
85 changes: 13 additions & 72 deletions src/mstrap/dsl/system.cr
Original file line number Diff line number Diff line change
@@ -1,83 +1,24 @@
module MStrap
module DSL
module System
# Executes a given command and waits for it to complete, returning whether
# the exit status indicated success.
#
# By default the process is configured with input, output, and error of
# the `mstrap` process.
#
# * _env_: optionally specifies the environment for the command
# * _command_: specifies the command to run. Arguments are allowed here, if
# _args_ are omitted and will be evaluated by the system shell.
# * _args_: optionally specifies arguments for the command. These will not
# be processed by the shell.
# * _shell_: specifies whether to run the command through the system shell
# * _input_: specifies where to direct STDIN on the spawned process
# * _output_: specifies where to direct STDOUT on the spawned process
# * _error_: specifies where to direct STDERR on the spawned process
# * _quiet_: If passed as `true`, it does no logging. If `mstrap` is
# running in debug mode, process output is always logged.
# * _sudo_: specifies whether to run the command with superuser privileges
# See `MStrap::Platform#has_command?`
def has_command?(command_name : String, **kwargs) : Bool
MStrap::Platform.has_command?(command_name, **kwargs)
end

# See `MStrap::Platform#run_command`
def cmd(
env : Hash?,
command : String,
args : Array(String)?,
shell = true,
input = Process::Redirect::Inherit,
output = Process::Redirect::Inherit,
error = Process::Redirect::Inherit,
quiet = false,
sudo = false
**kwargs
)
if sudo
if args
args.unshift(command)
command = "sudo"
else
command = "sudo #{command}"
end
end

logd "+ #{env ? env : ""} #{command} #{args ? args.join(" ") : ""}"

named = {
shell: shell,
env: env,
input: input,
output: output,
error: error,
}

if MStrap.debug?
named = named.merge({
input: Process::Redirect::Inherit,
output: Process::Redirect::Inherit,
error: Process::Redirect::Inherit,
})
elsif quiet
named = named.merge({
input: Process::Redirect::Close,
output: Process::Redirect::Close,
error: Process::Redirect::Close,
})
end

child = Process.new(command, args, **named)

at_exit {
# Cleanup this process when we exit, if it's still running. (e.g. receiving SIGINT)
unless child.terminated?
# Reap the whole process group, otherwise nested processes may live
# to print output another day
pgid = Process.pgid(child.pid)
Process.signal(Signal::TERM, -pgid)
child.wait
end
}

status = child.wait
status.success?
MStrap::Platform.run_command(
env,
command,
args,
**kwargs
)
end

# :nodoc:
Expand Down
102 changes: 98 additions & 4 deletions src/mstrap/platform.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,108 @@ module MStrap
{{ raise "Unsupported platform" }}
{% end %}

@@found_commands = Hash(String, String).new

# Indicates whether the host platform has Git installed
def self.has_git?
ENV["MSTRAP_IGNORE_GIT"]? != "true" && (`command -v git` && $?.success?)
ENV["MSTRAP_IGNORE_GIT"]? != "true" && has_command?("git")
end

# Indicates whether the host platform has a given command available
#
# Lookups are cached by default, but cached info can be skipped by passing
# `skip_cache: true`
def self.has_command?(command_name : String, skip_cache : Bool = false) : Bool
if (cmd_path = @@found_commands[command_name]?) && !skip_cache
true
elsif cmd_path = Process.find_executable(command_name)
@@found_commands[command_name] = cmd_path
true
else
@@found_commands.delete(command_name)
false
end
end

# Indicates whether the host platform has GPG installed
def self.has_gpg?
!!(`command -v gpg` && $?.success?)
# Executes a given command and waits for it to complete, returning whether
# the exit status indicated success.
#
# By default the process is configured with input, output, and error of
# the `mstrap` process.
#
# * _env_: optionally specifies the environment for the command
# * _command_: specifies the command to run. Arguments are allowed here, if
# _args_ are omitted and will be evaluated by the system shell.
# * _args_: optionally specifies arguments for the command. These will not
# be processed by the shell.
# * _shell_: specifies whether to run the command through the system shell
# * _input_: specifies where to direct STDIN on the spawned process
# * _output_: specifies where to direct STDOUT on the spawned process
# * _error_: specifies where to direct STDERR on the spawned process
# * _quiet_: If passed as `true`, it does no logging. If `mstrap` is
# running in debug mode, process output is always logged.
# * _sudo_: specifies whether to run the command with superuser privileges
def self.run_command(
env : Hash?,
command : String,
args : Array(String)?,
shell = true,
input = Process::Redirect::Inherit,
output = Process::Redirect::Inherit,
error = Process::Redirect::Inherit,
quiet = false,
sudo = false
)
if sudo
if args
args.unshift(command)
command = "sudo"
else
command = "sudo #{command}"
end
end

Log.debug { "+ #{env ? env : ""} #{command} #{args ? args.join(" ") : ""}" }

named = {
shell: shell,
env: env,
input: input,
output: output,
error: error,
}

if MStrap.debug?
named = named.merge({
input: Process::Redirect::Inherit,
output: Process::Redirect::Inherit,
error: Process::Redirect::Inherit,
})
elsif quiet
named = named.merge({
input: Process::Redirect::Close,
output: Process::Redirect::Close,
error: Process::Redirect::Close,
})
end

child = Process.new(command, args, **named)

# TODO: Refactor this into something less hacky
# (e.g. push to a Deque used by a Process.on_terminate handler or something)
at_exit {
# Cleanup this process when we exit, if it's still running. (e.g. receiving SIGINT)
unless child.terminated?
# Reap the whole process group, otherwise nested processes may live
# to print output another day
pgid = Process.pgid(child.pid)
Process.signal(Signal::TERM, -pgid)
child.wait
end
}

status = child.wait
status.success?
end

# Installs a list of packages using the platform's package manager
Expand Down
4 changes: 2 additions & 2 deletions src/mstrap/project.cr
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module MStrap
@repo : String
@repo_upstream : String?
@run_scripts : Bool
@runtimes : Array(String)
@runtimes : Array(String)?
@upstream : String?
@websocket : Bool
@web : Bool
Expand Down Expand Up @@ -68,7 +68,7 @@ module MStrap
@repo = project_def.repo
@repo_upstream = project_def.repo_upstream
@run_scripts = project_def.run_scripts?
@runtimes = project_def.runtimes
@runtimes = project_def.runtimes_present? ? project_def.runtimes : nil
@upstream = project_def.upstream
@websocket = project_def.websocket?
@web = if project_def.web_present?
Expand Down
9 changes: 7 additions & 2 deletions src/mstrap/runtimes/node.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ module MStrap
# based on conventions.
class Node < Runtime
def bootstrap
if File.exists?("yarn.lock")
cmd "brew install yarn", quiet: true && skip_reshim { runtime_exec "yarn install" }
if File.exists?("pnpm-lock.yaml") || File.exists?("pnpm-workspace.yaml")
cmd("brew install pnpm", quiet: true) unless has_command?("pnpm")
skip_reshim { runtime_exec "pnpm install" }
elsif File.exists?("yarn.lock")
cmd("brew install yarn", quiet: true) unless has_command?("yarn")
skip_reshim { runtime_exec "yarn install" }
elsif File.exists?("package.json")
skip_reshim { runtime_exec "npm install" }
end
Expand All @@ -29,6 +33,7 @@ module MStrap
def matches? : Bool
[
"yarn.lock",
"pnpm-lock.yaml",
"package.json",
".node-version",
].any? do |file|
Expand Down
4 changes: 2 additions & 2 deletions src/mstrap/supports/mise_installer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module MStrap
end

def installed?
File.exists?(MISE_INSTALL_PATH) && (`command -v mise` && $?.success?)
File.exists?(MISE_INSTALL_PATH) && has_command?("mise")
end

private def fetch_installer!
Expand Down Expand Up @@ -82,7 +82,7 @@ module MStrap
end

private def verify_installer?
@verify_installer ||= MStrap::Platform.has_gpg?
has_command?("gpg")
end
end
end
2 changes: 1 addition & 1 deletion src/mstrap/supports/mkcert.cr
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module MStrap

# Returns whether mkcert is installed
def installed?
cmd("command -v mkcert", quiet: true)
has_command?("mkcert")
end

# Runs mkcert install process to add CARoot, etc.
Expand Down
2 changes: 1 addition & 1 deletion src/mstrap/supports/rustup_installer.cr
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ module MStrap
end

def installed?
`command -v rustup` && $?.success?
has_command?("rustup")
end

private def fetch_installer!
Expand Down

0 comments on commit dda0e8d

Please sign in to comment.