-
Notifications
You must be signed in to change notification settings - Fork 81
/
run
executable file
·217 lines (178 loc) · 4.68 KB
/
run
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#!/usr/bin/env bash
#
# usage: ./run.sh command [argument ...]
#
# Commands used during development / CI.
# Also, executable documentation for project dev practices.
#
# See https://death.andgravity.com/run-sh
# for an explanation of how it works and why it's useful.
# First, set up the environment.
# (Check the notes at the end when changing this.)
set -o nounset
set -o pipefail
set -o errexit
# Enable this to echo commands as they are executed.
#set -o xtrace
# Change the current directory to the project root.
PROJECT_ROOT=${0%/*}
if [[ $0 != $PROJECT_ROOT && $PROJECT_ROOT != "" ]]; then
cd "$PROJECT_ROOT"
fi
readonly PROJECT_ROOT=$(pwd)
# Store the absolute path to this script (useful for recursion).
readonly SCRIPT="$PROJECT_ROOT/$(basename "$0")"
################################################################################
# Commands follow.
function all {
checks
}
function install-pio {
echo "📦 Installing PlatformIO project"
pio project init
}
function install-frontend {
echo "📦 Installing frontend dependencies"
( cd frontend && pnpm install )
}
function install {
echo "📦 Installing project and dependencies"
install-pio
install-frontend
}
function clean {
echo "🧹 Cleaning up"
rm -rf .pio/
rm -rf frontend/node_modules/
}
function build-pio {
echo "🏗️ Building the PlatformIO project"
pio run
}
function build-frontend {
echo "🏗️ Building the frontend"
( cd frontend && pnpm run css-compile )
( cd frontend && pnpm run build )
pio run -t frontend
}
function build {
echo "🏗️ Building the project"
build-frontend
build-pio
}
function upload {
echo "🚀 Uploading the project"
build
pio run -t upload
}
function upload-monitor {
echo "🚀 🖥️ Uploading the project and opening the serial monitor"
build
pio run -t upload --target monitor
}
function dev {
echo "👩💻 Starting development environment"
# TODO
}
function format {
echo "📝 Formatting code"
find src -print0 -name '*.cpp' -o -name '*.h' | xargs -0 xargs clang-format -i
( cd frontend && pnpm run format )
}
function lint {
echo "🔍 Linting code"
# TODO
}
function test {
echo "🧪 Running unit tests"
# Run tests
}
function checks {
echo "🔍 Running all checks"
# Run all checks
format
lint
test
}
function ci-test {
echo "🧪 Running tests in CI"
}
function help {
# list all "public" functions (those not beginning with an underscore)
# defined in this file
printf "%s <task> [args]\n\nTasks:\n" "${0}"
compgen -A function | grep -v "^_" | cat -n
printf "\nExtended help:\n Each task has comments for general usage\n"
}
################################################################################
# Helper functions
once_hash_array=()
function _once {
# Run a command only once during the execution of this script, even if it's
# called multiple times.
#
# Usage:
# _once <command> [argument ...]
#
# Example:
# _once echo "Hello"
# _once echo "Hello" # won't be executed
local command="$*"
local hash=$(echo "$command" | shasum | cut -d' ' -f1)
if [[ ! " ${once_hash_array[@]} " =~ " ${hash} " ]]; then
once_hash_array+=("$hash")
eval "$command"
fi
}
compose_flags=""
function _dc {
docker compose $compose_flags "$@"
}
function _env {
echo "🗝️ Setting environment from .env and .env.defaults"
# Go through the files and export all variables not already present in
# the environment. First file has precedence!
if [ -f .env ]; then
_export_unset .env
else
# Make sure a .env file exists, otherwise docker-compose will complain
cp .env.defaults .env
fi
_export_unset .env.defaults
}
function _export_unset {
local file="$1"
# Need to use a temp file to avoid a subshell
local tmpfile=$(mktemp)
grep -v '^#' $file > $tmpfile
while read -r line; do
if [[ ! "$line" =~ ^[[:space:]]*$ ]]; then
varname=$(echo "$line" | cut -d= -f1)
if [[ -z "${!varname:-}" ]]; then
eval $line
export $varname
fi
fi
done < $tmpfile
rm $tmpfile
}
function _test_export_unset {
_export_unset .env
env | sort
}
################################################################################
# Commands end.
# Dispatch to command. A simpler version would be just "$@" (with the quotes!).
TIMEFORMAT=$'\nTask completed in %3lR'
time "${@:-help}"
# Some dev notes for this script.
#
# The commands *require*:
#
# * The current working directory is the project root.
# * The shell options and globals are set as they are.
#
# Inspired by the following:
# - https://death.andgravity.com/run-sh
# - http://www.oilshell.org/blog/2020/02/good-parts-sketch.html
# - https://www.youtube.com/watch?v=SdmYd5hJISM&t=7s