add the pure bash core: core, str, naming and tags

Ported from make/utils.mk, make/def.mk, make/apps/def.docker.mk and
make/apps/def.mk, with the examples that sat as dead comments in
make/apps/def.mk turned into actual assertions.

Two deviations from the make macros are pinned and documented in DELTAS.md;
both only show up on code paths nothing uses.
This commit is contained in:
Yann Autissier
2026-09-03 18:26:00 +02:00
parent 6c97f99f87
commit 5b4db64114
9 changed files with 537 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
#shellcheck shell=sh
# Helper: myos_resu sets MYOS_RESU_NIAMOD/MYOS_RESU_PATH as a side effect;
# a subshell would lose them, so the assertion runs them here.
myos_resu "aya@github.com" >/dev/null
printf '%s %s\n' "$MYOS_RESU_NIAMOD" "$MYOS_RESU_PATH"
+125
View File
@@ -0,0 +1,125 @@
#shellcheck shell=sh
Include lib/str.sh
Include lib/core.sh
Include lib/naming.sh
Describe 'lib/naming.sh'
Describe 'myos_scope'
Parameters
"host/fabio" host
"host" host
"User/User" user
"user/ipfs" user
"cluster/postgres-ha" cluster
"postgres" app
"drone/drone" app
"./" app
End
It "scopes $1 as $2"
When call myos_scope "$1"
The output should equal "$2"
End
It 'honours an explicit MYOS_SCOPE'
MYOS_SCOPE=host
When call myos_scope postgres
The output should equal host
End
End
Describe 'myos_resu'
It 'turns a mail address into a user.domain identity'
When call myos_resu "aya@github.com"
The output should equal "aya.github.com"
End
It 'folds + and _ into dots, like the make macro'
When call myos_resu "aya+git@github.com"
The output should equal "aya.git.github.com"
End
It 'falls back to USER without a mail address'
USER=fallback
When call myos_resu ""
The output should equal "fallback"
End
It 'exposes the reversed identity and its path'
When run source spec/unit/naming_resu_helper.sh
The output should equal "com.github.aya com/github/aya"
End
End
Describe 'myos_project_name'
Describe 'app scope'
It 'defaults to user-env-app'
When call myos_project_name app aya master duniter
The output should equal "aya-master-duniter"
End
It 'keeps user-app-env when asked to'
MYOS_PROJECT_FORMAT=user-app-env
When call myos_project_name app aya master duniter
The output should equal "aya-duniter-master"
End
It 'normalizes the app name'
When call myos_project_name app aya local "My-App.v2"
The output should equal "aya-local-myappv2"
End
It 'appends the app path when there is one'
When call myos_project_name app aya local app sub/dir
The output should equal "aya-local-app-subdir"
End
It 'rejects an unknown format'
MYOS_PROJECT_FORMAT=nope
When run myos_project_name app aya local app
The status should equal 2
The stderr should include "unknown MYOS_PROJECT_FORMAT"
End
End
Describe 'other scopes'
It 'names a host stack after the machine'
HOSTNAME=sonic
When call myos_project_name host aya master fabio
The output should equal "sonic"
End
It 'prefers an explicit HOST_COMPOSE_PROJECT_NAME'
HOST_COMPOSE_PROJECT_NAME=axiomstudio
When call myos_project_name host aya master fabio
The output should equal "axiomstudio"
End
It 'names a user stack after the user identity'
MAIL=aya@github.com
When call myos_project_name user aya master User
The output should equal "aya-github-com"
End
It 'names a cluster stack after the stack itself'
When call myos_project_name cluster aya master postgres-ha
The output should equal "postgresha"
End
It 'always honours DOCKER_COMPOSE_PROJECT_NAME'
DOCKER_COMPOSE_PROJECT_NAME=explicit
When call myos_project_name app aya master duniter
The output should equal "explicit"
End
End
End
Describe 'networks'
It 'prefixes the default network so it is attached first'
When call myos_network_default "aya-master-duniter"
The output should equal "_aya-master-duniter"
End
It 'derives the private network from user and env'
When call myos_network_private aya master
The output should equal "aya-master"
End
It 'derives the public network from the hostname'
When call myos_network_public sonic
The output should equal "sonic"
End
End
Describe 'myos_service_name'
It 'replaces underscores with dashes'
When call myos_service_name "aya_master_app"
The output should equal "aya-master-app"
End
End
End
+70
View File
@@ -0,0 +1,70 @@
#shellcheck shell=sh
Include lib/str.sh
Describe 'lib/str.sh'
Describe 'myos_lower / myos_upper'
Parameters
"Foo-Bar" "foo-bar" "FOO_BAR"
"MYOS" "myos" "MYOS"
"a.b-c" "a.b-c" "A_B_C"
End
It "converts $1"
When call myos_lower "$1"
The output should equal "$2"
End
It "upcases $1 (- and . become _, as the make macro does)"
When call myos_upper "$1"
The output should equal "$3"
End
End
Describe 'myos_name'
Parameters
"Duniter" "duniter"
"my-app" "myapp"
"my_app.v2" "myappv2"
"host" "host"
End
It "normalizes $1 to a compose project fragment"
When call myos_name "$1"
The output should equal "$2"
End
End
Describe 'myos_reverse'
It 'reverses word order'
When call myos_reverse "com github aya"
The output should equal "aya github com"
End
It 'handles a single word'
When call myos_reverse "aya"
The output should equal "aya"
End
End
Describe 'myos_verle'
Parameters
"2.24.4" "2.29.0" success
"2.24.4" "2.24.4" success
"2.29.0" "2.24.4" failure
"2.5" "2.10" success
"" "2.24.4" failure
"2.24.4" "" failure
End
It "compares $1 <= $2"
When call myos_verle "$1" "$2"
The status should be "$3"
End
End
Describe 'myos_verlt'
It 'is false for equal versions'
When call myos_verlt "1.2.3" "1.2.3"
The status should be failure
End
It 'is true for a lower version'
When call myos_verlt "1.2.3" "1.10.0"
The status should be success
End
End
End
+109
View File
@@ -0,0 +1,109 @@
#shellcheck shell=sh
Include lib/str.sh
Include lib/core.sh
Include lib/tags.sh
# The expectations below are the very examples left as comments in
# make/apps/def.mk, which were never executed by anything.
Describe 'lib/tags.sh'
# APP_URI is "<host>/<path>" in the framework, so it always ends with a slash
# (make: APP_URI ?= $(patsubst %,%/$(APP_PATH),$(APP_HOST))).
BeforeEach 'APP_URI=app.domain/; APP_SCHEME=http'
Describe 'myos_urlprefix'
It 'routes the whole app by default'
When call myos_urlprefix
The output should equal "urlprefix-app.domain/*"
End
It 'routes a sub path'
When call myos_urlprefix "admin/"
The output should equal "urlprefix-app.domain/admin/*"
End
It 'carries fabio options'
When call myos_urlprefix ":443/" "proto=https" "app.domain"
The output should equal "urlprefix-app.domain:443/* proto=https"
End
It 'emits one comma separated tag per uri'
When call myos_urlprefix "" "" "a.domain/ b.domain/"
The output should equal "urlprefix-a.domain/*,urlprefix-b.domain/*"
End
End
Describe 'myos_uri'
It 'prefixes the base uri with the service name'
When call myos_uri kong 8000
The output should equal "kong.app.domain/"
End
It 'prefers an explicit service name'
SUPABASE_SERVICE_8000_NAME=studio
When call myos_uri supabase 8000
The output should equal "studio.app.domain/"
End
It 'expands every base uri'
When call myos_uri api 80 "a.tld b.tld"
The output should equal "api.a.tld api.b.tld"
End
End
Describe 'myos_url'
It 'prepends the scheme'
When call myos_url api 80
The output should equal "http://api.app.domain/"
End
End
Describe 'myos_envprefix'
It 'collects the fabio options that are set'
HOST_NGINX_SERVICE_443_PROTO="https tlsskipverify=true"
HOST_NGINX_SERVICE_443_STRIP="/api"
When call myos_envprefix HOST_NGINX 443 allow proto strip
The output should equal "proto=https tlsskipverify=true strip=/api"
End
It 'is empty when nothing is set'
When call myos_envprefix HOST_NGINX 443 allow proto strip
The output should equal ""
End
End
Describe 'myos_tagprefix'
It 'builds the tag of a service from its own uri'
When call myos_tagprefix supabase 8000
The output should equal "urlprefix-supabase.app.domain/*"
End
It 'uses the explicit URIS when there is one'
SUPABASE_SERVICE_8000_URIS="supabase.example.org/"
When call myos_tagprefix supabase 8000
The output should equal "urlprefix-supabase.example.org/*"
End
It 'appends the options collected from the SERVICE_<port>_* variables'
DUNITER_V2S_SERVICE_9944_STRIP="/ws"
DUNITER_V2S_SERVICE_9944_URIS="g1.example.org/"
When call myos_tagprefix duniter_v2s 9944
The output should equal "urlprefix-g1.example.org/* strip=/ws"
End
It 'honours an explicit PATH and OPTS'
HOST_FABIO_SERVICE_9998_PATH="admin/"
HOST_FABIO_SERVICE_9998_OPTS="proto=https"
HOST_FABIO_SERVICE_9998_URIS="fabio.example.org/"
When call myos_tagprefix host_fabio 9998
The output should equal "urlprefix-fabio.example.org/admin/* proto=https"
End
End
End
# Two deviations from the make macros, both documented in spec/golden/DELTAS.md:
# the make template leaves a stray space before the comma when it joins several
# uris, and it appends the url suffix after the options instead of after the
# path. Neither shape is used by anything on the fleet.
Describe 'lib/tags.sh deviations from the make macros'
BeforeEach 'APP_URI=app.domain/'
It 'joins several uris without a stray space'
When call myos_urlprefix "" "" "a.domain/ b.domain/"
The output should equal "urlprefix-a.domain/*,urlprefix-b.domain/*"
The output should not include " ,"
End
It 'keeps the url suffix right after the path when options are given'
When call myos_urlprefix ":443/" "proto=https" "app.domain"
The output should equal "urlprefix-app.domain:443/* proto=https"
End
End