Compare commits

..

1 Commits

Author SHA1 Message Date
b7a86e9841 - new workflows to test and publish aur builds 2024-04-14 01:42:46 -06:00
26 changed files with 253 additions and 727 deletions

View File

@ -44,7 +44,7 @@ commands:
custom: custom:
archlinux: archlinux:
prepare: prepare:
- &archlinux-prepare - &archlinux_prepare
run: run:
name: prepare archlinux dependencies name: prepare archlinux dependencies
command: | command: |
@ -52,26 +52,19 @@ custom:
useradd -m ci useradd -m ci
echo "ci ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers echo "ci ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
temp-downgrade-fakeroot:
- &archlinux-temp-downgrade-fakeroot
run:
name: downgrade fakeroot to v1.34 (v1.35 and v1.36 are confirmed to break)
command: |
pacman -U --noconfirm https://archive.archlinux.org/packages/f/fakeroot/fakeroot-1.34-1-x86_64.pkg.tar.zst
clone-aur: clone-aur:
- &archlinux-clone-aur - &archlinux_clone_aur
archlinux-run: archlinux-run:
_name: clone aur/scwrypts _name: clone aur/scwrypts
command: git clone https://aur.archlinux.org/scwrypts.git aur command: git clone https://aur.archlinux.org/scwrypts.git aur
clone-scwrypts: clone-scwrypts:
- &archlinux-clone-scwrypts - &archlinux_clone_scwrypts
run: run:
name: clone wrynegade/scwrypts name: clone wrynegade/scwrypts
working_directory: /home/ci working_directory: /home/ci
command: | command: |
GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git clone -b "$(echo $CIRCLE_BRANCH | grep . || echo $CIRCLE_TAG)" "$CIRCLE_REPOSITORY_URL" scwrypts GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git clone -b "$CIRCLE_BRANCH" "$CIRCLE_REPOSITORY_URL" scwrypts
chown -R ci:ci ./scwrypts chown -R ci:ci ./scwrypts
@ -90,10 +83,9 @@ jobs:
aur-test: aur-test:
executor: archlinux executor: archlinux
steps: steps:
- *archlinux-prepare - *archlinux_prepare
- *archlinux-temp-downgrade-fakeroot - *archlinux_clone_aur
- *archlinux-clone-aur - *archlinux_clone_scwrypts
- *archlinux-clone-scwrypts
- archlinux-run: - archlinux-run:
_name: test aur build on current source _name: test aur build on current source
working_directory: /home/ci/aur working_directory: /home/ci/aur
@ -110,22 +102,21 @@ jobs:
&& echo "source=(scwrypts.tar.gz)" >> PKGBUILD && echo "source=(scwrypts.tar.gz)" >> PKGBUILD
&& echo "sha256sums=(SKIP)" >> PKGBUILD && echo "sha256sums=(SKIP)" >> PKGBUILD
&& makepkg --noconfirm -si && makepkg --noconfirm -si
&& echo validating scwrypts version
&& scwrypts --version | grep "^scwrypts v$PKGVER$" && scwrypts --version | grep "^scwrypts v$PKGVER$"
; ;
aur-publish: aur-publish:
executor: archlinux executor: archlinux
steps: steps:
- *archlinux-prepare - *archlinux_prepare
- *archlinux-temp-downgrade-fakeroot - *archlinux_clone_aur
- *archlinux-clone-aur
- archlinux-run: - archlinux-run:
_name: update PKGBUILD and .SRCINFO _name: update PKGBUILD and .SRCINFO
working_directory: /home/ci/aur working_directory: /home/ci/aur
command: >- command: >-
: :
&& NEW_VERSION=$(echo $CIRCLE_TAG | sed 's/^v//') && NEW_VERSION=$(echo $CIRCLE_TAG | sed 's/^v//')
&& NEW_VERSION=4.2.0
&& sed "s/pkgver=.*/pkgver=$NEW_VERSION/; s/^pkgrel=.*/pkgrel=1/; /sha256sums/d" PKGBUILD -i && sed "s/pkgver=.*/pkgver=$NEW_VERSION/; s/^pkgrel=.*/pkgrel=1/; /sha256sums/d" PKGBUILD -i
&& makepkg -g >> PKGBUILD && makepkg -g >> PKGBUILD
&& makepkg --printsrcinfo > .SRCINFO && makepkg --printsrcinfo > .SRCINFO
@ -149,7 +140,7 @@ jobs:
&& eval $(ssh-agent) && eval $(ssh-agent)
&& echo -e $SSH_KEY_PRIVATE__AUR | ssh-add - && echo -e $SSH_KEY_PRIVATE__AUR | ssh-add -
&& git remote add upstream ssh://aur@aur.archlinux.org/scwrypts.git && git remote add upstream ssh://aur@aur.archlinux.org/scwrypts.git
&& GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git push upstream && echo 'DO THE GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git push upstream'
; ;
nodejs-test: nodejs-test:
@ -248,19 +239,18 @@ workflows:
test: test:
jobs: jobs:
- aur-test: - aur-test:
&dev-filters &dev_filters
filters: filters:
branches: branches:
ignore: /^main$/ ignore: /^main$/
- python-test: *dev-filters - python-test: *dev_filters
- nodejs-test: *dev-filters - nodejs-test: *dev_filters
publish: publish:
jobs: jobs:
- require-full-semver: - require-full-semver:
filters: filters:
&only-run-on-full-semver-tag-filters
tags: tags:
only: /^v\d+\.\d+\.\d+.*$/ only: /^v\d+\.\d+\.\d+.*$/
branches: branches:
@ -268,18 +258,8 @@ workflows:
- aur-test: - aur-test:
&only-publish-for-full-semver &only-publish-for-full-semver
filters: *only-run-on-full-semver-tag-filters requires: [require-full-semver]
requires:
- require-full-semver
- aur-publish: - aur-publish:
#
# there's a crazy-low-chance race-condition between this job and the GH Action '../.github/workflows/automatic-release.yaml'
# - automatic-release creates the release artifact, but takes no more than 15-30 seconds (current avg:16s max:26s)
# - this publish step requires the release artifact, but waits for all language-repository publishes to complete first (a few minutes at least)
#
# if something goes wrong, this step can be safely rerun after fixing the release artifact :)
#
filters: *only-run-on-full-semver-tag-filters
context: [aur-yage] context: [aur-yage]
requires: requires:
- aur-test - aur-test
@ -288,14 +268,10 @@ workflows:
- python-test: *only-publish-for-full-semver - python-test: *only-publish-for-full-semver
- python-publish: - python-publish:
filters: *only-run-on-full-semver-tag-filters
context: [pypi-yage]
requires: requires:
- python-test - python-test
- nodejs-test: *only-publish-for-full-semver - nodejs-test: *only-publish-for-full-semver
- nodejs-publish: - nodejs-publish:
filters: *only-run-on-full-semver-tag-filters
context: [npm-wrynegade]
requires: requires:
- nodejs-test - nodejs-test

View File

@ -12,9 +12,13 @@ export DISCORD__DEFAULT_AVATAR_URL=
export DISCORD__DEFAULT_CHANNEL_ID= export DISCORD__DEFAULT_CHANNEL_ID=
export DISCORD__DEFAULT_USERNAME= export DISCORD__DEFAULT_USERNAME=
export DISCORD__DEFAULT_WEBHOOK= export DISCORD__DEFAULT_WEBHOOK=
export I3__BORDER_PIXEL_SIZE=
export I3__DMENU_FONT_SIZE=
export I3__GLOBAL_FONT_SIZE=
export I3__MODEL_CONFIG=
export LINEAR__API_TOKEN= export LINEAR__API_TOKEN=
export MEDIA_SYNC__S3_BUCKET= export MEDIA_SYNC__S3_BUCKET
export MEDIA_SYNC__TARGETS= export MEDIA_SYNC__TARGETS
export REDIS_AUTH= export REDIS_AUTH=
export REDIS_HOST= export REDIS_HOST=
export REDIS_PORT= export REDIS_PORT=

View File

@ -15,6 +15,11 @@ DISCORD__DEFAULT_CHANNEL_ID |
DISCORD__DEFAULT_USERNAME | DISCORD__DEFAULT_USERNAME |
DISCORD__DEFAULT_WEBHOOK | DISCORD__DEFAULT_WEBHOOK |
I3__BORDER_PIXEL_SIZE | custom i3 configuration settings
I3__DMENU_FONT_SIZE |
I3__GLOBAL_FONT_SIZE |
I3__MODEL_CONFIG |
LINEAR__API_TOKEN | linear.app project management configuration LINEAR__API_TOKEN | linear.app project management configuration
MEDIA_SYNC__S3_BUCKET | s3 bucket name and filesystem targets for media backups MEDIA_SYNC__S3_BUCKET | s3 bucket name and filesystem targets for media backups

View File

@ -1,10 +1,11 @@
[[ $SCWRYPTS_KUBECTL_DRIVER_READY -eq 1 ]] && return 0 [[ $SCWRYPTS_KUBECTL_DRIVER_READY -eq 1 ]] && return 0
unalias k h f >/dev/null 2>&1 unalias k h >/dev/null 2>&1
k() { _SCWRYPTS_KUBECTL_DRIVER kubectl $@; } k() { _SCWRYPTS_KUBECTL_DRIVER kubectl $@; }
h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; } h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; }
f() { _SCWRYPTS_KUBECTL_DRIVER flux $@; } f() { _SCWRYPTS_KUBECTL_DRIVER flux $@; }
_SCWRYPTS_KUBECTL_DRIVER() { _SCWRYPTS_KUBECTL_DRIVER() {
[ ! $SCWRYPTS_ENV ] && { [ ! $SCWRYPTS_ENV ] && {
ERROR "must set SCWRYPTS_ENV in order to use '$(echo $CLI | head -c1)'" ERROR "must set SCWRYPTS_ENV in order to use '$(echo $CLI | head -c1)'"

View File

@ -4,7 +4,7 @@ from .scwrypts.exceptions import MissingVariableError
def getenv(name, required=True): def getenv(name, required=True):
value = os_getenv(f'{name}__override', os_getenv(name)) value = os_getenv(name, None)
if required and not value: if required and not value:
raise MissingVariableError(name) raise MissingVariableError(name)

View File

@ -2,22 +2,23 @@ from types import SimpleNamespace
from pytest import fixture from pytest import fixture
from scwrypts.test import get_generator from scwrypts.test import generate
from scwrypts.test.character_set import uri from scwrypts.test.character_set import uri
generate = get_generator({ options = {
'str_length_minimum': 8, 'str_length_minimum': 8,
'str_length_maximum': 128, 'str_length_maximum': 128,
'uuid_output_type': str, 'uuid_output_type': str,
}) }
def get_request_client_sample_data(): def get_request_client_sample_data():
return { return {
'base_url' : generate(str, {'character_set': uri}), 'base_url' : generate(str, options | {'character_set': uri}),
'endpoint' : generate(str, {'character_set': uri}), 'endpoint' : generate(str, options | {'character_set': uri}),
'method' : generate(str), 'method' : generate(str, options),
'response' : generate('requests_Response', {'depth': 4}), 'response' : generate('requests_Response', options | {'depth': 4}),
'payload' : generate(dict, { 'payload' : generate(dict, {
**options,
'depth': 1, 'depth': 1,
'data_types': { str, 'uuid' }, 'data_types': { str, 'uuid' },
}), }),
@ -29,11 +30,13 @@ def fixture_sample():
**get_request_client_sample_data(), **get_request_client_sample_data(),
headers = generate(dict, { headers = generate(dict, {
**options,
'depth': 1, 'depth': 1,
'data_types': { str, 'uuid' }, 'data_types': { str, 'uuid' },
}), }),
payload_headers = generate(dict, { payload_headers = generate(dict, {
**options,
'depth': 1, 'depth': 1,
'data_types': { str, 'uuid' }, 'data_types': { str, 'uuid' },
}), }),

View File

@ -2,14 +2,15 @@ from types import SimpleNamespace
from pytest import fixture from pytest import fixture
from scwrypts.test import generate
from scwrypts.test.character_set import uri from scwrypts.test.character_set import uri
from ..conftest import generate, get_request_client_sample_data from ..conftest import options, get_request_client_sample_data
@fixture(name='sample') @fixture(name='sample')
def fixture_sample(): def fixture_sample():
return SimpleNamespace( return SimpleNamespace(
**get_request_client_sample_data(), **get_request_client_sample_data(),
api_token = generate(str, {'character_set': uri}), api_token = generate(str, options | {'character_set': uri}),
query = generate(str), query = generate(str, options),
) )

View File

@ -3,8 +3,9 @@ from types import SimpleNamespace
from pytest import fixture from pytest import fixture
from scwrypts.test import generate
from scwrypts.test.character_set import uri from scwrypts.test.character_set import uri
from ..conftest import generate, get_request_client_sample_data from ..conftest import options, get_request_client_sample_data
@fixture(name='sample') @fixture(name='sample')
def fixture_sample(): def fixture_sample():
@ -13,12 +14,12 @@ def fixture_sample():
**get_request_client_sample_data(), **get_request_client_sample_data(),
'base_url': 'https://discord.com/api', 'base_url': 'https://discord.com/api',
}, },
bot_token = generate(str, {'character_set': uri}), bot_token = generate(str, options | {'character_set': uri}),
username = generate(str, {'character_set': ascii_letters + digits}), username = generate(str, options | {'character_set': ascii_letters + digits}),
avatar_url = generate(str, {'character_set': uri}), avatar_url = generate(str, options | {'character_set': uri}),
webhook = generate(str, {'character_set': uri}), webhook = generate(str, options | {'character_set': uri}),
channel_id = generate(str, {'character_set': uri}), channel_id = generate(str, options | {'character_set': uri}),
content_header = generate(str), content_header = generate(str, options),
content_footer = generate(str), content_footer = generate(str, options),
content = generate(str), content = generate(str, options),
) )

View File

@ -3,8 +3,9 @@ from types import SimpleNamespace
from pytest import fixture from pytest import fixture
from scwrypts.test import generate
from scwrypts.test.character_set import uri from scwrypts.test.character_set import uri
from ..conftest import generate, get_request_client_sample_data from ..conftest import options, get_request_client_sample_data
@fixture(name='sample') @fixture(name='sample')
def fixture_sample(): def fixture_sample():
@ -13,6 +14,6 @@ def fixture_sample():
**get_request_client_sample_data(), **get_request_client_sample_data(),
'base_url': 'https://api.linear.app', 'base_url': 'https://api.linear.app',
}, },
api_token = generate(str, {'character_set': uri}), api_token = generate(str, options | {'character_set': uri}),
query = generate(str), query = generate(str, options),
) )

View File

@ -13,7 +13,7 @@ class MissingFlagAndEnvironmentVariableError(EnvironmentError, ArgumentError):
class MissingScwryptsExecutableError(EnvironmentError): class MissingScwryptsExecutableError(EnvironmentError):
def __init__(self): def __init__(self):
super().__init__('scwrypts must be installed and available on your PATH') super().__init__(f'scwrypts must be installed and available on your PATH')
class BadScwryptsLookupError(ValueError): class BadScwryptsLookupError(ValueError):

View File

@ -5,54 +5,44 @@ from subprocess import run
from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError
def scwrypts(patterns=None, args=None, executable_args=None, name=None, group=None, _type=None): def scwrypts(*args, patterns=None, name=None, group=None, _type=None, log_level=None):
''' '''
top-level scwrypts invoker from python top-level scwrypts invoker from python
patterns str / list pattern-based scwrypt lookup - patterns allows for pattern-based scwrypt lookup
args str / list arguments forwarded to the invoked scwrypt - name/group/type allos for precise-match lookup
executable_args str / list arguments for the 'scwrypts' executable
(str above assumes space-delimited values)
name str exact scwrypt lookup name (requires group and _type) *args should be a list of strings and is forwarded to the
group str exact scwrypt lookup group invoked scwrypt
_type str exact scwrypt lookup type
SCWRYPTS_EXECUTABLE configuration variable which defines the full path to scwrypts executable
see 'scwrypts --help' for more information see 'scwrypts --help' for more information
''' '''
if patterns is None and name is None: executable = which('scwrypts')
raise BadScwryptsLookupError()
if name is not None and (group is None or _type is None):
raise MissingScwryptsGroupOrTypeError(group, _type)
executable = which(getenv('SCWRYPTS_EXECUTABLE', 'scwrypts'))
if executable is None: if executable is None:
raise MissingScwryptsExecutableError() raise MissingScwryptsExecutableError()
lookup = _parse(patterns) if name is None else f'--name {name} --group {group} --type {_type}' if patterns is None and name is None:
raise BadScwryptsLookupError()
pre_args = []
if name is None:
pre_args += patterns
else:
pre_args += ['--name', name, '--group', group, '--type', _type]
if group is None or _type is None:
raise MissingScwryptsGroupOrTypeError(group, _type)
if log_level is not None:
pre_args += ['--log-level', log_level]
depth = getenv('SUBSCWRYPT', '') depth = getenv('SUBSCWRYPT', '')
if depth != '': if depth != '':
depth = int(depth) + 1 depth = int(depth) + 1
return run( return run(
f'SUBSCWRYPT={depth} {executable} {_parse(executable_args)} {lookup} -- {_parse(args)}', f'SUBSCWRYPT={depth} {executable} {" ".join(pre_args)} -- {" ".join(args)}',
shell=True, shell=True,
executable='/bin/zsh', executable='/bin/zsh',
check=False, check=False,
capture_output=True,
text=True,
) )
def _parse(string_or_list_args):
if string_or_list_args is None:
return ''
if isinstance(string_or_list_args, list):
return ' '.join(string_or_list_args)
return str(string_or_list_args)

View File

@ -1,184 +0,0 @@
from random import choice
from re import search
from string import ascii_letters, digits
from types import SimpleNamespace
from unittest.mock import patch
from pytest import fixture, raises
from scwrypts.test import get_generator
from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError
from .scwrypts import scwrypts
#####################################################################
def test_scwrypts(sample, _scwrypts):
assert validate_scwrypts_output(sample, _scwrypts)
def test_scwrypts_finds_system_executable(sample, _scwrypts, mock_which):
mock_which.assert_called_once_with(sample.env['SCWRYPTS_EXECUTABLE'])
def test_scwrypts_uses_configured_executable_path(_scwrypts, mock_getenv):
mock_getenv.assert_any_call('SCWRYPTS_EXECUTABLE', 'scwrypts')
def test_scwrypts_uses_correct_depth(_scwrypts, mock_getenv):
mock_getenv.assert_any_call('SUBSCWRYPT', '')
def test_scwrypts_runs_subprocess(_scwrypts, mock_run):
mock_run.assert_called_once()
##########################################
def test_scwrypts_omit_optionals(sample, _scwrypts_omit_optionals):
assert validate_scwrypts_output(sample, _scwrypts_omit_optionals)
def test_scwrypts_omit_optionals_finds_system_executable(sample, _scwrypts_omit_optionals, mock_which):
mock_which.assert_called_once_with('scwrypts')
def test_scwrypts_omit_optionals_uses_configured_executable_path(_scwrypts_omit_optionals, mock_getenv):
mock_getenv.assert_any_call('SCWRYPTS_EXECUTABLE', 'scwrypts')
def test_scwrypts_omit_optionals_uses_correct_depth(_scwrypts_omit_optionals, mock_getenv):
mock_getenv.assert_any_call('SUBSCWRYPT', '')
def test_scwrypts_omit_optionals_runs_subprocess(_scwrypts_omit_optionals, mock_run):
mock_run.assert_called_once()
##########################################
def test_invalid_lookup_missing_patterns_and_name(sample):
sample.patterns = None
sample.name = None
with raises(BadScwryptsLookupError):
scwrypts(**get_scwrypts_args(sample))
def test_invalid_name_lookup_missing_group(sample):
sample.group = None
with raises(MissingScwryptsGroupOrTypeError):
scwrypts(**get_scwrypts_args(sample))
def test_invalid_name_lookup_missing_type(sample):
sample._type = None # pylint: disable=protected-access
with raises(MissingScwryptsGroupOrTypeError):
scwrypts(**get_scwrypts_args(sample))
def test_invalid_scwrypts_installation(sample, mock_which):
mock_which.return_value = None
with raises(MissingScwryptsExecutableError):
scwrypts(**get_scwrypts_args(sample))
#####################################################################
generate = get_generator({
'str_length_minimum': 8,
'str_length_maximum': 128,
'character_set': ascii_letters + digits + '/-_'
})
def _generate_str_or_list_arg():
random_arg = generate(list, {'data_types': {str}})
return random_arg if choice([str, list]) == list else ' '.join(random_arg)
@fixture(name='sample')
def fixture_sample():
sample = SimpleNamespace(
patterns = _generate_str_or_list_arg(),
args = _generate_str_or_list_arg(),
executable_args = _generate_str_or_list_arg(),
name = generate(str),
group = generate(str),
_type = generate(str),
executable = generate(str),
env = {
'SCWRYPTS_EXECUTABLE': generate(str),
'SUBSCWRYPT': str(generate(int, {'minimum': 1, 'maximum': 99})),
},
returncode = generate(int),
stdout = generate(str),
stderr = generate(str),
)
return sample
def get_scwrypts_args(sample):
return {
key: getattr(sample, key)
for key in [
'patterns',
'args',
'executable_args',
'name',
'group',
'_type',
]
}
#####################################################################
@fixture(name='mock_which', autouse=True)
def fixture_mock_which(sample):
with patch('scwrypts.scwrypts.scwrypts.which') as mock:
mock.return_value = sample.executable
yield mock
@fixture(name='mock_getenv', autouse=True)
def fixture_mock_getenv(sample):
with patch('scwrypts.scwrypts.scwrypts.getenv') as mock:
mock.side_effect = sample.env.get
yield mock
@fixture(name='mock_run', autouse=True)
def fixture_mock_run(sample):
with patch('scwrypts.scwrypts.scwrypts.run') as mock:
mock.side_effect = lambda *args, **_kwargs: SimpleNamespace(
args = args,
returncode = sample.returncode,
stdout = sample.stdout,
stderr = sample.stderr,
)
yield mock
#####################################################################
@fixture(name='_scwrypts')
def fixture_scwrypts(sample):
return scwrypts(**get_scwrypts_args(sample))
@fixture(name='_scwrypts_omit_optionals')
def fixture_scwrypts_omit_optionals(sample):
sample.args = None
sample.executable_args = None
del sample.env['SCWRYPTS_EXECUTABLE']
del sample.env['SUBSCWRYPT']
return scwrypts(**get_scwrypts_args(sample))
def validate_scwrypts_output(sample, output):
#
# I would love to use 'assert _scwrypts == SimpleNamespace(...expected...)'
# but the output.args is difficult to recreate without copying all the
# processing logic over from the scwrypts function
#
# opting for a bit of a strange equality test here, checking the args
# as closely as possible without copying parsing logic
#
run_args_reduced_to_a_single_string = len(output.args) == 1
run_args_follow_expected_form = search(
fr'^SUBSCWRYPT=.* {sample.executable} .*-- .*$',
output.args[0],
)
return all([
run_args_reduced_to_a_single_string,
run_args_follow_expected_form,
output.returncode == sample.returncode,
output.stdout == sample.stdout,
output.stderr == sample.stderr,
])

View File

@ -5,6 +5,6 @@ __all__ = [
'generate', 'generate',
] ]
from .generate import generate, get_generator from .generate import generate
from .character_set import * from .character_set import *

View File

@ -45,21 +45,6 @@ DEFAULT_OPTIONS = {
'requests_response_status_code': status_codes.codes[200], 'requests_response_status_code': status_codes.codes[200],
} }
def get_generator(default_options=None):
if default_options is None:
default_options = {}
def generator_function(data_type=None, options_overrides=None):
if options_overrides is None:
options_overrides = {}
return generate(
data_type = data_type,
options = default_options | options_overrides,
)
return generator_function
def generate(data_type=None, options=None): def generate(data_type=None, options=None):
''' '''
generate random data with the call of a function generate random data with the call of a function

169
scwrypts
View File

@ -1,12 +1,16 @@
#!/bin/zsh #!/bin/zsh
export EXECUTION_DIR=$(pwd) export EXECUTION_DIR=$(pwd)
export SCWRYPTS_RUNTIME_ID=$(uuidgen)
source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42 source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
##################################################################### #####################################################################
() { () {
cd "$SCWRYPTS_ROOT__scwrypts" cd "$SCWRYPTS_ROOT__scwrypts"
GIT_SCWRYPTS() { git -C "$SCWRYPTS_ROOT__scwrypts" $@; } GIT_SCWRYPTS() { git -C "$SCWRYPTS_ROOT__scwrypts" $@; }
local INSTALLATION_TYPE
[ ! -d "$SCWRYPTS_ROOT__scwrypts/.git" ] && [ ! -f "$SCWRYPTS_ROOT__scwrypts/.git" ] \
&& INSTALLATION_TYPE=$(cat "$SCWRYPTS_ROOT__scwrypts/MANAGED_BY" 2>/dev/null) \
|| INSTALLATION_TYPE=manual \
;
local ERRORS=0 local ERRORS=0
local USAGE=' local USAGE='
@ -22,26 +26,20 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
runtime runtime
-y, --yes auto-accept all [yn] prompts through current scwrypt -y, --yes auto-accept all [yn] prompts through current scwrypt
-e, --env <env-name> set environment; overwrites SCWRYPTS_ENV -e, --env <env-name> set environment; overwrites SCWRYPTS_ENV
-n shorthand for "--log-level 0"
-n shorthand for "--log-level 0" -v, --log-level [0-4] set incremental scwrypts log level to one of the following:
-v, --log-level <0-4> set incremental scwrypts log level to one of the following: 0 : only command output and critical failures; skips logfile
0 : only command output and critical failures; skips logfile 1 : include success / failure messages
1 : include success / failure messages 2 : include status update messages
2 : include status update messages 3 : (default) include warning messages
3 : (default) include warning messages 4 : include debug messages
4 : include debug messages
-o, --output <format> specify output format; one of: pretty,json (default: pretty)
alternate commands alternate commands
-h, --help display this message and exit -h, --help display this message and exit
-l, --list print out command list and exit -l, --list print out command list and exit
--list-envs print out environment list and exit --list-envs print out environment list and exit
--list-groups print out configured scwrypts groups and exit --update update scwrypts library to latest version
--config "eval"-ed to enable config and "use" import in non-scwrypts environments --version print out scwrypts version and exit
--root print out SCWRYPTS_ROOT__scwrypts and exit
--update update scwrypts library to latest version
--version print out scwrypts version and exit
patterns: patterns:
- a list of glob patterns to loose-match a scwrypt by name - a list of glob patterns to loose-match a scwrypt by name
@ -62,10 +60,8 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=3 [ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=3
local SHIFT_COUNT
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
SHIFT_COUNT=1
case $1 in case $1 in
-[a-z][a-z]* ) -[a-z][a-z]* )
VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/') VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/')
@ -89,44 +85,23 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
return 0 return 0
;; ;;
--list-groups )
echo "${SCWRYPTS_GROUPS[@]}" | sed 's/\s\+/\n/g' | sort -u
return 0
;;
--version ) --version )
case $SCWRYPTS_INSTALLATION_TYPE in case $INSTALLATION_TYPE in
manual ) echo "scwrypts $(GIT_SCWRYPTS describe --tags) (via GIT)" ;; manual ) echo "scwrypts $(GIT_SCWRYPTS describe --tags) (via GIT)" ;;
* ) echo "scwrypts $(cat "$SCWRYPTS_ROOT__scwrypts/VERSION")" ;; * ) echo scwrypts $(cat "$SCWRYPTS_ROOT__scwrypts/VERSION") ;;
esac esac
return 0 return 0
;; ;;
--root )
echo "$SCWRYPTS_ROOT__scwrypts"
return 0
;;
--config )
echo "source '$SCWRYPTS_ROOT__scwrypts/zsh/lib/import.driver.zsh'"
echo "CHECK_ENVIRONMENT --no-fail --no-usage"
echo "unset __SCWRYPT"
return 0
;;
--update ) --update )
case $SCWRYPTS_INSTALLATION_TYPE in case $INSTALLATION_TYPE in
aur ) aur )
SCWRYPTS_LOG_LEVEL=3 REMINDER " SCWRYPTS_LOG_LEVEL=3 REMINDER "
This installation is built from the AUR. Update through 'makepkg' or use This installation is built from the AUR. Update through 'makepkg' or use
your preferred AUR package management tool (e.g. 'yay -Syu scwrypts') your preferred AUR package management tool (e.g. 'yay -Syu scwrypts')
" "
;; ;;
homebrew )
SCWRYPTS_LOG_LEVEL=3 REMINDER "This installation is managed by homebrew. Update me with 'brew update'"
;;
manual ) manual )
GIT_SCWRYPTS fetch --quiet origin main GIT_SCWRYPTS fetch --quiet origin main
GIT_SCWRYPTS fetch --quiet origin main --tags GIT_SCWRYPTS fetch --quiet origin main --tags
@ -150,7 +125,7 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
;; ;;
* ) * )
SCWRYPTS_LOG_LEVEL=3 REMINDER " SCWRYPTS_LOG_LEVEL=3 REMINDER "
This is a managed installation of scwrypts. Please update through your This is a managed installation of scwrypts. Please update through your
system package manager. system package manager.
" "
@ -162,54 +137,46 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
### scwrypts filters ##################### ### scwrypts filters #####################
-m | --name ) -m | --name )
((SHIFT_COUNT+=1))
[ $2 ] || { ERROR "missing value for argument $1"; break; } [ $2 ] || { ERROR "missing value for argument $1"; break; }
SEARCH_NAME=$2 SEARCH_NAME=$2
shift 1
;; ;;
-g | --group ) -g | --group )
((SHIFT_COUNT+=1))
[ $2 ] || { ERROR "missing value for argument $1"; break; } [ $2 ] || { ERROR "missing value for argument $1"; break; }
SEARCH_GROUP=$2 SEARCH_GROUP=$2
GROUP=$2 shift 1
;; ;;
-t | --type ) -t | --type )
((SHIFT_COUNT+=1))
[ $2 ] || { ERROR "missing value for argument $1"; break; } [ $2 ] || { ERROR "missing value for argument $1"; break; }
SEARCH_TYPE=$2 SEARCH_TYPE=$2
TYPE=$2 shift 1
;; ;;
### runtime settings ##################### ### runtime settings #####################
-y | --yes ) export __SCWRYPTS_YES=1 ;; -y | --yes ) export __SCWRYPTS_YES=1 ;;
-n ) SCWRYPTS_LOG_LEVEL=0 ;; -n | --no-log )
SCWRYPTS_LOG_LEVEL=0
-v | --log-level ) [[ $1 =~ ^--no-log$ ]] && WARNING 'the --no-log flag is deprecated and will be removed in scwrypts v4.2'
((SHIFT_COUNT+=1))
[[ $2 =~ ^[0-4]$ ]] || ERROR "invalid setting for log-level '$2'"
SCWRYPTS_LOG_LEVEL=$2
;; ;;
-o | --output ) -v | --log-level )
((SHIFT_COUNT+=1)) [[ $2 =~ ^[0-4]$ ]] || ERROR "invalid setting for log-level '$2'"
export SCWRYPTS_OUTPUT_FORMAT=$2 SCWRYPTS_LOG_LEVEL=$2
case $SCWRYPTS_OUTPUT_FORMAT in shift 1
pretty | json ) ;;
* ) ERROR "unsupported format '$SCWRYPTS_OUTPUT_FORMAT'" ;;
esac
;; ;;
-e | --env ) -e | --env )
((SHIFT_COUNT+=1))
[ $2 ] || { ERROR "missing value for argument $1"; break; } [ $2 ] || { ERROR "missing value for argument $1"; break; }
[ $ENV_NAME ] && DEBUG 'overwriting session environment' [ $ENV_NAME ] && DEBUG 'overwriting session environment'
ENV_NAME="$2" ENV_NAME="$2"
STATUS "using CLI environment '$ENV_NAME'" STATUS "using CLI environment '$ENV_NAME'"
shift 1
;; ;;
########################################## ##########################################
@ -218,11 +185,9 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
--* ) ERROR "unrecognized argument '$1'" ;; --* ) ERROR "unrecognized argument '$1'" ;;
* ) SEARCH_PATTERNS+=($1) ;; * ) SEARCH_PATTERNS+=($1) ;;
esac esac
shift $SHIFT_COUNT shift 1
done done
[ $SCWRYPTS_OUTPUT_FORMAT ] || export SCWRYPTS_OUTPUT_FORMAT=pretty
[ $SEARCH_NAME ] && { [ $SEARCH_NAME ] && {
[ $SEARCH_TYPE ] || ERROR '--name requires --type argument' [ $SEARCH_TYPE ] || ERROR '--name requires --type argument'
[ $SEARCH_GROUP ] || ERROR '--name requires --group argument' [ $SEARCH_GROUP ] || ERROR '--name requires --group argument'
@ -249,6 +214,7 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
echo $SCWRYPTS_AVAILABLE | head -n1 echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | grep ' [^/]*'$SEARCH_TYPE'[^/]* ' echo $SCWRYPTS_AVAILABLE | grep ' [^/]*'$SEARCH_TYPE'[^/]* '
} \ } \
| awk '{$2=""; print $0;}' \
| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g' \ | sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g' \
| column -ts '^' | column -ts '^'
) )
@ -258,8 +224,9 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
SCWRYPTS_AVAILABLE=$( SCWRYPTS_AVAILABLE=$(
{ {
echo $SCWRYPTS_AVAILABLE | head -n1 echo $SCWRYPTS_AVAILABLE | head -n1
echo $SCWRYPTS_AVAILABLE | grep "$SEARCH_GROUP"'[^/ ]*$' echo $SCWRYPTS_AVAILABLE | grep "$SEARCH_GROUP"'[^/]*$'
} \ } \
| awk '{$NF=""; print $0;}' \
| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g' \ | sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g' \
| column -ts '^' | column -ts '^'
) )
@ -327,17 +294,9 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
[[ $ENV_REQUIRED =~ true ]] && { [[ $ENV_REQUIRED =~ true ]] && {
[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV) [ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV)
[ ! $ENV_NAME ] && ABORT
export ENV_NAME
export SCWRYPTS_ENV=$ENV_NAME
for GROUP in ${SCWRYPTS_GROUPS[@]} for GROUP in ${SCWRYPTS_GROUPS[@]}
do do
local REQUIRED_REGEX=$(eval echo '$SCWRYPTS_REQUIRED_ENVIRONMENT_REGEX__'$GROUP)
[ $REQUIRED_REGEX ] && {
[[ $ENV_NAME =~ $REQUIRED_REGEX ]] || continue
}
local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME" "$GROUP") local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME" "$GROUP")
source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$GROUP/$ENV_NAME'" source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$GROUP/$ENV_NAME'"
@ -346,6 +305,8 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
source "$f" || FAIL 5 "invalid static config '$f'" source "$f" || FAIL 5 "invalid static config '$f'"
done done
done done
export ENV_NAME
} }
[ $REQUIRED_ENVIRONMENT_REGEX ] && { [ $REQUIRED_ENVIRONMENT_REGEX ] && {
@ -353,12 +314,11 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment name to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)" || FAIL 5 "group '$SCWRYPT_GROUP' requires current environment name to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)"
} }
########################################## ##########################################
[ ! $SUBSCWRYPT ] && export SUBSCWRYPT=0 [ ! $SUBSCWRYPT ] && export SUBSCWRYPT=0
[[ $SCWRYPTS_INSTALLATION_TYPE =~ ^manual$ ]] && { [[ $INSTALLATION_TYPE =~ ^manual$ ]] && {
[[ $SUBSCWRYPT -eq 0 ]] && [[ $ENV_NAME =~ prod ]] && [[ $SCWRYPTS_LOG_LEVEL -gt 0 ]] && { [[ $SUBSCWRYPT -eq 0 ]] && [[ $ENV_NAME =~ prod ]] && [[ $SCWRYPTS_LOG_LEVEL -gt 0 ]] && {
STATUS "on '$ENV_NAME'; checking diff against origin/main" STATUS "on '$ENV_NAME'; checking diff against origin/main"
@ -412,42 +372,25 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
[[ $SCWRYPT_NAME =~ interactive ]] && RUN_MODE=interactive [[ $SCWRYPT_NAME =~ interactive ]] && RUN_MODE=interactive
local HEADER FOOTER local HEADER FOOTER
[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && {
case $SCWRYPTS_OUTPUT_FORMAT in
pretty )
HEADER=$(
echo "
=====================================================================
scwrypt : $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME
run at : $(date)
config : $ENV_NAME
log level : $SCWRYPTS_LOG_LEVEL
\\033[1;33m--- SCWRYPT BEGIN ---------------------------------------------------\\033[0m
" | sed 's/^\s\+//; 1d'
)
FOOTER="\\033[1;33m--- SCWRYPT END ---------------------------------------------------\\033[0m" [[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && {
;; HEADER=$(
json ) echo "
HEADER=$(echo '{}' | jq -c ". =====================================================================
| .timestamp = \"$(date +%s)\" script : $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME
| .runtime = \"$SCWRYPTS_RUNTIME_ID\" run at : $(date)
| .scwrypt = \"start of $SCWRYPT_NAME $SCWRYPT_GROUP $SCWRYPT_TYPE\" config : $ENV_NAME
| .config = \"$ENV_NAME\" log level : $SCWRYPTS_LOG_LEVEL
| .logLevel = \"$SCWRYPTS_LOG_LEVEL\" \\033[1;33m--- SCWRYPT BEGIN ---------------------------------------------------\\033[0m
| .subscwrypt = $SUBSCWRYPT " | sed 's/^\s\+//; 1d'
") )
;;
esac FOOTER="\\033[1;33m--- SCWRYPT END ---------------------------------------------------\\033[0m"
} }
[[ $SUBSCWRYPT -eq 0 ]] || { [[ $SUBSCWRYPT -eq 0 ]] || {
case $SCWRYPTS_OUTPUT_FORMAT in HEADER="\\033[0;33m--- ($SUBSCWRYPT) BEGIN $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---"
pretty ) FOOTER="\\033[0;33m--- ($SUBSCWRYPT) END $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---"
HEADER="\\033[0;33m--- ($SUBSCWRYPT) BEGIN $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---"
FOOTER="\\033[0;33m--- ($SUBSCWRYPT) END $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---"
;;
esac
} }
##################################################################### #####################################################################
@ -478,5 +421,5 @@ source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42
&& echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m" && echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m"
return $EXIT_CODE return $EXIT_CODE
} | tee --append "$LOGFILE" } 2>&1 | tee --append "$LOGFILE"
} $@ } $@

View File

@ -1,223 +1,80 @@
# #####################################################################
# typically you do not need to reload this plugin in a single session;
# if for some reason you do, you can run the following command and command -v scwrypts &>/dev/null || {
# source this file again echo 'scwrypts is required in your PATH in order to use the zsh plugins; skipping' >&2
# return 0
# unset __SCWRYPTS_PLUGIN_LOADED }
#
[[ $__SCWRYPTS_PLUGIN_LOADED =~ true ]] && return 0 NO_EXPORT_CONFIG=1 source "${0:a:h}/zsh/lib/import.driver.zsh" || return 42
##################################################################### #####################################################################
: \ SCWRYPTS__ZSH_PLUGIN() {
&& command -v scwrypts &>/dev/null \ local SCWRYPT_SELECTION=$(scwrypts --list | FZF 'select a script' --header-lines 1)
&& eval "$(scwrypts --config)" \ local NAME
|| { local TYPE
echo 'scwrypts must be in PATH and properly configured; skipping zsh plugin setup' >&2 local GROUP
LBUFFER= RBUFFER=
[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; }
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
which scwrypts >/dev/null 2>&1\
&& RBUFFER="scwrypts" || RBUFFER="$SCWRYPTS_ROOT/scwrypts"
RBUFFER+=" --name $NAME --group $GROUP --type $TYPE"
zle accept-line
}
zle -N scwrypts SCWRYPTS__ZSH_PLUGIN
bindkey $SCWRYPTS_SHORTCUT scwrypts
#####################################################################
SCWRYPTS__ZSH_BUILDER_PLUGIN() {
local SCWRYPT_SELECTION=$(scwrypts --list | FZF 'select a script' --header-lines 1)
echo $SCWRYPT_SELECTION >&2
local NAME
local TYPE
local GROUP
LBUFFER= RBUFFER=
[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; }
SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION
scwrypts -n --name $NAME --group $GROUP --type $TYPE -- --help >&2 || {
zle accept-line
return 0 return 0
} }
echo
__SCWRYPTS_PARSE() { zle reset-prompt
SCWRYPT_SELECTION=$(scwrypts --list | fzf --ansi --prompt 'select a script : ' --header-lines 1) which scwrypts >/dev/null 2>&1\
LBUFFER= RBUFFER= && LBUFFER="scwrypts" || LBUFFER="$SCWRYPTS_ROOT/scwrypts"
[ $SCWRYPT_SELECTION ] || return 1
NAME=$(echo "$SCWRYPT_SELECTION" | awk '{print $1;}') LBUFFER+=" --name $NAME --group $GROUP --type $TYPE -- "
TYPE=$(echo "$SCWRYPT_SELECTION" | awk '{print $2;}')
GROUP=$(echo "$SCWRYPT_SELECTION" | awk '{print $3;}')
[ $NAME ] && [ $TYPE ] && [ $GROUP ]
} }
zle -N scwrypts-builder SCWRYPTS__ZSH_BUILDER_PLUGIN
bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder
##################################################################### #####################################################################
[ $SCWRYPTS_SHORTCUT ] && { SCWRYPTS__ZSH_PLUGIN_ENV() {
SCWRYPTS__ZSH_PLUGIN() { local RESET='reset'
local SCWRYPT_SELECTION NAME TYPE GROUP local SELECTED=$(\
__SCWRYPTS_PARSE || { zle accept-line; return 0; } { [ $SCWRYPTS_ENV ] && echo $RESET; SCWRYPTS__GET_ENV_NAMES; } \
| FZF 'select an environment' \
)
RBUFFER="scwrypts --name $NAME --type $TYPE --group $GROUP" zle clear-command-line
zle accept-line [ $SELECTED ] && {
[[ $SELECTED =~ ^$RESET$ ]] \
&& RBUFFER='unset SCWRYPTS_ENV' \
|| RBUFFER="export SCWRYPTS_ENV=$SELECTED"
} }
zle accept-line
zle -N scwrypts SCWRYPTS__ZSH_PLUGIN
bindkey $SCWRYPTS_SHORTCUT scwrypts
unset SCWRYPTS_SHORTCUT
} }
##################################################################### zle -N scwrypts-setenv SCWRYPTS__ZSH_PLUGIN_ENV
bindkey $SCWRYPTS_ENV_SHORTCUT scwrypts-setenv
[ $SCWRYPTS_BUILDER_SHORTCUT ] && {
SCWRYPTS__ZSH_BUILDER_PLUGIN() {
local SCWRYPT_SELECTION NAME TYPE GROUP
__SCWRYPTS_PARSE || { echo >&2; zle accept-line; return 0; }
echo $SCWRYPT_SELECTION >&2
scwrypts -n --name $NAME --group $GROUP --type $TYPE -- --help >&2 || {
zle accept-line
return 0
}
echo
zle reset-prompt
LBUFFER="scwrypts --name $NAME --type $TYPE --group $GROUP -- "
}
zle -N scwrypts-builder SCWRYPTS__ZSH_BUILDER_PLUGIN
bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder
unset SCWRYPTS_BUILDER_SHORTCUT
}
#####################################################################
[ $SCWRYPTS_ENV_SHORTCUT ] && {
SCWRYPTS__ZSH_PLUGIN_ENV() {
local RESET='reset'
local SELECTED=$(\
{ [ $SCWRYPTS_ENV ] && echo $RESET; scwrypts --list-envs; } \
| fzf --prompt 'select an environment : ' \
)
zle clear-command-line
[ $SELECTED ] && {
[[ $SELECTED =~ ^$RESET$ ]] \
&& RBUFFER='unset SCWRYPTS_ENV' \
|| RBUFFER="export SCWRYPTS_ENV=$SELECTED"
}
zle accept-line
}
zle -N scwrypts-setenv SCWRYPTS__ZSH_PLUGIN_ENV
bindkey $SCWRYPTS_ENV_SHORTCUT scwrypts-setenv
unset SCWRYPTS_ENV_SHORTCUT
}
#####################################################################
# badass(/terrifying?) zsh autocompletion
command -v compdef &>/dev/null && {
_scwrypts() {
echo $words | grep -q "\s--\s" && _arguments && return 0
eval "_arguments $(
{
HELP=$(scwrypts --help 2>&1 | sed -n 's/^\s\+\(-.* .\)/\1/p' | sed 's/[[]/(/g; s/[]]/)/g')
echo $HELP \
| sed 's/^\(\(-[^-\s]\),*\s*\|\)\(\(--[-a-z0-9A-Z\]*\)\s\(<\([^>]*\)>\|\)\|\)\s\+\(.*\)/\2[\7]:\6:->\2/' \
| grep -v '^[[]' \
;
echo $HELP \
| sed 's/^\(\(-[^-\s]\),*\s*\|\)\(\(--[-a-z0-9A-Z\]*\)\s\(<\([^>]*\)>\|\)\|\)\s\+\(.*\)/\4[\7]:\6:->\4/' \
| grep -v '^[[]' \
;
echo ":pattern:->pattern"
echo ":pattern:->pattern"
echo ":pattern:->pattern"
echo ":pattern:->pattern"
echo ":pattern:->pattern"
} | sed 's/::->.*$//g' | sed "s/\\(^\\|$\\)/'/g" | tr '\n' ' '
)"
local _group=''
echo $words | grep -q ' -g [^\s]' \
&& _group=$(echo $words | sed 's/.*-g \([^ ]\+\)\s*.*/\1/')
echo $words | grep -q ' --group .' \
&& _group=$(echo $words | sed 's/.*--group \([^ ]\+\)\s*.*/\1/')
local _type=''
echo $words | grep -q ' -t [^\s]' \
&& _type=$(echo $words | sed 's/.*-t \([^ ]\+\)\s*.*/\1/')
echo $words | grep -q ' --type .' \
&& _type=$(echo $words | sed 's/.*--type \([^ ]\+\)\s*.*/\1/')
local _name=''
echo $words | grep -q ' -m [^\s]' \
&& _name=$(echo $words | sed 's/.*-m \([^ ]\+\)\s*.*/\1/')
echo $words | grep -q ' --name .' \
&& _name=$(echo $words | sed 's/.*--name \([^ ]\+\)\s*.*/\1/')
local _pattern _patterns=()
[ ! $_name ] \
&& _patterns=($(echo "${words[@]:1}" | sed 's/\s\+/\n/g' | grep -v '^-'))
_get_remaining_scwrypts() {
[ $_name ] || local _name='[^ ]\+'
[ $_type ] || local _type='[^ ]\+'
[ $_group ] || local _group='[^ ]\+'
local remaining=$(\
scwrypts --list \
| sed "1d; s,\x1B\[[0-9;]*[a-zA-Z],,g" \
| grep "^$_name\s" \
| grep "\s$_group$" \
| grep "\s$_type\s" \
)
for _pattern in ${_patterns[@]}
do
remaining=$(echo "$remaining" | grep "$_pattern")
done
echo "$remaining"
}
case $state in
( -m | --name )
compadd $(_get_remaining_scwrypts | awk '{print $1;}' | sort -u)
;;
( -t | --type )
compadd $(_get_remaining_scwrypts | awk '{print $2;}' | sort -u)
;;
( -g | --group )
[[ $_name$_type$_group =~ ^$ ]] \
&& compadd $(scwrypts --list-groups) \
|| compadd $(_get_remaining_scwrypts | awk '{print $3;}' | sort -u) \
;;
( -e | --env )
compadd $(scwrypts --list-envs)
;;
( -v | --log-level )
local _help="$(\
scwrypts --help 2>&1 \
| sed -n '/-v, --log-level/,/^$/p' \
| sed -n 's/\s\+\([0-9]\) : \(.*\)/\1 -- \2/p' \
)"
eval "local _descriptions=($(echo "$_help" | sed "s/\\(^\|$\\)/'/g"))"
local _values=($(echo "$_help" | sed 's/ --.*//'))
compadd -d _descriptions -a _values
;;
( -o | --output )
compadd pretty json
;;
( pattern )
[[ $_name =~ ^$ ]] && {
local _remaining_scwrypts="$(_get_remaining_scwrypts)"
# stop providing suggestions if your pattern is sufficient
[[ $(echo $_remaining_scwrypts | wc -l) -le 1 ]] && return 0
local _remaining_patterns="$(echo "$_remaining_scwrypts" | sed 's/\s\+/\n/g; s|/|\n|g;' | sort -u)"
for _pattern in ${_patterns[@]}
do
_remaining_patterns="$(echo "$_remaining_patterns" | grep -v "^$_pattern$")"
done
compadd $(echo $_remaining_patterns)
}
;;
( * ) ;;
esac
}
compdef _scwrypts scwrypts
}
__SCWRYPTS_PLUGIN_LOADED=true

View File

@ -1,11 +0,0 @@
SCWRYPTS_GROUPS+=(scwrypts)
export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT"
export SCWRYPTS_COLOR__scwrypts='\033[0;32m'
#export SCWRYPTS_TYPE__scwrypts=
#export SCWRYPTS_LIBRARY_ROOT__scwrypts=
export SCWRYPTS_VIRTUALENV_PATH__scwrypts="$SCWRYPTS_DATA_PATH/virtualenv"
export SCWRYPTS_PREFERRED_PYTHON_VERSIONS__scwrypts=(3.12 3.11 3.10)
export SCWRYPTS_NODE_VERSION__scwrypts=18.0.0

10
zsh/lib/config.group.zsh Normal file
View File

@ -0,0 +1,10 @@
export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT"
export SCWRYPTS_LIBRARY_ROOT__scwrypts="$SCWRYPTS_ROOT/zsh/lib"
export SCWRYPTS_COLOR__scwrypts='\033[0;32m'
export SCWRYPTS_VIRTUALENV_PATH__scwrypts="$SCWRYPTS_DATA_PATH/virtualenv"
[ ! -d "$SCWRYPTS_VIRTUALENV_PATH__scwrypts" ] && mkdir -p "$SCWRYPTS_VIRTUALENV_PATH__scwrypts"
export SCWRYPTS_PREFERRED_PYTHON_VERSIONS__scwrypts=(3.11 3.10 3.9)
export SCWRYPTS_NODE_VERSION__scwrypts=18.0.0

View File

@ -1,31 +1,17 @@
[[ $__SCWRYPT -eq 1 ]] && return 0 [[ $__SCWRYPT -eq 1 ]] && return 0
##################################################################### #####################################################################
# Apparently MacOS puts ALL of the homebrew stuff inside of a top level git repository [ ! $SCWRYPTS_ROOT ] \
# with bizarre git ignores; so: && SCWRYPTS_ROOT="$(cd $(dirname "${0:a:h}"); git rev-parse --show-toplevel 2>/dev/null)"
# - USE the git root if it's a manual install...
# - UNLESS that git root is just the $(brew --prefix)
SCWRYPTS_ROOT="$(cd -- ${0:a:h}; git rev-parse --show-toplevel 2>/dev/null | grep -v "^$(brew --prefix 2>/dev/null)$")"
[ $SCWRYPTS_ROOT ] && [ -d "$SCWRYPTS_ROOT" ] \ [ ! $SCWRYPTS_ROOT ] && [ -d /usr/share/scwrypts ] \
|| SCWRYPTS_ROOT="$(echo "${0:a:h}" | sed -n 's|\(share/scwrypts\).*$|\1|p')" && SCWRYPTS_ROOT=/usr/share/scwrypts
[ $SCWRYPTS_ROOT ] && [ -d "$SCWRYPTS_ROOT" ] || {
echo "cannot determine scwrypts root path for current installation; aborting"
exit 1
}
export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT" export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT"
[ -f "$SCWRYPTS_ROOT__scwrypts/MANAGED_BY" ] \
&& export SCWRYPTS_INSTALLATION_TYPE=$(cat "$SCWRYPTS_ROOT__scwrypts/MANAGED_BY") \
|| export SCWRYPTS_INSTALLATION_TYPE=manual \
;
##################################################################### #####################################################################
DEFAULT_CONFIG="$SCWRYPTS_ROOT__scwrypts/zsh/lib/config.user.zsh" DEFAULT_CONFIG="$SCWRYPTS_ROOT/zsh/lib/config.user.zsh"
source "$DEFAULT_CONFIG" source "$DEFAULT_CONFIG"
USER_CONFIG_OVERRIDES="$SCWRYPTS_CONFIG_PATH/config.zsh" USER_CONFIG_OVERRIDES="$SCWRYPTS_CONFIG_PATH/config.zsh"
@ -35,13 +21,11 @@ USER_CONFIG_OVERRIDES="$SCWRYPTS_CONFIG_PATH/config.zsh"
} }
source "$USER_CONFIG_OVERRIDES" source "$USER_CONFIG_OVERRIDES"
mkdir -p \ [ ! -d $SCWRYPTS_CONFIG_PATH ] && mkdir -p $SCWRYPTS_CONFIG_PATH
"$SCWRYPTS_CONFIG_PATH" \ [ ! -d $SCWRYPTS_DATA_PATH ] && mkdir -p $SCWRYPTS_DATA_PATH
"$SCWRYPTS_DATA_PATH" \ [ ! -d $SCWRYPTS_ENV_PATH ] && mkdir -p $SCWRYPTS_ENV_PATH
"$SCWRYPTS_ENV_PATH" \ [ ! -d $SCWRYPTS_LOG_PATH ] && mkdir -p $SCWRYPTS_LOG_PATH
"$SCWRYPTS_LOG_PATH" \ [ ! -d $SCWRYPTS_OUTPUT_PATH ] && mkdir -p $SCWRYPTS_OUTPUT_PATH
"$SCWRYPTS_OUTPUT_PATH" \
;
export \ export \
SCWRYPTS_GROUPS \ SCWRYPTS_GROUPS \
@ -53,9 +37,10 @@ export \
SCWRYPTS_OUTPUT_PATH \ SCWRYPTS_OUTPUT_PATH \
; ;
source "$SCWRYPTS_ROOT/scwrypts.scwrypts.zsh" \ SCWRYPTS_GROUPS=(scwrypts $(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u))
|| FAIL 69 'failed to set up scwrypts group; aborting'
source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \
|| FAIL 69 'failed to set up scwrypts group; aborting'
##################################################################### #####################################################################
@ -77,8 +62,7 @@ done
&& [ ! "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] \ && [ ! "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] \
&& [ $GITHUB_WORKSPACE ] \ && [ $GITHUB_WORKSPACE ] \
&& [ ! $SCWRYPTS_GITHUB_NO_AUTOLOAD ] \ && [ ! $SCWRYPTS_GITHUB_NO_AUTOLOAD ] \
&& SCWRYPTS_AUTODETECT_GROUP_BASEDIR="$GITHUB_WORKSPACE" \ && SCWRYPTS_AUTODETECT_GROUP_BASEDIR="$GITHUB_WORKSPACE"
;
[ "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && [ -d "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && { [ "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && [ -d "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] && {
for GROUP_LOADER in $(find "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" -type f -name \*scwrypts.zsh) for GROUP_LOADER in $(find "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" -type f -name \*scwrypts.zsh)
@ -88,8 +72,5 @@ done
} }
##################################################################### #####################################################################
[ $NO_EXPORT_CONFIG ] || __SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt
SCWRYPTS_GROUPS=(scwrypts $(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u | grep -v '^scwrypts$')) true
#####################################################################
__SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt

View File

@ -34,7 +34,7 @@ source "${0:a:h}/config.zsh"
use() { use() {
local SCWRYPTS_LIBRARY SCWRYPTS_LIBRARY_ROOT SCWRYPTS_LIBRARY_GROUP local SCWRYPTS_LIBRARY SCWRYPTS_LIBRARY_ROOT SCWRYPTS_LIBRARY_GROUP
local DEFER_ENVIRONMENT_CHECK=true local DEFER_ENVIRONMENT_CHECK=1
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
@ -49,8 +49,8 @@ use() {
SCWRYPTS_LIBRARY_ROOT=$2 SCWRYPTS_LIBRARY_ROOT=$2
shift 1 shift 1
;; ;;
-c | --check-environment ) --check-environment )
DEFER_ENVIRONMENT_CHECK=false DEFER_ENVIRONMENT_CHECK=0
;; ;;
* ) * )
[ ! $SCWRYPTS_LIBRARY ] \ [ ! $SCWRYPTS_LIBRARY ] \
@ -106,7 +106,7 @@ use() {
return 1 return 1
} }
[[ $DEFER_ENVIRONMENT_CHECK =~ false ]] && { [[ $DEFER_ENVIRONMENT_CHECK -eq 0 ]] && {
CHECK_ENVIRONMENT || { CHECK_ENVIRONMENT || {
((IMPORT_ERRORS+=1)) ((IMPORT_ERRORS+=1))
ERROR "import error for '$SCWRYPTS_LIBRARY_GROUP/$SCWRYPTS_LIBRARY'" ERROR "import error for '$SCWRYPTS_LIBRARY_GROUP/$SCWRYPTS_LIBRARY'"

View File

@ -12,10 +12,7 @@ SCWRYPTS__RUN() { # context wrapper to run scwrypts within scwrypts
local EXIT_CODE=0 local EXIT_CODE=0
((SUBSCWRYPT+=1)) ((SUBSCWRYPT+=1))
SCWRYPTS_LOG_LEVEL=$SCWRYPTS_LOG_LEVEL \ SUBSCWRYPT=$SUBSCWRYPT $SCWRYPTS_ROOT/scwrypts $@
SUBSCWRYPT=$SUBSCWRYPT \
$SCWRYPTS_ROOT__scwrypts/scwrypts $@
EXIT_CODE=$? EXIT_CODE=$?
((SUBSCWRYPT-=1)) ((SUBSCWRYPT-=1))

View File

@ -12,7 +12,7 @@ SCWRYPTS__GET_AVAILABLE_SCWRYPTS() {
local GROUP GROUP_PATH GROUP_COLOR LOOKUP_PIDS=() local GROUP GROUP_PATH GROUP_COLOR LOOKUP_PIDS=()
{ {
echo 'NAME^TYPE^GROUP' echo 'NAME^TYPE^GROUP'
for GROUP in ${SCWRYPTS_GROUPS[@]} for GROUP in ${SCWRYPTS_GROUPS}
do do
GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP) GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP)
GROUP_COLOR=$(eval echo '$SCWRYPTS_COLOR__'$GROUP) GROUP_COLOR=$(eval echo '$SCWRYPTS_COLOR__'$GROUP)
@ -94,7 +94,7 @@ SCWRYPTS__GET_RUNSTRING() {
} }
RUNSTRING="SCWRYPTS_ENV=$ENV_NAME; $RUNSTRING" RUNSTRING="SCWRYPTS_ENV=$ENV_NAME; $RUNSTRING"
RUNSTRING="source $SCWRYPTS_ROOT__scwrypts/zsh/lib/import.driver.zsh; $RUNSTRING" RUNSTRING="source $SCWRYPTS_ROOT/zsh/lib/import.driver.zsh; $RUNSTRING"
local _VIRTUALENV=$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$SCWRYPT_GROUP'/$SCWRYPT_TYPE/bin/activate') local _VIRTUALENV=$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$SCWRYPT_GROUP'/$SCWRYPT_TYPE/bin/activate')
[ -f $_VIRTUALENV ] && RUNSTRING="source $_VIRTUALENV; $RUNSTRING" [ -f $_VIRTUALENV ] && RUNSTRING="source $_VIRTUALENV; $RUNSTRING"

View File

@ -74,8 +74,6 @@ _VIRTUALENV__GET_PATH() {
local ENV_PATH="$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP 2>/dev/null)" local ENV_PATH="$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP 2>/dev/null)"
[ ! $ENV_PATH ] && ENV_PATH="$SCWRYPTS_VIRTUALENV_PATH__scwrypts" [ ! $ENV_PATH ] && ENV_PATH="$SCWRYPTS_VIRTUALENV_PATH__scwrypts"
mkdir -p "$ENV_PATH/$TYPE" &>/dev/null
echo $ENV_PATH/$TYPE echo $ENV_PATH/$TYPE
} }
@ -97,7 +95,7 @@ CREATE_VIRTUALENV__scwrypts__py() {
} }
done done
[ ! $PYTHON ] && { [ ! $PYTHON ] && {
ERROR 'python>=3.10 not available; skipping python env' ERROR 'python>=3.9 not available; skipping python env'
return 1 return 1
} }
@ -124,7 +122,7 @@ UPDATE_VIRTUALENV__scwrypts__py() {
PIP_INSTALL_ARGS+=(--no-cache-dir) PIP_INSTALL_ARGS+=(--no-cache-dir)
PIP_INSTALL_ARGS+=(-r requirements.txt) PIP_INSTALL_ARGS+=(-r requirements.txt)
cd "$SCWRYPTS_ROOT__scwrypts/py" cd "$SCWRYPTS_ROOT/py"
pip install ${PIP_INSTALL_ARGS[@]} pip install ${PIP_INSTALL_ARGS[@]}
} }
@ -161,9 +159,7 @@ ACTIVATE_VIRTUALENV__scwrypts__zx() {
UPDATE_VIRTUALENV__scwrypts__zx() { UPDATE_VIRTUALENV__scwrypts__zx() {
local NPM_INSTALL_ARGS=() local NPM_INSTALL_ARGS=()
[ $CI ] && NPM_INSTALL_ARGS+=(--ignore-scripts) cd "$SCWRYPTS_ROOT/zx"
cd "$SCWRYPTS_ROOT__scwrypts/zx"
npm install ${NPM_INSTALL_ARGS[@]} npm install ${NPM_INSTALL_ARGS[@]}
} }

View File

@ -1,8 +1,5 @@
FZF() { FZF() {
[ $CI ] && { [ $CI ] && FAIL 1 'currently in CI, but FZF requires user input'
DEBUG "invoked FZF with $@"
FAIL 1 'currently in CI, but FZF requires user input'
}
local FZF_ARGS=() local FZF_ARGS=()

View File

@ -5,61 +5,34 @@ PRINT() {
local STDOUT=0 local STDOUT=0
local LTRIM=1 local LTRIM=1
local FORMAT=$SCWRYPTS_OUTPUT_FORMAT
local _S
while [[ $# -gt 0 ]] while [[ $# -gt 0 ]]
do do
_S=1
case $1 in case $1 in
-n | --no-trim-tabs ) LTRIM=0 ;; -n | --no-trim-tabs ) LTRIM=0 ;;
-x | --no-line-end ) LAST_LINE_END='' ;; -x | --no-line-end ) LAST_LINE_END='' ;;
-o | --use-stdout ) STDOUT=1; STDERR=0 ;; -o | --use-stdout ) STDOUT=1; STDERR=0 ;;
-f | --format ) ((_S+=1)); FORMAT=$2 ;;
* ) MESSAGE+="$(echo $1) " ;; * ) MESSAGE+="$(echo $1) " ;;
esac esac
shift $_S shift 1
done done
[ $FORMAT ] || FORMAT=pretty MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')"
local STYLED_MESSAGE
case $FORMAT in
pretty )
STYLED_MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')"
STYLED_MESSAGE="$({
printf "${COLOR}"
while IFS='' read line
do
[[ $PREFIX =~ ^[[:space:]]\+$ ]] && printf '\n'
printf "${PREFIX} : $(echo "$line" | sed 's/^ \+//; s/ \+$//')" local STYLED_MESSAGE="$({
printf "${COLOR}"
while IFS='' read line
do
[[ $PREFIX =~ ^[[:space:]]\+$ ]] && printf '\n'
PREFIX=$(echo $PREFIX | sed 's/./ /g') printf "${PREFIX} : $(echo "$line" | sed 's/^ \+//; s/ \+$//')"
done <<< $MESSAGE
})"
STYLED_MESSAGE="${COLOR}$(echo "$STYLED_MESSAGE" | sed 's/%/%%/g')${__COLOR_RESET}${LAST_LINE_END}"
;;
json )
STYLED_MESSAGE="$(
echo '{}' | jq -c ".
| .timestamp = \"$(date +%s)\"
| .runtime = \"$SCWRYPTS_RUNTIME_ID\"
| .status = \"$(echo "$PREFIX" | sed 's/ .*//')\"
| .message = $(echo $MESSAGE | sed 's/^\t\+//' | jq -Rs)
" | sed 's/\\/\\\\/g'
)\n"
;;
* )
echo "ERROR : unsupported format '$FORMAT'" >&2
return 1
;;
esac
PREFIX=$(echo $PREFIX | sed 's/./ /g')
done <<< $MESSAGE
})"
STYLED_MESSAGE="${COLOR}$(echo "$STYLED_MESSAGE" | sed 's/%/%%/g')${__COLOR_RESET}${LAST_LINE_END}"
[[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2
[[ $STDERR -eq 1 ]] && printf -- "$STYLED_MESSAGE" >&2 [[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE
[[ $STDOUT -eq 1 ]] && printf -- "$STYLED_MESSAGE"
return 0 return 0
} }

View File

@ -72,7 +72,7 @@ CHECK_ENVIRONMENT() {
$E "environment errors found (see above)\n$ERROR_MESSAGE" $E "environment errors found (see above)\n$ERROR_MESSAGE"
} }
[[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && [[ $__SCWRYPT ]] && { [[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && {
REMINDER " REMINDER "
to quickly update missing environment variables, run: to quickly update missing environment variables, run:
'scwrypts zsh/scwrypts/environment/edit' 'scwrypts zsh/scwrypts/environment/edit'