From a0d899aa2aeddd6f9d6cda09fb99775aa8082da0 Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Mon, 15 Jul 2024 09:59:36 -0400 Subject: [PATCH 1/9] docker-based dev environment --- .gitignore | 1 + Dockerfile.dx | 27 +++++ docker-compose.dx.yml | 17 +++ dx/build | 29 +++++ dx/docker-compose.base.env | 18 ++++ dx/docker-compose.env | 27 +++++ dx/dx.sh.lib | 39 +++++++ dx/exec | 26 +++++ dx/prune | 19 ++++ dx/setup | 57 ++++++++++ dx/setupkit.sh.lib | 117 +++++++++++++++++++++ dx/show-help-in-app-container-then-wait.sh | 38 +++++++ dx/start | 22 ++++ dx/stop | 19 ++++ 14 files changed, 456 insertions(+) create mode 100644 Dockerfile.dx create mode 100644 docker-compose.dx.yml create mode 100755 dx/build create mode 100644 dx/docker-compose.base.env create mode 100644 dx/docker-compose.env create mode 100644 dx/dx.sh.lib create mode 100755 dx/exec create mode 100755 dx/prune create mode 100755 dx/setup create mode 100644 dx/setupkit.sh.lib create mode 100755 dx/show-help-in-app-container-then-wait.sh create mode 100755 dx/start create mode 100755 dx/stop diff --git a/.gitignore b/.gitignore index 1bc4f0e..ba09434 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ results.html .DS_Store Session.vim scaffold_test +dx/docker-compose.local.env diff --git a/Dockerfile.dx b/Dockerfile.dx new file mode 100644 index 0000000..bfa4374 --- /dev/null +++ b/Dockerfile.dx @@ -0,0 +1,27 @@ +FROM ruby:3.1 + +ENV DEBIAN_FRONTEND noninteractive +RUN apt-get -y update + + +# dx.snippet.start=templates/snippets/bundler/latest__bundler.dockerfile-snippet +# Based on documentation at https://guides.rubygems.org/command-reference/#gem-update +# based on the vendor's documentation +RUN echo "gem: --no-document" >> ~/.gemrc && \ + gem update --system && \ + gem install bundler + +# dx.snippet.end=templates/snippets/bundler/latest__bundler.dockerfile-snippet + + +# dx.snippet.start=templates/snippets/vim/bullseye_vim.dockerfile-snippet +# Based on documentation at https://packages.debian.org/search?keywords=vim +# based on the vendor's documentation +ENV EDITOR=vim +RUN apt-get install -y vim && \ + echo "set -o vi" >> /root/.bashrc +# dx.snippet.end=templates/snippets/vim/bullseye_vim.dockerfile-snippet + +# This entrypoint produces a nice help message and waits around for you to do +# something with the container. +COPY dx/show-help-in-app-container-then-wait.sh /root diff --git a/docker-compose.dx.yml b/docker-compose.dx.yml new file mode 100644 index 0000000..ac06d71 --- /dev/null +++ b/docker-compose.dx.yml @@ -0,0 +1,17 @@ +services: + app: + image: ${IMAGE} + build: + context: "./" + dockerfile: "Dockerfile.dx" + platform: ${DOCKER_DEFAULT_PLATFORM} + pull_policy: "missing" + init: true + volumes: + - type: bind + source: "./" + target: "/root/work" + consistency: "consistent" + entrypoint: /root/show-help-in-app-container-then-wait.sh + working_dir: /root/work + diff --git a/dx/build b/dx/build new file mode 100755 index 0000000..20bd6a6 --- /dev/null +++ b/dx/build @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" + +require_command "docker" + +usage_on_help "Builds the Docker image based on the Dockerfile" "" "${@}" +ensure_docker_compose_env + +if [[ -f "${SCRIPT_DIR}/build.pre" && -x "${SCRIPT_DIR/build.pre}" ]]; then + log "🎬" "${SCRIPT_DIR}/build.pre exists - executing" + "${SCRIPT_DIR}/build.pre" Dockerfile.dx "${IMAGE}" +fi +docker build -f Dockerfile.dx -t "${IMAGE}" ./ + +log "🌈" "Your Docker image has been built tagged '${IMAGE}'" +log "πŸ”„" "You can now run dx/start to start it up, though you may need to stop it first with Ctrl-C" + +if [[ -f "${SCRIPT_DIR}/build.post" && -x "${SCRIPT_DIR/build.post}" ]]; then + log "🎬" "build.post exists - executing" + "${SCRIPT_DIR}/build.post" Dockerfile.dx "${IMAGE}" +fi +log "βœ…" "Done" + +# vim: ft=bash diff --git a/dx/docker-compose.base.env b/dx/docker-compose.base.env new file mode 100644 index 0000000..0039396 --- /dev/null +++ b/dx/docker-compose.base.env @@ -0,0 +1,18 @@ +# IMAGE is the name of the image to be built for running +# your app. The recommended format is ORG/REPO:TAG +# +# ORG - your org on GitHub or DockerHub +# REPO - the name of the repo on GitHub or the app name +# TAG - a version identifier. Recommend you avoid latest as this is confusing +IMAGE=davetron5000/gli:ruby-3.2 + +# This is used to tell docker compose what the name +# of your project is for the purpose of naming +# containers. It can be anything and is mostly +# used for pruning containers via bin/prune +PROJECT_NAME=gli + +# Use this to override the service name for your +# app in docker-compose.dx.yml +DEFAULT_SERVICE=app +# vim: ft=bash diff --git a/dx/docker-compose.env b/dx/docker-compose.env new file mode 100644 index 0000000..887160c --- /dev/null +++ b/dx/docker-compose.env @@ -0,0 +1,27 @@ +# This is generated - do not edit +# +# To make changes for the project, edit dx/docker-compose.base.env +# To make changes for your computer, edit dx/docker-compose.local.env +# Delete this file after changing either of those +# + +# IMAGE is the name of the image to be built for running +# your app. The recommended format is ORG/REPO:TAG +# +# ORG - your org on GitHub or DockerHub +# REPO - the name of the repo on GitHub or the app name +# TAG - a version identifier. Recommend you avoid latest as this is confusing +IMAGE=davetron5000/gli:ruby-3.2 + +# This is used to tell docker compose what the name +# of your project is for the purpose of naming +# containers. It can be anything and is mostly +# used for pruning containers via bin/prune +PROJECT_NAME=gli + +# Use this to override the service name for your +# app in docker-compose.dx.yml +DEFAULT_SERVICE=app +# vim: ft=bash +DOCKER_DEFAULT_PLATFORM=linux/arm64 + diff --git a/dx/dx.sh.lib b/dx/dx.sh.lib new file mode 100644 index 0000000..1a46ea0 --- /dev/null +++ b/dx/dx.sh.lib @@ -0,0 +1,39 @@ +# shellcheck shell=bash + +. "${SCRIPT_DIR}/setupkit.sh.lib" + +require_command "realpath" +require_command "cat" + +ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.env +BASE_ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.base.env +LOCAL_ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.local.env + +DOT_DOT=$(realpath "${SCRIPT_DIR}/..")/ +ENV_FILE_RELATIVE=${ENV_FILE//"${DOT_DOT}"/} +BASE_ENV_FILE_RELATIVE=${BASE_ENV_FILE//"${DOT_DOT}"/} +LOCAL_ENV_FILE_RELATIVE=${LOCAL_ENV_FILE//"${DOT_DOT}"/} + +ensure_docker_compose_env() { + if [ ! -e "${ENV_FILE}" ]; then + if [ ! -e "${LOCAL_ENV_FILE}" ]; then + fatal "Looks like you have not set up yet. Please run dx/setup" + else + log "πŸ—„" "Creating ${ENV_FILE_RELATIVE} from ${LOCAL_ENV_FILE_RELATIVE} and ${BASE_ENV_FILE_RELATIVE}" + echo "# This is generated - do not edit" > "${ENV_FILE}" + { + echo "#" + echo "# To make changes for the project, edit ${BASE_ENV_FILE_RELATIVE}" + echo "# To make changes for your computer, edit ${LOCAL_ENV_FILE_RELATIVE}" + echo "# Delete this file after changing either of those" + echo "#" + echo "" + cat "${BASE_ENV_FILE}" + grep -v ^# "${LOCAL_ENV_FILE}" + } >> "${ENV_FILE}" + fi + fi + # shellcheck disable=SC1090 + . "${ENV_FILE}" +} +# vim: ft=bash diff --git a/dx/exec b/dx/exec new file mode 100755 index 0000000..5cff700 --- /dev/null +++ b/dx/exec @@ -0,0 +1,26 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" + +require_command "docker" + +usage_on_help "Execute a command inside the app's container. Use enviornment variable SERVICE_NAME to execute inside another service" "command" "${@}" +ensure_docker_compose_env + +CMD=$* + +if [ -z "$CMD" ]; then + log "😐" "You should specify a command to run e.g. $0 ls -l" + echo + usage +fi + +SERVICE="${SERVICE_NAME:-${DEFAULT_SERVICE}}" +log "πŸš‚" "Running '$CMD' inside container with service name '${SERVICE}'" +docker compose -f docker-compose.dx.yaml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" exec "${SERVICE}" "${@}" + +# vim: ft=bash diff --git a/dx/prune b/dx/prune new file mode 100755 index 0000000..001ff1e --- /dev/null +++ b/dx/prune @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" +require_command "docker" + +usage_on_help "Prune containers for this repo" "command" "${@}" +ensure_docker_compose_env + +for container_id in $(docker container ls -a -f "name=^${PROJECT_NAME}-.*-1$" --format="{{.ID}}"); do + log "πŸ—‘" "Removing container with id '${container_id}'" + docker container rm "${container_id}" +done +echo "🧼" "Containers removed" + +# vim: ft=bash diff --git a/dx/setup b/dx/setup new file mode 100755 index 0000000..738d3eb --- /dev/null +++ b/dx/setup @@ -0,0 +1,57 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" +require_command "docker" +require_command "ruby" + +usage_on_help "Initialize your development environment" "command" "${@}" + +if [ -e "${LOCAL_ENV_FILE}" ]; then + fatal "You're already set up. Delete ${LOCAL_ENV_FILE_RELATIVE} and start over if you want to reset" +fi + +while [ -z "${DOCKER_DEFAULT_PLATFORM}" ]; do + if ! command -v ruby > /dev/null 2>&1 ; then + PLATFORM_GUESS="" + else + PLATFORM_GUESS=$(docker version -f json | ruby -rjson -e "x = JSON.parse(STDIN.read)['Server']; puts x['Os'] + '/' + x['Arch']") + fi + + + user_input "πŸ’Ύ" "Enter your 'Docker Platform' or type 'help' to get help on choosing" "${PLATFORM_GUESS}" + DOCKER_DEFAULT_PLATFORM="${INPUT}" + if [ "${DOCKER_DEFAULT_PLATFORM}" = "help" ]; then + log + log "ℹ️ " "Should be in format Β«osΒ»/Β«archΒ» or Β«osΒ»/Β«archΒ»/Β«variantΒ»" + log + log "πŸͺŸ" "If you are on an Intel or AMD chip, you most likely want linux/amd64" + log "🍎" "If you are on Apple Silicon, you most likely want linux/arm64/v8" + log "🀷" "Otherwise, prepare yourself:" + log + log "πŸ•΅οΈ" "To figure this out you need to choose an os and an arch that match the list here:" + log "🌎" "https://go.dev/doc/install/source#environment" + log "πŸ”Ž" "(search for GOOS on that page)" + log + log "😒" "For the variant, you are pretty much on your own, sorry" + log + DOCKER_DEFAULT_PLATFORM="" + fi +done + +log "😷" "Creating ${LOCAL_ENV_FILE_RELATIVE}" +echo "# This is specific to your computer and should not be checked in" > "${LOCAL_ENV_FILE}" +{ + echo "# If you have copied these from another computer, you may want" + echo "# to delete this file and re-run bin/set" + echo "DOCKER_DEFAULT_PLATFORM=${DOCKER_DEFAULT_PLATFORM}" + echo +} >> "${LOCAL_ENV_FILE}" + +ensure_docker_compose_env + +log "πŸŽ‰" "You are all set up. Try dx/build or dx/start" +# vim: ft=bash diff --git a/dx/setupkit.sh.lib b/dx/setupkit.sh.lib new file mode 100644 index 0000000..dd19278 --- /dev/null +++ b/dx/setupkit.sh.lib @@ -0,0 +1,117 @@ +# shellcheck shell=bash + +fatal() { + remainder=${*:2} + if [ -z "$remainder" ]; then + log "πŸ›‘" "${@}" + else + log "${@}" + fi + exit 1 +} + +log() { + emoji=$1 + remainder=${*:2} + if [ -z "${NO_EMOJI}" ]; then + echo "[ ${0} ] ${*}" + else + if [ -z "$remainder" ]; then + echo "[ ${0} ] ${*}" + else + echo "[ ${0} ] ${remainder}" + fi + fi +} + +usage() { + echo "usage: ${0} [-h] ${extra_usage}" + if [ -n "$1" ]; then + echo + echo "DESCRIPTION" + echo " ${description}" + fi + exit 0 +} + +usage_on_help() { + description=$1 + extra_usage=$2 + cli_args=( "${@:3}" ) + + for arg in "${cli_args[@]}"; do + if [ "${arg}" = "-h" ] || [ "${arg}" = "--help" ]; then + usage "${description}" + fi + done +} + +# Read user input into the variable 'INPUT' +# +# Args: +# +# [1] - an emoji to use for messages +# [2] - the message explaining what input is being requested +# [3] - a default value to use if no value is provided +# +# Respects NO_EMOJI when outputing messages to the user +user_input() { + emoji=$1 + message=$2 + default=$3 + prompt=$4 + + if [ -z "$message" ]; then + echo "user_input requires a message" + exit 1 + fi + + INPUT= + + if [ -z "${prompt}" ]; then + prompt=$(log "${emoji}" "Value: ") + if [ -n "${default}" ]; then + prompt=$(log "${emoji}" "Value (or hit return to use '${default}): ") + fi + fi + + while [ -z "${INPUT}" ]; do + + log "$emoji" "$message" + read -r -p "${prompt}" INPUT + if [ -z "$INPUT" ]; then + INPUT=$default + fi + if [ -z "$INPUT" ]; then + log "😢", "You must provide a value" + fi + done +} + +user_confirm() { + user_input "$1" "$2" "$3" "y/n> " +} + +require_not_exist() { + file=$1 + message=$2 + if [ -e "${file}" ]; then + fatal "$message" + fi +} +require_exist() { + file=$1 + message=$2 + if [ ! -e "${file}" ]; then + fatal "$message" + fi +} + +require_command() { + command_name=$1 + if ! command -v "${command_name}" >/dev/null 2>&1; then + fatal "Command '${command_name}' not found - it is required for this script to run" + fi +} + +# vim: ft=bash diff --git a/dx/show-help-in-app-container-then-wait.sh b/dx/show-help-in-app-container-then-wait.sh new file mode 100755 index 0000000..f391610 --- /dev/null +++ b/dx/show-help-in-app-container-then-wait.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -e + +# Ideally, the message below is shown after everything starts up. We can't +# achieve this using healtchecks because the interval for a healtcheck is +# also an initial delay, and we don't really want to do healthchecks on +# our DB or Redis every 2 seconds. So, we sleep just a bit to let +# the other containers start up and vomit out their output first. +sleep 2 +# Output some helpful messaging when invoking `dx/start` (which itself is +# a convenience script for `docker compose up`. +# +# Adding this to work around the mild inconvenience of the `app` container's +# entrypoint generating no output. +# +cat <<-'PROMPT' + + + + πŸŽ‰ Dev Environment Initialized! πŸŽ‰ + + ℹ️ To use this environment, open a new terminal and run + + dx/exec bash + + πŸ•Ή Use `ctrl-c` to exit. + + + +PROMPT + +# Using `sleep infinity` instead of `tail -f /dev/null`. This may be a +# performance improvement based on the conversation on a semi-related +# StackOverflow page. +# +# @see https://stackoverflow.com/a/41655546 +sleep infinity diff --git a/dx/start b/dx/start new file mode 100755 index 0000000..02b9680 --- /dev/null +++ b/dx/start @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" +require_command "docker" + +usage_on_help "Starts all services, including a container in which to run your app" "" "${@}" +ensure_docker_compose_env + +log "πŸš€" "Starting docker-compose.dx.yml" + +BUILD=--build +if [ "${1}" == "--no-build" ]; then + BUILD= +fi + +docker compose -f docker-compose.dx.yml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" up ${BUILD} --timestamps --force-recreate + +# vim: ft=bash diff --git a/dx/stop b/dx/stop new file mode 100755 index 0000000..c3b7fe6 --- /dev/null +++ b/dx/stop @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) + +. "${SCRIPT_DIR}/dx.sh.lib" +require_command "docker" + +usage_on_help "Stops all services, the container in which to run your app and removes any volumes" "" "${@}" +ensure_docker_compose_env + +log "πŸš€" "Starting docker-compose.dx.yml" + +log "πŸš‰" "Exporting DOCKER_DEFAULT_PLATFORM as '${DOCKER_DEFAULT_PLATFORM}'" +export DOCKER_DEFAULT_PLATFORM +docker compose -f docker-compose.dx.yml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" down -v + +# vim: ft=bash From 766af6de8e1809c268c33283f9f3e70743f63b57 Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Mon, 15 Jul 2024 10:00:46 -0400 Subject: [PATCH 2/9] remove --- .tool-versions | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index a9e31a4..0000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -ruby 2.7.1 From 7185267c0ed77b5a819a99fd746503e2da0f4a07 Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 10:53:19 -0400 Subject: [PATCH 3/9] remove warnings from test runs --- Rakefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Rakefile b/Rakefile index a94e247..ae0c8a9 100644 --- a/Rakefile +++ b/Rakefile @@ -80,6 +80,9 @@ Rake::TestTask.new("test:unit") do |t| ENV["RUBYOPT"].split(/\s/).each do |opt| t.ruby_opts << opt end + if t.ruby_opts.none? { |x| x =~ /^\-W/ } + t.ruby_opts << "-W0" + end t.test_files = FileList["test/unit/**/*_test.rb"] end @@ -89,6 +92,9 @@ Rake::TestTask.new("test:integration") do |t| ENV["RUBYOPT"].split(/\s/).each do |opt| t.ruby_opts << opt end + if t.ruby_opts.none? { |x| x =~ /^\-W/ } + t.ruby_opts << "-W0" + end explicitly_named_files = ARGV[1..-1] if Array(explicitly_named_files).size == 0 t.test_files = FileList["test/integration/**/*_test.rb"] From 80d9fdc0d28e0f5c47645d203166d24f4e873114 Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 10:53:36 -0400 Subject: [PATCH 4/9] Change to `Minitest`, since that is the standard as of 10 years ago --- test/integration/gli_cli_test.rb | 2 +- test/integration/gli_powered_app_test.rb | 2 +- test/integration/scaffold_test.rb | 2 +- test/unit/command_finder_test.rb | 2 +- test/unit/command_test.rb | 2 +- test/unit/compound_command_test.rb | 2 +- test/unit/doc_test.rb | 2 +- test/unit/flag_test.rb | 2 +- test/unit/gli_test.rb | 2 +- test/unit/help_test.rb | 2 +- test/unit/options_test.rb | 2 +- test/unit/subcommand_parsing_test.rb | 2 +- test/unit/subcommands_test.rb | 2 +- test/unit/switch_test.rb | 2 +- test/unit/terminal_test.rb | 2 +- test/unit/verbatim_wrapper_test.rb | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/test/integration/gli_cli_test.rb b/test/integration/gli_cli_test.rb index ea0de0e..5fed7ce 100644 --- a/test/integration/gli_cli_test.rb +++ b/test/integration/gli_cli_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require "open3" -class GLICLITest < MiniTest::Test +class GLICLITest < Minitest::Test include TestHelper class AppHelp < GLICLITest diff --git a/test/integration/gli_powered_app_test.rb b/test/integration/gli_powered_app_test.rb index b4e3074..8323507 100644 --- a/test/integration/gli_powered_app_test.rb +++ b/test/integration/gli_powered_app_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require "open3" -class GLIPoweredAppTest < MiniTest::Test +class GLIPoweredAppTest < Minitest::Test include TestHelper def teardown diff --git a/test/integration/scaffold_test.rb b/test/integration/scaffold_test.rb index 2c3559f..5f5ce51 100644 --- a/test/integration/scaffold_test.rb +++ b/test/integration/scaffold_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require "open3" -class ScaffoldCommandTest < MiniTest::Test +class ScaffoldCommandTest < Minitest::Test include TestHelper def test_scaffolded_app_has_reasonable_setup diff --git a/test/unit/command_finder_test.rb b/test/unit/command_finder_test.rb index b9df403..6ec4c0d 100644 --- a/test/unit/command_finder_test.rb +++ b/test/unit/command_finder_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class CommandFinderTest < MiniTest::Test +class CommandFinderTest < Minitest::Test include TestHelper def setup diff --git a/test/unit/command_test.rb b/test/unit/command_test.rb index dad9e3c..b86176d 100644 --- a/test/unit/command_test.rb +++ b/test/unit/command_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require_relative "support/fake_std_out" -class CommandTest < MiniTest::Test +class CommandTest < Minitest::Test include TestHelper def setup @fake_stdout = FakeStdOut.new diff --git a/test/unit/compound_command_test.rb b/test/unit/compound_command_test.rb index 1734c55..4fb1d9f 100644 --- a/test/unit/compound_command_test.rb +++ b/test/unit/compound_command_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class CompoundCommandFinderTest < MiniTest::Test +class CompoundCommandFinderTest < Minitest::Test include TestHelper def test_exception_for_missing_commands diff --git a/test/unit/doc_test.rb b/test/unit/doc_test.rb index 14a9cd4..20fc7b3 100644 --- a/test/unit/doc_test.rb +++ b/test/unit/doc_test.rb @@ -18,7 +18,7 @@ def blank? end end -class DocTest < MiniTest::Test +class DocTest < Minitest::Test include TestHelper class TestApp diff --git a/test/unit/flag_test.rb b/test/unit/flag_test.rb index 93d4bdb..939095c 100644 --- a/test/unit/flag_test.rb +++ b/test/unit/flag_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class FlagTest < MiniTest::Test +class FlagTest < Minitest::Test include TestHelper def test_basics_simple diff --git a/test/unit/gli_test.rb b/test/unit/gli_test.rb index 985a998..57636e4 100644 --- a/test/unit/gli_test.rb +++ b/test/unit/gli_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require_relative "support/fake_std_out" -class GLITest < MiniTest::Test +class GLITest < Minitest::Test include TestHelper def setup diff --git a/test/unit/help_test.rb b/test/unit/help_test.rb index cc514cf..03d8f82 100644 --- a/test/unit/help_test.rb +++ b/test/unit/help_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class HelpTest < MiniTest::Test +class HelpTest < Minitest::Test include TestHelper def setup diff --git a/test/unit/options_test.rb b/test/unit/options_test.rb index 20e7e71..a97460b 100644 --- a/test/unit/options_test.rb +++ b/test/unit/options_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class OptiosnTest < MiniTest::Test +class OptiosnTest < Minitest::Test include TestHelper def test_by_method diff --git a/test/unit/subcommand_parsing_test.rb b/test/unit/subcommand_parsing_test.rb index 209dc02..8697d4a 100644 --- a/test/unit/subcommand_parsing_test.rb +++ b/test/unit/subcommand_parsing_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require_relative "support/fake_std_out" -class SubcommandParsingTest < MiniTest::Test +class SubcommandParsingTest < Minitest::Test include TestHelper def setup diff --git a/test/unit/subcommands_test.rb b/test/unit/subcommands_test.rb index b0c7bd5..5c7884a 100644 --- a/test/unit/subcommands_test.rb +++ b/test/unit/subcommands_test.rb @@ -1,7 +1,7 @@ require_relative "test_helper" require_relative "support/fake_std_out" -class SubcommandsTest < MiniTest::Test +class SubcommandsTest < Minitest::Test include TestHelper def setup diff --git a/test/unit/switch_test.rb b/test/unit/switch_test.rb index 4d00332..caabd81 100644 --- a/test/unit/switch_test.rb +++ b/test/unit/switch_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class SwitchTest < MiniTest::Test +class SwitchTest < Minitest::Test include TestHelper def test_basics_simple diff --git a/test/unit/terminal_test.rb b/test/unit/terminal_test.rb index cc07445..b666c76 100644 --- a/test/unit/terminal_test.rb +++ b/test/unit/terminal_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class TerminalTest < MiniTest::Test +class TerminalTest < Minitest::Test include TestHelper # TODO: Make this test not mess with the internals of the class diff --git a/test/unit/verbatim_wrapper_test.rb b/test/unit/verbatim_wrapper_test.rb index ac3d31a..19c4fa1 100644 --- a/test/unit/verbatim_wrapper_test.rb +++ b/test/unit/verbatim_wrapper_test.rb @@ -1,6 +1,6 @@ require_relative "test_helper" -class TerminalTest < MiniTest::Test +class TerminalTest < Minitest::Test include TestHelper def test_handles_nil From 8251eb06a61a30dec1b03c7cda0c36393ed534a1 Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 11:22:18 -0400 Subject: [PATCH 5/9] Clarify minitest dependency. Also, change bin/setup to account for changes in the gemspec --- bin/setup | 10 ++++++++-- gli.gemspec | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/bin/setup b/bin/setup index 6c02e2e..376f7b5 100755 --- a/bin/setup +++ b/bin/setup @@ -1,5 +1,11 @@ #!/bin/bash set -e - -bundle check || bundle install +if [ Gemfile.lock -ot gli.gemspec ] ; then + echo "[ bin/setup ] gli.gemspec has been modified - deleting Gemfile.lock" + rm Gemfile.lock + bundle install +else + echo "[ bin/setup ] checking bundle and updating as necessary" + bundle check || bundle install +fi diff --git a/gli.gemspec b/gli.gemspec index 3b2c1ac..81cfe82 100644 --- a/gli.gemspec +++ b/gli.gemspec @@ -26,5 +26,5 @@ spec = Gem::Specification.new do |s| s.add_development_dependency("rdoc") s.add_development_dependency("rainbow", "~> 1.1", "~> 1.1.1") s.add_development_dependency("sdoc") - s.add_development_dependency("minitest") + s.add_development_dependency("minitest", "~> 5") end From d355c102c29e865ff81c7c5e163b056688f8065d Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 11:23:26 -0400 Subject: [PATCH 6/9] remove CircleCI as it almost never works and requires constant upkeep --- .circleci/config.yml | 30 ------------------------------ 1 file changed, 30 deletions(-) delete mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 8ffe556..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: 2.1 -orbs: - # See https://circleci.com/developer/orbs/orb/circleci/ruby - ruby: circleci/ruby@2.0.1 -jobs: # keyword - test: # my name for the job - parameters: # keyword - ruby-version: # my parameter name - type: string # type is a keyword - docker: # keyword - - image: cimg/base:stable - steps: # keyword - - checkout # magic name - - ruby/install: # ruby/ is from the orb name, install is a command in that orb - version: << parameters.ruby-version >> # magic nonsense for param subst (version param to the command) - - run: - command: "bin/setup" - - run: - command: "bin/ci none" -workflows: # keyword - all-rubies: # my name for the workflow - jobs: # keyword - - test: # my name for the job - matrix: # keyword - parameters: # keyword - # All rubies being maintained per this page: - # https://www.ruby-lang.org/en/downloads/branches/ - # These also need to have complete version numbers - # or rvm won't install - ruby-version: [ "3.0.4", "3.1.3", "3.2.2" ] From 31fa4e228b24db1ec7f208f29f91b1f8acaaadfa Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 11:58:10 -0400 Subject: [PATCH 7/9] update development tools to use Docker --- .gitignore | 3 ++ CONTRIBUTING.md | 81 ++++++++++++++++++++++++++++---------- Dockerfile.dx | 3 +- README.rdoc | 8 +++- docker-compose.dx.yml | 32 +++++++++++---- dx/build | 67 ++++++++++++++++++++++--------- dx/docker-compose.base.env | 18 --------- dx/docker-compose.env | 28 ++----------- dx/dx.sh.lib | 37 ++++++----------- dx/exec | 55 ++++++++++++++++++++------ dx/prune | 4 +- dx/setup | 57 --------------------------- dx/setupkit.sh.lib | 41 +++++++++++++++---- dx/start | 14 +++++-- dx/stop | 16 +++++--- 15 files changed, 259 insertions(+), 205 deletions(-) delete mode 100644 dx/docker-compose.base.env delete mode 100755 dx/setup diff --git a/.gitignore b/.gitignore index ba09434..7e89364 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ results.html Session.vim scaffold_test dx/docker-compose.local.env +docker-compose.dx.yml +.tool-versions +.ruby-version diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 66b25a3..75bced8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,21 +1,60 @@ -Contributions are welcome as long as they are part of my vision for GLI (or can be treated as optional to the user). I am obsessive about backwards-compatibility, so you may need to default things to disable your features. Sorry, not ready to bump a major version any time soon. - -1. Fork my Repository -2. Create a branch off of main -3. Make your changes: - * Please include tests and watch out for reek and roodi; i.e. keep your code clean - * If you make changes to the gli executable or the scaffolding, please update the cucumber features - * Please rubydoc any new methods and update the rubydoc to methods you change in the following format: -```ruby - # Short description - # - # Longer description if needed - # - # +args+:: get documented using this syntax - # +args+:: please state the TYPE of every arg - # - # Returns goes here, please state the TYPE of what's returned, if anything -``` - * Use # :nodoc: for methods that a _user_ of GLI should not call (but still please do document all methods) -4. Make sure your branch will merge with my gli-2 branch (or just rebase your branch from my gli-2 branch) -5. Create a pull request explaining your change +# Contributing/Developing + +## Types of Contributions + +GLI is relatively stable. As such: + +* No major new features should be added +* No refactorings or "modernization" is desired +* No runtime dependencies should be added. + +If you really want to make a change like this, open an issue first to discuss. + +That said, I welcome: + +* Bugfixes +* Doc changes +* Minor improvements + +I am responsive on issues, so reach out there if you have a question. + +## How to Do Development + +GLI us using a Docker-based development system to ensure consistency. To use it, you will need to have Docker installed, as well +as Bash. This should all work under Windows Subsystem for Linux. + +### Setting Up + +1. Install Docker +2. `dx/build` + + This will use `Dockerfile.dx` to create one Docker image for each supported Ruby version (see `dx/docker-compose.env`'s `RUBY_VERSIONS` variable for the current list). This will also generate `docker-compose.dx.yml` which will run all versions of Ruby for GLI at the same time. +3. `dx/start` + + This will start Docker using `docker-compose.dx.yml`, which will run containers for all the images generated by `dx/build` + +4. From here, you can run commands inside the running containers, or you can run `bash` inside a container to effectively "log + in" and run commands. + +### Doing Development + +Once you are set up, you should run `dx/exec bash`. This will log you into the container running the oldest supported version of +Ruby. This is the version where you should do your basic work. This container has access to the source code you cloned from +GitHub. + +1. `on-your-computer> dx/exec bash` +2. `inside-docker-container> bin/setup # installs all gems` +3. `inside-docker-container> bin/rake # runs all tests` + +Once you have stuff working, run tests on the other versions. Since the container you were working in was operating on your +checked-out files, the other containers will have access as well. + +1. `on-your-computer> dx/exec -v 3.3 bash # connects to the conatiner where Ruby 3.3 is installed` +2. `inside-docker-container> bin/setup # installs all gems` +3. `inside-docker-container> bin/rake # runs all tests` + +#### If You Want To Use Your Local Computer + +In theory, GLI can be worked on using RVM, RBEnv, asdf, or whatever other way you want to manage Ruby. You can create a +`.ruby-version` or `.tool-versions`. These are ignored so you can keep them on your machine. I don't support this setup, so if +something is wrong, I probably can't help. This is why I have it set up with Docker. diff --git a/Dockerfile.dx b/Dockerfile.dx index bfa4374..2710a5e 100644 --- a/Dockerfile.dx +++ b/Dockerfile.dx @@ -1,4 +1,5 @@ -FROM ruby:3.1 +ARG RUBY_VERSION +FROM ruby:${RUBY_VERSION} ENV DEBIAN_FRONTEND noninteractive RUN apt-get -y update diff --git a/README.rdoc b/README.rdoc index e60f99e..6f94595 100644 --- a/README.rdoc +++ b/README.rdoc @@ -92,9 +92,9 @@ Get a more detailed walkthrough on the {main site}[http://davetron5000.github.io == Supported Platforms -See `.circleci/config.yml` for the supported rubies, but general we're running tests on the all MRI rubies receiving support, which tends to be the most recent four versions. +See `dx/docker-compose.env` and the variable `RUBY_VERSIONS` for the versions that are supported. This should generally track with the supported version of Ruby from Ruby's maintainers. -GLI should work on older Rubies and JRuby, but it's too much work to keep tests passing for those. +That said, GLI should generally work on other Rubies as it doesn't have any runtime dependencies and there are no plans to use more modern features of Ruby in the codebase. == Documentation @@ -102,6 +102,10 @@ Extensive documentation is {available at the wiki}[https://github.com/davetron50 API Documentation is available {here}[http://davetron5000.github.io/gli/rdoc/index.html]. Recommend starting with GLI::DSL or GLI::App. +== Developing + +See `CONTRIBUTING.md` + == Credits Author:: Dave Copeland (mailto:davetron5000 at g mail dot com) diff --git a/docker-compose.dx.yml b/docker-compose.dx.yml index ac06d71..503debb 100644 --- a/docker-compose.dx.yml +++ b/docker-compose.dx.yml @@ -1,11 +1,28 @@ +# THIS IS GENERATED - DO NOT EDIT + services: - app: - image: ${IMAGE} - build: - context: "./" - dockerfile: "Dockerfile.dx" - platform: ${DOCKER_DEFAULT_PLATFORM} - pull_policy: "missing" + gli-3.1: + image: davetron5000/gli-dev:ruby-3.1 + init: true + volumes: + - type: bind + source: "./" + target: "/root/work" + consistency: "consistent" + entrypoint: /root/show-help-in-app-container-then-wait.sh + working_dir: /root/work + gli-3.2: + image: davetron5000/gli-dev:ruby-3.2 + init: true + volumes: + - type: bind + source: "./" + target: "/root/work" + consistency: "consistent" + entrypoint: /root/show-help-in-app-container-then-wait.sh + working_dir: /root/work + gli-3.3: + image: davetron5000/gli-dev:ruby-3.3 init: true volumes: - type: bind @@ -14,4 +31,3 @@ services: consistency: "consistent" entrypoint: /root/show-help-in-app-container-then-wait.sh working_dir: /root/work - diff --git a/dx/build b/dx/build index 20bd6a6..942ae52 100755 --- a/dx/build +++ b/dx/build @@ -7,23 +7,54 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) . "${SCRIPT_DIR}/dx.sh.lib" require_command "docker" - -usage_on_help "Builds the Docker image based on the Dockerfile" "" "${@}" -ensure_docker_compose_env - -if [[ -f "${SCRIPT_DIR}/build.pre" && -x "${SCRIPT_DIR/build.pre}" ]]; then - log "🎬" "${SCRIPT_DIR}/build.pre exists - executing" - "${SCRIPT_DIR}/build.pre" Dockerfile.dx "${IMAGE}" -fi -docker build -f Dockerfile.dx -t "${IMAGE}" ./ - -log "🌈" "Your Docker image has been built tagged '${IMAGE}'" -log "πŸ”„" "You can now run dx/start to start it up, though you may need to stop it first with Ctrl-C" - -if [[ -f "${SCRIPT_DIR}/build.post" && -x "${SCRIPT_DIR/build.post}" ]]; then - log "🎬" "build.post exists - executing" - "${SCRIPT_DIR}/build.post" Dockerfile.dx "${IMAGE}" -fi -log "βœ…" "Done" +load_docker_compose_env + +usage_on_help "Builds the Docker image based on the Dockerfile" "" "build.pre" "build.post" "${@}" + +for ruby_version in ${RUBY_VERSIONS[@]}; do + dockerfile="Dockerfile.dx" + docker_image_name="${IMAGE}:ruby-${ruby_version}" + + log "Building for Ruby '${ruby_version}' using Docker image name '${docker_image_name}'" + + exec_hook_if_exists "build.pre" "${dockerfile}" "${docker_image_name}" + + docker build \ + --file "${dockerfile}" \ + --build-arg="RUBY_VERSION=${ruby_version}" \ + --tag "${docker_image_name}" \ + ./ + + exec_hook_if_exists "build.post" "${dockerfile}" "${docker_image_name}" + log "🌈" "Your Docker image has been built tagged '${docker_image_name}'" +done + +log "βœ…" "All images built" + +log "✨" "Creating docker-compose.dx.yml" +compose_file="docker-compose.dx.yml" +log "πŸ—‘οΈ" "Deleting previous ${compose_file}" + +rm "${compose_file}" +echo "# THIS IS GENERATED - DO NOT EDIT" > "${compose_file}" +echo "" >> "${compose_file}" +echo "services:" >> "${compose_file}" + +for ruby_version in ${RUBY_VERSIONS[@]}; do + log "Generating stanza for version '${ruby_version}'" + docker_image_name="${IMAGE}:ruby-${ruby_version}" + echo " gli-${ruby_version}:" >> "${compose_file}" + echo " image: ${docker_image_name}" >> "${compose_file}" + echo " init: true" >> "${compose_file}" + echo " volumes:" >> "${compose_file}" + echo " - type: bind" >> "${compose_file}" + echo " source: \"./\"" >> "${compose_file}" + echo " target: \"/root/work\"" >> "${compose_file}" + echo " consistency: \"consistent\"" >> "${compose_file}" + echo " entrypoint: /root/show-help-in-app-container-then-wait.sh" >> "${compose_file}" + echo " working_dir: /root/work" >> "${compose_file}" +done +log "🎼" "${compose_file} is noq created" +log "πŸ”„" "You can run dx/start to start it up, though you may need to stop it first with Ctrl-C" # vim: ft=bash diff --git a/dx/docker-compose.base.env b/dx/docker-compose.base.env deleted file mode 100644 index 0039396..0000000 --- a/dx/docker-compose.base.env +++ /dev/null @@ -1,18 +0,0 @@ -# IMAGE is the name of the image to be built for running -# your app. The recommended format is ORG/REPO:TAG -# -# ORG - your org on GitHub or DockerHub -# REPO - the name of the repo on GitHub or the app name -# TAG - a version identifier. Recommend you avoid latest as this is confusing -IMAGE=davetron5000/gli:ruby-3.2 - -# This is used to tell docker compose what the name -# of your project is for the purpose of naming -# containers. It can be anything and is mostly -# used for pruning containers via bin/prune -PROJECT_NAME=gli - -# Use this to override the service name for your -# app in docker-compose.dx.yml -DEFAULT_SERVICE=app -# vim: ft=bash diff --git a/dx/docker-compose.env b/dx/docker-compose.env index 887160c..b28cc42 100644 --- a/dx/docker-compose.env +++ b/dx/docker-compose.env @@ -1,27 +1,5 @@ -# This is generated - do not edit -# -# To make changes for the project, edit dx/docker-compose.base.env -# To make changes for your computer, edit dx/docker-compose.local.env -# Delete this file after changing either of those -# - -# IMAGE is the name of the image to be built for running -# your app. The recommended format is ORG/REPO:TAG -# -# ORG - your org on GitHub or DockerHub -# REPO - the name of the repo on GitHub or the app name -# TAG - a version identifier. Recommend you avoid latest as this is confusing -IMAGE=davetron5000/gli:ruby-3.2 - -# This is used to tell docker compose what the name -# of your project is for the purpose of naming -# containers. It can be anything and is mostly -# used for pruning containers via bin/prune +# This array must include the oldest Ruby first! +RUBY_VERSIONS=("3.1" "3.2" "3.3") +IMAGE=davetron5000/gli-dev PROJECT_NAME=gli - -# Use this to override the service name for your -# app in docker-compose.dx.yml -DEFAULT_SERVICE=app # vim: ft=bash -DOCKER_DEFAULT_PLATFORM=linux/arm64 - diff --git a/dx/dx.sh.lib b/dx/dx.sh.lib index 1a46ea0..6aecb9c 100644 --- a/dx/dx.sh.lib +++ b/dx/dx.sh.lib @@ -6,34 +6,19 @@ require_command "realpath" require_command "cat" ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.env -BASE_ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.base.env -LOCAL_ENV_FILE=$(realpath "${SCRIPT_DIR}")/docker-compose.local.env -DOT_DOT=$(realpath "${SCRIPT_DIR}/..")/ -ENV_FILE_RELATIVE=${ENV_FILE//"${DOT_DOT}"/} -BASE_ENV_FILE_RELATIVE=${BASE_ENV_FILE//"${DOT_DOT}"/} -LOCAL_ENV_FILE_RELATIVE=${LOCAL_ENV_FILE//"${DOT_DOT}"/} +load_docker_compose_env() { + . "${ENV_FILE}" +} -ensure_docker_compose_env() { - if [ ! -e "${ENV_FILE}" ]; then - if [ ! -e "${LOCAL_ENV_FILE}" ]; then - fatal "Looks like you have not set up yet. Please run dx/setup" - else - log "πŸ—„" "Creating ${ENV_FILE_RELATIVE} from ${LOCAL_ENV_FILE_RELATIVE} and ${BASE_ENV_FILE_RELATIVE}" - echo "# This is generated - do not edit" > "${ENV_FILE}" - { - echo "#" - echo "# To make changes for the project, edit ${BASE_ENV_FILE_RELATIVE}" - echo "# To make changes for your computer, edit ${LOCAL_ENV_FILE_RELATIVE}" - echo "# Delete this file after changing either of those" - echo "#" - echo "" - cat "${BASE_ENV_FILE}" - grep -v ^# "${LOCAL_ENV_FILE}" - } >> "${ENV_FILE}" - fi +exec_hook_if_exists() { + script_name=$1 + shift + if [ -x "${SCRIPT_DIR}"/"${script_name}" ]; then + log "πŸͺ" "${script_name} exists - executing" + "${SCRIPT_DIR}"/"${script_name}" "${@}" + else + debug "${script_name} does not exist" fi - # shellcheck disable=SC1090 - . "${ENV_FILE}" } # vim: ft=bash diff --git a/dx/exec b/dx/exec index 5cff700..a1bad31 100755 --- a/dx/exec +++ b/dx/exec @@ -7,20 +7,53 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) . "${SCRIPT_DIR}/dx.sh.lib" require_command "docker" +load_docker_compose_env -usage_on_help "Execute a command inside the app's container. Use enviornment variable SERVICE_NAME to execute inside another service" "command" "${@}" -ensure_docker_compose_env +usage_description="Execute a command inside the app's container." +usage_args="[-s service] [-v ruby_version] command" +usage_pre="exec.pre" +usage_on_help "${usage_description}" "${usage_args}" "${usage_pre}" "" "${@}" -CMD=$* - -if [ -z "$CMD" ]; then - log "😐" "You should specify a command to run e.g. $0 ls -l" - echo - usage +LATEST_RUBY=${RUBY_VERSIONS[0]} +DEFAULT_SERVICE=gli-${LATEST_RUBY} +SERVICE="${SERVICE_NAME:-${DEFAULT_SERVICE}}" +while getopts "v:s:" opt "${@}"; do + case ${opt} in + v ) + SERVICE="gli-${OPTARG}" + ;; + s ) + SERVICE="${OPTARG}" + ;; + \? ) + log "πŸ›‘" "Unknown option: ${opt}" + usage "${description}" "${usage_args}" "${usage_pre}" + ;; + : ) + log "πŸ›‘" "Invalid option: ${opt} requires an argument" + usage "${description}" "${usage_args}" "${usage_pre}" + ;; + esac +done +shift $((OPTIND -1)) + +if [ $# -eq 0 ]; then + log "πŸ›‘" "You must provide a command e.g. bash or ls -l" + usage "${description}" "${usage_args}" "${usage_pre}" fi -SERVICE="${SERVICE_NAME:-${DEFAULT_SERVICE}}" -log "πŸš‚" "Running '$CMD' inside container with service name '${SERVICE}'" -docker compose -f docker-compose.dx.yaml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" exec "${SERVICE}" "${@}" + +exec_hook_if_exists "exec.pre" + +log "πŸš‚" "Running '${*}' inside container with service name '${SERVICE}'" + +docker \ + compose \ + --file docker-compose.dx.yaml \ + --project-name "${PROJECT_NAME}" \ + --env-file "${ENV_FILE}" \ + exec \ + "${SERVICE}" \ + "${@}" # vim: ft=bash diff --git a/dx/prune b/dx/prune index 001ff1e..e4a46ff 100755 --- a/dx/prune +++ b/dx/prune @@ -6,9 +6,9 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) . "${SCRIPT_DIR}/dx.sh.lib" require_command "docker" +load_docker_compose_env -usage_on_help "Prune containers for this repo" "command" "${@}" -ensure_docker_compose_env +usage_on_help "Prune containers for this repo" "" "" "" "${@}" for container_id in $(docker container ls -a -f "name=^${PROJECT_NAME}-.*-1$" --format="{{.ID}}"); do log "πŸ—‘" "Removing container with id '${container_id}'" diff --git a/dx/setup b/dx/setup deleted file mode 100755 index 738d3eb..0000000 --- a/dx/setup +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -set -e - -SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) - -. "${SCRIPT_DIR}/dx.sh.lib" -require_command "docker" -require_command "ruby" - -usage_on_help "Initialize your development environment" "command" "${@}" - -if [ -e "${LOCAL_ENV_FILE}" ]; then - fatal "You're already set up. Delete ${LOCAL_ENV_FILE_RELATIVE} and start over if you want to reset" -fi - -while [ -z "${DOCKER_DEFAULT_PLATFORM}" ]; do - if ! command -v ruby > /dev/null 2>&1 ; then - PLATFORM_GUESS="" - else - PLATFORM_GUESS=$(docker version -f json | ruby -rjson -e "x = JSON.parse(STDIN.read)['Server']; puts x['Os'] + '/' + x['Arch']") - fi - - - user_input "πŸ’Ύ" "Enter your 'Docker Platform' or type 'help' to get help on choosing" "${PLATFORM_GUESS}" - DOCKER_DEFAULT_PLATFORM="${INPUT}" - if [ "${DOCKER_DEFAULT_PLATFORM}" = "help" ]; then - log - log "ℹ️ " "Should be in format Β«osΒ»/Β«archΒ» or Β«osΒ»/Β«archΒ»/Β«variantΒ»" - log - log "πŸͺŸ" "If you are on an Intel or AMD chip, you most likely want linux/amd64" - log "🍎" "If you are on Apple Silicon, you most likely want linux/arm64/v8" - log "🀷" "Otherwise, prepare yourself:" - log - log "πŸ•΅οΈ" "To figure this out you need to choose an os and an arch that match the list here:" - log "🌎" "https://go.dev/doc/install/source#environment" - log "πŸ”Ž" "(search for GOOS on that page)" - log - log "😒" "For the variant, you are pretty much on your own, sorry" - log - DOCKER_DEFAULT_PLATFORM="" - fi -done - -log "😷" "Creating ${LOCAL_ENV_FILE_RELATIVE}" -echo "# This is specific to your computer and should not be checked in" > "${LOCAL_ENV_FILE}" -{ - echo "# If you have copied these from another computer, you may want" - echo "# to delete this file and re-run bin/set" - echo "DOCKER_DEFAULT_PLATFORM=${DOCKER_DEFAULT_PLATFORM}" - echo -} >> "${LOCAL_ENV_FILE}" - -ensure_docker_compose_env - -log "πŸŽ‰" "You are all set up. Try dx/build or dx/start" -# vim: ft=bash diff --git a/dx/setupkit.sh.lib b/dx/setupkit.sh.lib index dd19278..ef65a40 100644 --- a/dx/setupkit.sh.lib +++ b/dx/setupkit.sh.lib @@ -16,32 +16,59 @@ log() { if [ -z "${NO_EMOJI}" ]; then echo "[ ${0} ] ${*}" else + # if remainder is empty that means no emoji was passed if [ -z "$remainder" ]; then echo "[ ${0} ] ${*}" - else + else # emoji was passed, but we ignore it echo "[ ${0} ] ${remainder}" fi fi } +debug() { + message=$1 + if [ -z "${DOCKBOX_DEBUG}" ]; then + return + fi + log "πŸ›" "${message}" +} + usage() { - echo "usage: ${0} [-h] ${extra_usage}" - if [ -n "$1" ]; then + description=$1 + arg_names=$2 + pre_hook=$3 + post_hook=$4 + echo "usage: ${0} [-h] ${arg_names}" + if [ -n "${description}" ]; then echo echo "DESCRIPTION" echo " ${description}" fi + if [ -n "${pre_hook}" ] || [ -n "${post_hook}" ]; then + echo + echo "HOOKS" + if [ -n "${pre_hook}" ]; then + echo " ${pre_hook} - if present, called before the main action" + fi + if [ -n "${post_hook}" ]; then + echo " ${post_hook} - if present, called after the main action" + fi + fi exit 0 } usage_on_help() { description=$1 - extra_usage=$2 - cli_args=( "${@:3}" ) + arg_names=$2 + pre_hook=$3 + post_hook=$4 + # These are the args passed to the invocation so this + # function can determine if the user requested help + cli_args=( "${@:5}" ) for arg in "${cli_args[@]}"; do if [ "${arg}" = "-h" ] || [ "${arg}" = "--help" ]; then - usage "${description}" + usage "${description}" "${arg_names}" "${pre_hook}" "${post_hook}" fi done } @@ -71,7 +98,7 @@ user_input() { if [ -z "${prompt}" ]; then prompt=$(log "${emoji}" "Value: ") if [ -n "${default}" ]; then - prompt=$(log "${emoji}" "Value (or hit return to use '${default}): ") + prompt=$(log "${emoji}" "Value (or hit return to use '${default}'): ") fi fi diff --git a/dx/start b/dx/start index 02b9680..d400c63 100755 --- a/dx/start +++ b/dx/start @@ -6,9 +6,9 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) . "${SCRIPT_DIR}/dx.sh.lib" require_command "docker" +load_docker_compose_env -usage_on_help "Starts all services, including a container in which to run your app" "" "${@}" -ensure_docker_compose_env +usage_on_help "Starts all services, including a container in which to run your app" "" "" "" "${@}" log "πŸš€" "Starting docker-compose.dx.yml" @@ -17,6 +17,14 @@ if [ "${1}" == "--no-build" ]; then BUILD= fi -docker compose -f docker-compose.dx.yml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" up ${BUILD} --timestamps --force-recreate +docker \ + compose \ + --file docker-compose.dx.yml \ + --project-name "${PROJECT_NAME}" \ + --env-file "${ENV_FILE}" \ + up \ + "${BUILD}" \ + --timestamps \ + --force-recreate # vim: ft=bash diff --git a/dx/stop b/dx/stop index c3b7fe6..4560aed 100755 --- a/dx/stop +++ b/dx/stop @@ -6,14 +6,18 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${0}" )" > /dev/null 2>&1 && pwd ) . "${SCRIPT_DIR}/dx.sh.lib" require_command "docker" +load_docker_compose_env -usage_on_help "Stops all services, the container in which to run your app and removes any volumes" "" "${@}" -ensure_docker_compose_env +usage_on_help "Stops all services, the container in which to run your app and removes any volumes" "" "" "" "${@}" -log "πŸš€" "Starting docker-compose.dx.yml" +log "πŸš€" "Stopping docker-compose.dx.yml" -log "πŸš‰" "Exporting DOCKER_DEFAULT_PLATFORM as '${DOCKER_DEFAULT_PLATFORM}'" -export DOCKER_DEFAULT_PLATFORM -docker compose -f docker-compose.dx.yml -p "${PROJECT_NAME}" --env-file "${ENV_FILE}" down -v +docker \ + compose \ + --file docker-compose.dx.yml \ + --project-name "${PROJECT_NAME}" \ + --env-file "${ENV_FILE}" \ + down \ + --volumes # vim: ft=bash From e97a0f53d97208c3bf71c0a562907ab93b13fecf Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 13:12:49 -0400 Subject: [PATCH 8/9] fix bug in generated gemspec for Ruby 3.3 --- lib/gli/commands/scaffold.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gli/commands/scaffold.rb b/lib/gli/commands/scaffold.rb index 6303d6b..e48dd85 100644 --- a/lib/gli/commands/scaffold.rb +++ b/lib/gli/commands/scaffold.rb @@ -121,7 +121,7 @@ def self.mk_rakefile(root_dir,dry_run,project_name,create_test_dir) rd.title = 'Your application title' end -spec = eval(File.read('#{project_name}.gemspec')) +spec = Gem::Specification.load("#{project_name}.gemspec") Gem::PackageTask.new(spec) do |pkg| end From e4e2b1a5b542ad2aeb3e4dcc86d9673b79c7e2aa Mon Sep 17 00:00:00 2001 From: Dave Copeland Date: Tue, 16 Jul 2024 13:23:45 -0400 Subject: [PATCH 9/9] remove as this is now generated --- docker-compose.dx.yml | 33 --------------------------------- 1 file changed, 33 deletions(-) delete mode 100644 docker-compose.dx.yml diff --git a/docker-compose.dx.yml b/docker-compose.dx.yml deleted file mode 100644 index 503debb..0000000 --- a/docker-compose.dx.yml +++ /dev/null @@ -1,33 +0,0 @@ -# THIS IS GENERATED - DO NOT EDIT - -services: - gli-3.1: - image: davetron5000/gli-dev:ruby-3.1 - init: true - volumes: - - type: bind - source: "./" - target: "/root/work" - consistency: "consistent" - entrypoint: /root/show-help-in-app-container-then-wait.sh - working_dir: /root/work - gli-3.2: - image: davetron5000/gli-dev:ruby-3.2 - init: true - volumes: - - type: bind - source: "./" - target: "/root/work" - consistency: "consistent" - entrypoint: /root/show-help-in-app-container-then-wait.sh - working_dir: /root/work - gli-3.3: - image: davetron5000/gli-dev:ruby-3.3 - init: true - volumes: - - type: bind - source: "./" - target: "/root/work" - consistency: "consistent" - entrypoint: /root/show-help-in-app-container-then-wait.sh - working_dir: /root/work