Compare commits
	
		
			3 Commits
		
	
	
		
			main
			...
			v4-develop
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6081122e88 | |||
| db18183c94 | |||
| fec8c5e560 | 
| @@ -4,14 +4,7 @@ version: 2.1 | ||||
| orbs: | ||||
|   python: circleci/python@2.1.1 | ||||
|  | ||||
|  | ||||
| executors: | ||||
|   archlinux: | ||||
|     docker: | ||||
|       - image: archlinux:base-devel | ||||
|     resource_class: small | ||||
|     working_directory: / | ||||
|  | ||||
|   python: | ||||
|     docker: | ||||
|       - image: cimg/python:3.11 | ||||
| @@ -23,134 +16,29 @@ executors: | ||||
|     resource_class: medium | ||||
|  | ||||
|  | ||||
| commands: | ||||
|   archlinux-run: | ||||
|     description: execute command steps in the archlinux container from the CI user | ||||
|     parameters: | ||||
|       _name: | ||||
|         type: string | ||||
|       command: | ||||
|         type: string | ||||
|       working_directory: | ||||
|         type: string | ||||
|         default: /home/ci | ||||
|     steps: | ||||
|       - run: | ||||
|           name: << parameters._name >> | ||||
|           working_directory: << parameters.working_directory >> | ||||
|           command: su ci -c '<< parameters.command >>' | ||||
|  | ||||
|  | ||||
| custom: | ||||
|   archlinux: | ||||
|     prepare: | ||||
|       - &archlinux-prepare | ||||
|         run: | ||||
|           name: prepare archlinux dependencies | ||||
|           command: | | ||||
|             pacman --noconfirm -Syu git openssh ca-certificates-utils | ||||
|             useradd -m ci | ||||
|             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: | ||||
|       - &archlinux-clone-aur | ||||
|         archlinux-run: | ||||
|           _name: clone aur/scwrypts | ||||
|           command: git clone https://aur.archlinux.org/scwrypts.git aur | ||||
|  | ||||
|     clone-scwrypts: | ||||
|       - &archlinux-clone-scwrypts | ||||
|         run: | ||||
|           name: clone wrynegade/scwrypts | ||||
|           working_directory: /home/ci | ||||
|           command: | | ||||
|             GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git clone -b "$(echo $CIRCLE_BRANCH | grep . || echo $CIRCLE_TAG)" "$CIRCLE_REPOSITORY_URL" scwrypts | ||||
|             chown -R ci:ci  ./scwrypts | ||||
|  | ||||
|  | ||||
| jobs: | ||||
|   require-full-semver: | ||||
|   python-test: | ||||
|     executor: python | ||||
|     working_directory: ~/scwrypts/py/lib | ||||
|     steps: | ||||
|       - checkout: | ||||
|           path: ~/scwrypts | ||||
|       - run: | ||||
|           name: check CIRCLE_TAG for full semantic version | ||||
|           name: pytest | ||||
|           command: | | ||||
|             : \ | ||||
|                 && [ $CIRCLE_TAG ] \ | ||||
|                 && [[ $CIRCLE_TAG =~ ^v[0-9]*.[0-9]*.[0-9]*$ ]] \ | ||||
|                 ; | ||||
|               && pip install . .[test] \ | ||||
|               && pytest \ | ||||
|               ; | ||||
|  | ||||
|   aur-test: | ||||
|     executor: archlinux | ||||
|   python-publish: | ||||
|     executor: python | ||||
|     working_directory: ~/scwrypts/py/lib | ||||
|     steps: | ||||
|       - *archlinux-prepare | ||||
|       - *archlinux-temp-downgrade-fakeroot | ||||
|       - *archlinux-clone-aur | ||||
|       - *archlinux-clone-scwrypts | ||||
|       - archlinux-run: | ||||
|           _name: test aur build on current source | ||||
|           working_directory: /home/ci/aur | ||||
|           command: >- | ||||
|             : | ||||
|             && PKGVER=$(sed -n "s/^pkgver=//p" ./PKGBUILD) | ||||
|             && cp -r ../scwrypts ../scwrypts-$PKGVER | ||||
|             && rm -rf ../scwrypts-$PKGVER/.circleci | ||||
|             && rm -rf ../scwrypts-$PKGVER/.git | ||||
|             && rm -rf ../scwrypts-$PKGVER/.gitattributes | ||||
|             && rm -rf ../scwrypts-$PKGVER/.gitignore | ||||
|             && rm -rf ../scwrypts-$PKGVER/.github | ||||
|             && tar -czf scwrypts.tar.gz ../scwrypts-$PKGVER | ||||
|             && echo "source=(scwrypts.tar.gz)" >> PKGBUILD | ||||
|             && echo "sha256sums=(SKIP)" >> PKGBUILD | ||||
|             && makepkg --noconfirm -si | ||||
|             && echo validating scwrypts version | ||||
|             && scwrypts --version | grep "^scwrypts v$PKGVER$" | ||||
|             ; | ||||
|  | ||||
|   aur-publish: | ||||
|     executor: archlinux | ||||
|     steps: | ||||
|       - *archlinux-prepare | ||||
|       - *archlinux-temp-downgrade-fakeroot | ||||
|       - *archlinux-clone-aur | ||||
|       - archlinux-run: | ||||
|           _name: update PKGBUILD and .SRCINFO | ||||
|           working_directory: /home/ci/aur | ||||
|           command: >- | ||||
|             : | ||||
|             && NEW_VERSION=$(echo $CIRCLE_TAG | sed 's/^v//') | ||||
|             && sed "s/pkgver=.*/pkgver=$NEW_VERSION/; s/^pkgrel=.*/pkgrel=1/; /sha256sums/d" PKGBUILD -i | ||||
|             && makepkg -g >> PKGBUILD | ||||
|             && makepkg --printsrcinfo > .SRCINFO | ||||
|             ; | ||||
|       - archlinux-run: | ||||
|           _name: sanity check for version build | ||||
|           working_directory: /home/ci/aur | ||||
|           command: >- | ||||
|             : | ||||
|             && makepkg --noconfirm -si | ||||
|             && scwrypts --version | ||||
|             && scwrypts --version | grep -q "^scwrypts $CIRCLE_TAG\$" | ||||
|             ; | ||||
|       - archlinux-run: | ||||
|           _name: publish new version | ||||
|           working_directory: /home/ci/aur | ||||
|           command: >- | ||||
|             : | ||||
|             && git add PKGBUILD .SRCINFO | ||||
|             && git -c user.email=yage@yage.io -c user.name=yage commit -am "$CIRCLE_TAG" | ||||
|             && eval $(ssh-agent) | ||||
|             && echo -e $SSH_KEY_PRIVATE__AUR | ssh-add - | ||||
|             && git remote add upstream ssh://aur@aur.archlinux.org/scwrypts.git | ||||
|             && GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no" git push upstream | ||||
|             ; | ||||
|       - checkout: | ||||
|           path: ~/scwrypts | ||||
|       - python/dist | ||||
|       - run: pip install twine && twine upload dist/* | ||||
|  | ||||
|   nodejs-test: | ||||
|     executor: nodejs | ||||
| @@ -214,88 +102,32 @@ jobs: | ||||
|             : \ | ||||
|               && [ $CIRCLE_TAG ] \ | ||||
|               && pnpm build \ | ||||
|               && pnpm version $CIRCLE_TAG \ | ||||
|               && pnpm version $(git describe --tags) \ | ||||
|               && pnpm set //registry.npmjs.org/:_authToken=$NPM_TOKEN \ | ||||
|               && pnpm publish --no-git-checks \ | ||||
|               ; | ||||
|  | ||||
|   python-test: | ||||
|     executor: python | ||||
|     working_directory: ~/scwrypts/py/lib | ||||
|     steps: | ||||
|       - checkout: | ||||
|           path: ~/scwrypts | ||||
|       - run: | ||||
|           name: pytest | ||||
|           command: | | ||||
|             : \ | ||||
|               && pip install . .[test] \ | ||||
|               && pytest \ | ||||
|               ; | ||||
|       - run: pip install build && python -m build | ||||
|  | ||||
|   python-publish: | ||||
|     executor: python | ||||
|     working_directory: ~/scwrypts/py/lib | ||||
|     steps: | ||||
|       - checkout: | ||||
|           path: ~/scwrypts | ||||
|       - run: pip install build && python -m build | ||||
|       - run: pip install twine && twine upload dist/* | ||||
|  | ||||
|  | ||||
| workflows: | ||||
|   test: | ||||
|   python: | ||||
|     jobs: | ||||
|       - aur-test: | ||||
|           &dev-filters | ||||
|       - python-test | ||||
|       - python-publish: | ||||
|           requires: [python-test] | ||||
|           context: [pypi-yage] | ||||
|           filters: | ||||
|             branches: | ||||
|               ignore: /^main$/ | ||||
|  | ||||
|       - python-test: *dev-filters | ||||
|       - nodejs-test: *dev-filters | ||||
|  | ||||
|   publish: | ||||
|     jobs: | ||||
|       - require-full-semver: | ||||
|           filters: | ||||
|             &only-run-on-full-semver-tag-filters | ||||
|             tags: | ||||
|               only: /^v\d+\.\d+\.\d+.*$/ | ||||
|               only: /^v.*$/ | ||||
|             branches: | ||||
|               ignore: /^.*$/ | ||||
|  | ||||
|       - aur-test: | ||||
|           &only-publish-for-full-semver | ||||
|           filters: *only-run-on-full-semver-tag-filters | ||||
|           requires: | ||||
|             - require-full-semver | ||||
|       - 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] | ||||
|           requires: | ||||
|             - aur-test | ||||
|             - python-publish | ||||
|             - nodejs-publish | ||||
|  | ||||
|       - python-test: *only-publish-for-full-semver | ||||
|       - python-publish: | ||||
|           filters: *only-run-on-full-semver-tag-filters | ||||
|           context: [pypi-yage] | ||||
|           requires: | ||||
|             - python-test | ||||
|  | ||||
|       - nodejs-test: *only-publish-for-full-semver | ||||
|   nodejs: | ||||
|     jobs: | ||||
|       - nodejs-test | ||||
|       - nodejs-publish: | ||||
|           filters: *only-run-on-full-semver-tag-filters | ||||
|           requires: [nodejs-test] | ||||
|           context: [npm-wrynegade] | ||||
|           requires: | ||||
|             - nodejs-test | ||||
|           filters: | ||||
|             tags: | ||||
|               only: /^v.*$/ | ||||
|             branches: | ||||
|               ignore: /^.*$/ | ||||
|   | ||||
| @@ -12,9 +12,13 @@ export DISCORD__DEFAULT_AVATAR_URL= | ||||
| export DISCORD__DEFAULT_CHANNEL_ID= | ||||
| export DISCORD__DEFAULT_USERNAME= | ||||
| 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 MEDIA_SYNC__S3_BUCKET= | ||||
| export MEDIA_SYNC__TARGETS= | ||||
| export MEDIA_SYNC__S3_BUCKET | ||||
| export MEDIA_SYNC__TARGETS | ||||
| export REDIS_AUTH= | ||||
| export REDIS_HOST= | ||||
| export REDIS_PORT= | ||||
|   | ||||
| @@ -15,6 +15,11 @@ DISCORD__DEFAULT_CHANNEL_ID | | ||||
| DISCORD__DEFAULT_USERNAME   | | ||||
| 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 | ||||
|  | ||||
| MEDIA_SYNC__S3_BUCKET | s3 bucket name and filesystem targets for media backups | ||||
|   | ||||
							
								
								
									
										19
									
								
								.github/workflows/automatic-release.yaml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/automatic-release.yaml
									
									
									
									
										vendored
									
									
								
							| @@ -1,19 +0,0 @@ | ||||
| --- | ||||
| name: Automatic Tag-release | ||||
|  | ||||
| on:  # yamllint disable-line rule:truthy | ||||
|   push: | ||||
|     branches-ignore: | ||||
|       - '**' | ||||
|     tags: | ||||
|       - 'v*.*.*' | ||||
|  | ||||
| jobs: | ||||
|   automatic-tag-release: | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: marvinpinto/action-automatic-releases@latest | ||||
|         with: | ||||
|           repo_token: "${{ secrets.GITHUB_TOKEN }}" | ||||
|           prerelease: false | ||||
| @@ -29,7 +29,6 @@ runs: | ||||
|         repository: wrynegade/scwrypts | ||||
|         path: ./wrynegade/scwrypts | ||||
|         ref: ${{ inputs.version }} | ||||
|         fetch-tags: true | ||||
|  | ||||
|     - name: check dependencies | ||||
|       shell: bash | ||||
| @@ -52,7 +51,7 @@ runs: | ||||
|         } > $HOME/.scwrypts.apt-get.log 2>&1 | ||||
|  | ||||
|         echo "updating virtual dependencies" | ||||
|         $GITHUB_WORKSPACE/wrynegade/scwrypts/scwrypts \ | ||||
|         $GITHUB_WORKSPACE/wrynegade/scwrypts/scwrypts -n \ | ||||
|           --name scwrypts/virtualenv/update-all \ | ||||
|           --group scwrypts \ | ||||
|           --type zsh \ | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| [[ $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 $@; } | ||||
| h() { _SCWRYPTS_KUBECTL_DRIVER helm $@; } | ||||
| f() { _SCWRYPTS_KUBECTL_DRIVER flux $@; } | ||||
| 
 | ||||
| 
 | ||||
| _SCWRYPTS_KUBECTL_DRIVER() { | ||||
| 	[ ! $SCWRYPTS_ENV ] && { | ||||
| 		ERROR "must set SCWRYPTS_ENV in order to use '$(echo $CLI | head -c1)'" | ||||
| @@ -170,7 +171,7 @@ _SCWRYPTS_KUBECTL_DRIVER() { | ||||
| 
 | ||||
| 			[ $NAMESPACE ] && CLI_ARGS+=(--namespace $NAMESPACE) | ||||
| 			[[ $VERBOSE -eq 1 ]] && { | ||||
| 				REMINDER " | ||||
| 				INFO " | ||||
| 					context '$CONTEXT' | ||||
| 					namespace '$NAMESPACE' | ||||
| 					environment '$SCWRYPTS_ENV' | ||||
| @@ -179,7 +180,7 @@ _SCWRYPTS_KUBECTL_DRIVER() { | ||||
| 				STATUS "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | ||||
| 			} || { | ||||
| 				[[ $(_SCWRYPTS_KUBECTL_SETTINGS get context) =~ ^show$ ]] && { | ||||
| 					REMINDER "$SCWRYPTS_ENV.$SUBSESSION : $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | ||||
| 					INFO "$SCWRYPTS_ENV.$SUBSESSION : $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | ||||
| 				} | ||||
| 			} | ||||
| 			$CLI ${CLI_ARGS[@]} ${USER_ARGS[@]} | ||||
|   | ||||
| @@ -112,8 +112,8 @@ KUBECTL__SERVE() { | ||||
| 	SERVICE_PASSWORD="$(KUBECTL__GET_SERVICE_PASSWORD)" | ||||
| 	KUBECTL__SERVICE_PARSE | ||||
| 
 | ||||
| 	REMINDER "attempting to serve ${NAMESPACE}/${SERVICE_NAME}:${SERVICE_PORT}" | ||||
| 	[ $SERVICE_PASSWORD ] && REMINDER "password : $SERVICE_PASSWORD" | ||||
| 	INFO "attempting to serve ${NAMESPACE}/${SERVICE_NAME}:${SERVICE_PORT}" | ||||
| 	[ $SERVICE_PASSWORD ] && INFO "password : $SERVICE_PASSWORD" | ||||
| 
 | ||||
| 	KUBECTL port-forward service/$SERVICE_NAME $SERVICE_PORT | ||||
| } | ||||
|   | ||||
							
								
								
									
										3
									
								
								py/lib/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								py/lib/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,4 +1 @@ | ||||
| dist/ | ||||
| __pycache__/ | ||||
| *.py[cod] | ||||
| *.so | ||||
|   | ||||
| @@ -55,5 +55,6 @@ source = 'versioningit' | ||||
| [tool.hatch.build.targets.wheel] | ||||
| packages = ['./'] | ||||
|  | ||||
| [tool.versioningit.vcs] | ||||
| match = ['v[0-9]*.[0-9]*.[0-9]*'] | ||||
| [tool.versioningit] | ||||
| match = ['v*'] | ||||
|  | ||||
|   | ||||
| @@ -4,7 +4,7 @@ from .scwrypts.exceptions import MissingVariableError | ||||
|  | ||||
|  | ||||
| def getenv(name, required=True): | ||||
|     value = os_getenv(f'{name}__override', os_getenv(name)) | ||||
|     value = os_getenv(name, None) | ||||
|  | ||||
|     if required and not value: | ||||
|         raise MissingVariableError(name) | ||||
|   | ||||
| @@ -2,22 +2,23 @@ from types import SimpleNamespace | ||||
|  | ||||
| from pytest import fixture | ||||
|  | ||||
| from scwrypts.test import get_generator | ||||
| from scwrypts.test import generate | ||||
| from scwrypts.test.character_set import uri | ||||
|  | ||||
| generate = get_generator({ | ||||
| options = { | ||||
|         'str_length_minimum':   8, | ||||
|         'str_length_maximum': 128, | ||||
|         'uuid_output_type':   str, | ||||
|         }) | ||||
|         } | ||||
|  | ||||
| def get_request_client_sample_data(): | ||||
|     return { | ||||
|             'base_url' : generate(str, {'character_set': uri}), | ||||
|             'endpoint' : generate(str, {'character_set': uri}), | ||||
|             'method'   : generate(str), | ||||
|             'response' : generate('requests_Response', {'depth': 4}), | ||||
|             'base_url' : generate(str, options | {'character_set': uri}), | ||||
|             'endpoint' : generate(str, options | {'character_set': uri}), | ||||
|             'method'   : generate(str, options), | ||||
|             'response' : generate('requests_Response', options | {'depth': 4}), | ||||
|             'payload'  : generate(dict, { | ||||
|                 **options, | ||||
|                 'depth': 1, | ||||
|                 'data_types': { str, 'uuid' }, | ||||
|                 }), | ||||
| @@ -29,11 +30,13 @@ def fixture_sample(): | ||||
|             **get_request_client_sample_data(), | ||||
|  | ||||
|             headers = generate(dict, { | ||||
|                 **options, | ||||
|                 'depth': 1, | ||||
|                 'data_types': { str, 'uuid' }, | ||||
|                 }), | ||||
|  | ||||
|             payload_headers = generate(dict, { | ||||
|                 **options, | ||||
|                 'depth': 1, | ||||
|                 'data_types': { str, 'uuid' }, | ||||
|                 }), | ||||
|   | ||||
| @@ -2,14 +2,15 @@ from types import SimpleNamespace | ||||
|  | ||||
| from pytest import fixture | ||||
|  | ||||
| from scwrypts.test import generate | ||||
| 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') | ||||
| def fixture_sample(): | ||||
|     return SimpleNamespace( | ||||
|             **get_request_client_sample_data(), | ||||
|             api_token = generate(str, {'character_set': uri}), | ||||
|             query     = generate(str), | ||||
|             api_token = generate(str, options | {'character_set': uri}), | ||||
|             query     = generate(str, options), | ||||
|             ) | ||||
|   | ||||
| @@ -3,8 +3,9 @@ from types import SimpleNamespace | ||||
|  | ||||
| from pytest import fixture | ||||
|  | ||||
| from scwrypts.test import generate | ||||
| 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') | ||||
| def fixture_sample(): | ||||
| @@ -13,12 +14,12 @@ def fixture_sample(): | ||||
|                 **get_request_client_sample_data(), | ||||
|                 'base_url': 'https://discord.com/api', | ||||
|                 }, | ||||
|             bot_token  = generate(str, {'character_set': uri}), | ||||
|             username   = generate(str, {'character_set': ascii_letters + digits}), | ||||
|             avatar_url = generate(str, {'character_set': uri}), | ||||
|             webhook    = generate(str, {'character_set': uri}), | ||||
|             channel_id = generate(str, {'character_set': uri}), | ||||
|             content_header = generate(str), | ||||
|             content_footer = generate(str), | ||||
|             content = generate(str), | ||||
|             bot_token  = generate(str, options | {'character_set': uri}), | ||||
|             username   = generate(str, options | {'character_set': ascii_letters + digits}), | ||||
|             avatar_url = generate(str, options | {'character_set': uri}), | ||||
|             webhook    = generate(str, options | {'character_set': uri}), | ||||
|             channel_id = generate(str, options | {'character_set': uri}), | ||||
|             content_header = generate(str, options), | ||||
|             content_footer = generate(str, options), | ||||
|             content = generate(str, options), | ||||
|         ) | ||||
|   | ||||
| @@ -3,8 +3,9 @@ from types import SimpleNamespace | ||||
|  | ||||
| from pytest import fixture | ||||
|  | ||||
| from scwrypts.test import generate | ||||
| 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') | ||||
| def fixture_sample(): | ||||
| @@ -13,6 +14,6 @@ def fixture_sample(): | ||||
|                 **get_request_client_sample_data(), | ||||
|                 'base_url': 'https://api.linear.app', | ||||
|                 }, | ||||
|             api_token = generate(str, {'character_set': uri}), | ||||
|             query     = generate(str), | ||||
|             api_token = generate(str, options | {'character_set': uri}), | ||||
|             query     = generate(str, options), | ||||
|         ) | ||||
|   | ||||
| @@ -13,7 +13,7 @@ class MissingFlagAndEnvironmentVariableError(EnvironmentError, ArgumentError): | ||||
|  | ||||
| class MissingScwryptsExecutableError(EnvironmentError): | ||||
|     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): | ||||
|   | ||||
| @@ -5,54 +5,44 @@ from subprocess import run | ||||
| 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 | ||||
|  | ||||
|         patterns          str / list   pattern-based scwrypt lookup | ||||
|         args              str / list   arguments forwarded to the invoked scwrypt | ||||
|         executable_args   str / list   arguments for the 'scwrypts' executable | ||||
|           (str above assumes space-delimited values) | ||||
|     - patterns allows for pattern-based scwrypt lookup | ||||
|     - name/group/type allos for precise-match lookup | ||||
|  | ||||
|         name    str   exact scwrypt lookup name (requires group and _type) | ||||
|         group   str   exact scwrypt lookup group | ||||
|         _type   str   exact scwrypt lookup type | ||||
|  | ||||
|         SCWRYPTS_EXECUTABLE   configuration variable which defines the full path to scwrypts executable | ||||
|     *args should be a list of strings and is forwarded to the | ||||
|     invoked scwrypt | ||||
|  | ||||
|     see 'scwrypts --help' for more information | ||||
|     ''' | ||||
|     if patterns is None and name is None: | ||||
|         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')) | ||||
|  | ||||
|     executable = which('scwrypts') | ||||
|     if executable is None: | ||||
|         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', '') | ||||
|     if depth != '': | ||||
|         depth = int(depth) + 1 | ||||
|  | ||||
|     return run( | ||||
|         f'SUBSCWRYPT={depth} {executable} {_parse(executable_args)} {lookup} -- {_parse(args)}', | ||||
|         f'SUBSCWRYPT={depth} {executable} {pre_args} -- {" ".join(args)}', | ||||
|         shell=True, | ||||
|         executable='/bin/zsh', | ||||
|         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) | ||||
|   | ||||
| @@ -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, | ||||
|         ]) | ||||
| @@ -5,6 +5,6 @@ __all__ = [ | ||||
|         'generate', | ||||
|         ] | ||||
|  | ||||
| from .generate import generate, get_generator | ||||
| from .generate import generate | ||||
|  | ||||
| from .character_set import * | ||||
|   | ||||
| @@ -45,21 +45,6 @@ DEFAULT_OPTIONS = { | ||||
|         '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): | ||||
|     ''' | ||||
|     generate random data with the call of a function | ||||
|   | ||||
							
								
								
									
										388
									
								
								run
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										388
									
								
								run
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,388 @@ | ||||
| #!/bin/zsh | ||||
| export EXECUTION_DIR=$(pwd) | ||||
| source "${0:a:h}/zsh/lib/import.driver.zsh" || exit 42 | ||||
| ##################################################################### | ||||
| () { | ||||
| 	cd "$SCWRYPTS_ROOT__scwrypts" | ||||
| 	GIT_SCWRYPTS() { git -C "$SCWRYPTS_ROOT__scwrypts" $@; } | ||||
| 	local ERRORS=0 | ||||
| 	local USAGE=' | ||||
| 		usage: scwrypts [...options...] [...patterns...] -- [...script options...] | ||||
|  | ||||
| 		options: | ||||
| 		  selection | ||||
| 		    -m, --name <scwrypt-name>   only run the script if there is an exact match | ||||
| 		                                  (requires type and group) | ||||
| 		    -g, --group <group-name>    only use scripts from the indicated group | ||||
| 		    -t, --type <type-name>      only use scripts of the indicated type | ||||
|  | ||||
| 		  runtime | ||||
| 		    -y, --yes              auto-accept all [yn] prompts through current scwrypt | ||||
| 		    -e, --env <env-name>   set environment; overwrites SCWRYPTS_ENV | ||||
| 		    -n                     shorthand for "--log-level 0" | ||||
| 		    -v, --log-level [0-4]  set scwrypts log level to one of the following: | ||||
| 			                         0 : only command output and critical failures; skips logfile | ||||
| 			                         1 : add success / failure messages | ||||
| 			                         2 : (default) include status update messages | ||||
| 									 3 : (CI default) include warning messages | ||||
| 			                         4 : include debug messages | ||||
|  | ||||
| 		  alternate commands | ||||
| 		    -h, --help        display this message and exit | ||||
| 		    -l, --list        print out command list and exit | ||||
| 		        --list-envs   print out environment list and exit | ||||
| 		        --update      update scwrypts library to latest version | ||||
| 		        --version     print out scwrypts version and exit | ||||
|  | ||||
| 		patterns: | ||||
| 		  - a list of glob patterns to loose-match a scwrypt by name | ||||
|  | ||||
| 		script options: | ||||
| 		  - everything after "--" is forwarded to the scwrypt you run | ||||
| 		    ("-- --help" will provide more information) | ||||
| 	' | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### cli argument parsing and global configuration ################### | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local ENV_NAME="$SCWRYPTS_ENV" | ||||
| 	local SEARCH_PATTERNS=() | ||||
|  | ||||
| 	local VARSPLIT SEARCH_GROUP SEARCH_TYPE SEARCH_NAME | ||||
|  | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && { | ||||
| 		local SCWRYPTS_LOG_LEVEL | ||||
| 		[ $CI ] && SCWRYPTS_LOG_LEVEL=3 || SCWRYPTS_LOG_LEVEL=2 | ||||
| 	} | ||||
|  | ||||
| 	while [[ $# -gt 0 ]] | ||||
| 	do | ||||
| 		case $1 in | ||||
| 			-[a-z][a-z]* ) | ||||
| 				VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/') | ||||
| 				set -- $(echo " $VARSPLIT ") ${@:2} | ||||
| 				;; | ||||
|  | ||||
| 			### alternate commands ################### | ||||
|  | ||||
| 			-h | --help ) | ||||
| 				USAGE | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			-l | --list ) | ||||
| 				SCWRYPTS__GET_AVAILABLE_SCWRYPTS | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--list-envs ) | ||||
| 				SCWRYPTS__GET_ENV_NAMES | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--version ) | ||||
| 				echo scwrypts $(GIT_SCWRYPTS describe --tags) | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--update ) | ||||
| 				GIT_SCWRYPTS fetch --quiet origin main | ||||
| 				GIT_SCWRYPTS fetch --quiet origin main --tags | ||||
| 				local SYNC_STATUS=$? | ||||
|  | ||||
| 				GIT_SCWRYPTS diff --exit-code origin/main -- . >/dev/null 2>&1 | ||||
| 				local DIFF_STATUS=$? | ||||
|  | ||||
| 				[[ $SYNC_STATUS -eq 0 ]] && [[ $DIFF_STATUS -eq 0 ]] && { | ||||
| 					SUCCESS 'already up-to-date with origin/main' | ||||
| 				} || { | ||||
| 					GIT_SCWRYPTS rebase --autostash origin/main \ | ||||
| 						&& SUCCESS 'up-to-date with origin/main' \ | ||||
| 						&& GIT_SCWRYPTS log -n1 \ | ||||
| 						|| { | ||||
| 							GIT_SCWRYPTS rebase --abort | ||||
| 							ERROR 'unable to update scwrypts; please try manual upgrade' | ||||
| 							REMINDER "installation in '$(pwd)'" | ||||
| 						} | ||||
| 				} | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			### scwrypts filters ##################### | ||||
|  | ||||
| 			-m | --name ) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_NAME=$2 | ||||
| 				shift 1 | ||||
| 				;; | ||||
|  | ||||
| 			-g | --group ) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_GROUP=$2 | ||||
| 				shift 1 | ||||
| 				;; | ||||
|  | ||||
| 			-t | --type ) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_TYPE=$2 | ||||
| 				shift 1 | ||||
| 				;; | ||||
|  | ||||
| 			### runtime settings ##################### | ||||
|  | ||||
| 			-y | --yes ) export __SCWRYPTS_YES=1 ;; | ||||
|  | ||||
| 			-n | --no-log ) | ||||
| 				SCWRYPTS_LOG_LEVEL=0 | ||||
| 				[[ $1 =~ ^--no-log$ ]] && WARNING 'the --no-log flag is deprecated and will be removed in scwrypts v4.2' | ||||
| 				;; | ||||
|  | ||||
| 			-v | --log-level ) | ||||
| 				[[ $2 =~ ^[0-4]$ ]] || ERROR "invalid setting for log-level '$2'" | ||||
| 				SCWRYPTS_LOG_LEVEL=$2 | ||||
| 				shift 1 | ||||
| 				;; | ||||
|  | ||||
| 			-e | --env ) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
|  | ||||
| 				[ $ENV_NAME ] && DEBUG 'overwriting session environment' | ||||
|  | ||||
| 				ENV_NAME="$2" | ||||
| 				STATUS "using CLI environment '$ENV_NAME'" | ||||
| 				shift 1 | ||||
| 				;; | ||||
|  | ||||
| 			########################################## | ||||
|  | ||||
| 			--  ) shift 1; break ;; # pass arguments after '--' to the scwrypt | ||||
| 			--* ) ERROR "unrecognized argument '$1'" ;; | ||||
| 			*   ) SEARCH_PATTERNS+=($1) ;; | ||||
| 		esac | ||||
| 		shift 1 | ||||
| 	done | ||||
|  | ||||
| 	[ $SEARCH_NAME ] && { | ||||
| 		[ $SEARCH_TYPE  ] || ERROR '--name requires --type argument' | ||||
| 		[ $SEARCH_GROUP ] || ERROR '--name requires --group argument' | ||||
| 	} | ||||
|  | ||||
| 	CHECK_ERRORS | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### scwrypts selection / filtering ################################## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local SCWRYPTS_AVAILABLE | ||||
| 	SCWRYPTS_AVAILABLE=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS) | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[ $SEARCH_NAME ] && SCWRYPTS_AVAILABLE=$({ | ||||
| 		echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 		echo $SCWRYPTS_AVAILABLE | sed -e 's/\x1b\[[0-9;]*m//g' | grep "^$SEARCH_NAME *$SEARCH_TYPE *$SEARCH_GROUP\$" | ||||
| 	}) || { | ||||
| 		[ $SEARCH_TYPE ] && { | ||||
| 			SCWRYPTS_AVAILABLE=$(\ | ||||
| 				{ | ||||
| 					echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 					echo $SCWRYPTS_AVAILABLE | grep ' [^/]*'$SEARCH_TYPE'[^/]* ' | ||||
| 				} \ | ||||
| 				| awk '{$2=""; print $0;}' \ | ||||
| 				| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g'  \ | ||||
| 				| column -ts '^' | ||||
| 			) | ||||
| 		} | ||||
|  | ||||
| 		[ $SEARCH_GROUP ] && { | ||||
| 			SCWRYPTS_AVAILABLE=$( | ||||
| 				{ | ||||
| 					echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 					echo $SCWRYPTS_AVAILABLE | grep "$SEARCH_GROUP"'[^/]*$' | ||||
| 				} \ | ||||
| 				| awk '{$NF=""; print $0;}' \ | ||||
| 				| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g'  \ | ||||
| 				| column -ts '^' | ||||
| 			) | ||||
| 		} | ||||
|  | ||||
| 		[[ ${#SEARCH_PATTERNS[@]} -gt 0 ]] && { | ||||
| 			POTENTIAL_ERROR+="\n   PATTERNS : $SEARCH_PATTERNS" | ||||
| 			local P | ||||
| 			for P in ${SEARCH_PATTERNS[@]} | ||||
| 			do | ||||
| 				SCWRYPTS_AVAILABLE=$( | ||||
| 					{ | ||||
| 						echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 						echo $SCWRYPTS_AVAILABLE | grep $P | ||||
| 					} | ||||
| 				) | ||||
| 			done | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -lt 2 ]] && { | ||||
| 		FAIL 1 "$(echo " | ||||
| 		no such scwrypt exists | ||||
| 		  NAME     : '$SEARCH_NAME' | ||||
| 		  TYPE     : '$SEARCH_TYPE' | ||||
| 		  GROUP    : '$SEARCH_GROUP' | ||||
| 		  PATTERNS : '$SEARCH_PATTERNS' | ||||
| 		" | sed "1d; \$d; /''$/d")" | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -eq 2 ]] \ | ||||
| 		&& SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | tail -n1) \ | ||||
| 		|| SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | FZF "select a script to run" --header-lines 1) \ | ||||
| 		; | ||||
|  | ||||
| 	[ $SCWRYPT_SELECTION ] || exit 2 | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	local NAME TYPE GROUP | ||||
| 	SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION | ||||
|  | ||||
| 	export SCWRYPT_NAME=$NAME | ||||
| 	export SCWRYPT_TYPE=$TYPE | ||||
| 	export SCWRYPT_GROUP=$GROUP | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### environment variables and configuration validation ############## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local ENV_REQUIRED=true \ | ||||
| 		&& [ ! $CI ] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/logs ]] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/environment ]] \ | ||||
| 		|| ENV_REQUIRED=false | ||||
|  | ||||
| 	local REQUIRED_ENVIRONMENT_REGEX=$(eval echo '$SCWRYPTS_REQUIRED_ENVIRONMENT_REGEX__'$SCWRYPT_GROUP) | ||||
|  | ||||
| 	[[ $ENV_REQUIRED =~ true ]] && { | ||||
| 		[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV) | ||||
|  | ||||
| 		for GROUP in ${SCWRYPTS_GROUPS[@]} | ||||
| 		do | ||||
| 			local ENV_FILE=$(SCWRYPTS__GET_ENV_FILE "$ENV_NAME" "$GROUP") | ||||
| 			source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$GROUP/$ENV_NAME'" | ||||
|  | ||||
| 			for f in $(eval 'echo $SCWRYPTS_STATIC_CONFIG__'$GROUP) | ||||
| 			do | ||||
| 				source "$f" || FAIL 5 "invalid static config '$f'" | ||||
| 			done | ||||
| 		done | ||||
|  | ||||
| 		export ENV_NAME | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[ $REQUIRED_ENVIRONMENT_REGEX ] && { | ||||
| 		[[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \ | ||||
| 			|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment name to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)" | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[ ! $SUBSCWRYPT ] && [[ $ENV_NAME =~ prod ]] && { | ||||
| 		STATUS "on '$ENV_NAME'; checking diff against origin/main" | ||||
|  | ||||
| 		GIT_SCWRYPTS fetch --quiet origin main | ||||
| 		local SYNC_STATUS=$? | ||||
|  | ||||
| 		GIT_SCWRYPTS diff --exit-code origin/main -- . >&2 | ||||
| 		local DIFF_STATUS=$? | ||||
|  | ||||
| 		[[ $SYNC_STATUS -eq 0 ]] && [[ $DIFF_STATUS -eq 0 ]] && { | ||||
| 			SUCCESS 'up-to-date with origin/main' | ||||
| 		} || { | ||||
| 			SCWRYPTS_LOG_LEVEL=3 WARNING "you are trying to run in ${__BRIGHT_RED}production${__YELLOW} but $([[ $SYNC_STATUS -ne 0 ]] && echo 'I am unable to verify your scwrypts version')$([[ $DIFF_STATUS -ne 0 ]] && echo 'your scwrypts is out-of-date (diff listed above)')" | ||||
|  | ||||
| 			yN 'continue?' || { | ||||
| 				REMINDER "you can use 'scwrypts --update' to quickly update scwrypts to latest" | ||||
| 				ABORT | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	local RUN_STRING=$(SCWRYPTS__GET_RUNSTRING $SCWRYPT_NAME $SCWRYPT_TYPE $SCWRYPT_GROUP) | ||||
| 	[ "$RUN_STRING" ] || return 42 | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### logging and pretty header/footer setup ########################## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local LOGFILE \ | ||||
| 		&& [[ $SCWRYPTS_LOG_LEVEL -gt 0 ]] \ | ||||
| 		&& [ ! $SUBSCWRYPT ] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/logs ]] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ interactive ]] \ | ||||
| 		&& LOGFILE="$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log" \ | ||||
| 		|| LOGFILE='/dev/null' \ | ||||
| 		; | ||||
|  | ||||
| 	local RUN_MODE=normal | ||||
| 	[[ $LOGFILE      =~ ^/dev/null$ ]] && RUN_MODE=no-logfile | ||||
| 	[[ $SCWRYPT_NAME =~ interactive ]] && RUN_MODE=interactive | ||||
|  | ||||
| 	local HEADER FOOTER | ||||
|  | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && { | ||||
| 		HEADER=$( | ||||
| 			echo " | ||||
| 				===================================================================== | ||||
| 				script    : $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" | ||||
| 	} | ||||
|  | ||||
| 	[ $SUBSCWRYPT ] && { | ||||
| 		HEADER="\\033[0;33m--- ($SUBSCWRYPT) BEGIN $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---" | ||||
| 		FOOTER="\\033[0;33m--- ($SUBSCWRYPT) END   $SCWRYPT_GROUP $SCWRYPT_TYPE $SCWRYPT_NAME ---" | ||||
| 	} | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### run the scwrypt ################################################# | ||||
| 	##################################################################### | ||||
|  | ||||
| 	[ ! $SUBSCWRYPT ] && export SUBSCWRYPT=0 | ||||
|  | ||||
| 	set -o pipefail | ||||
| 	{ | ||||
| 		[ $HEADER ] && echo $HEADER | ||||
| 		case $RUN_MODE in | ||||
| 			normal ) | ||||
| 				(eval "$RUN_STRING $(printf "%q " "$@")") | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 			no-logfile ) | ||||
| 				eval "$RUN_STRING $(printf "%q " "$@")" | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 			interactive ) | ||||
| 				eval "$RUN_STRING $(printf "%q " "$@")" </dev/tty >/dev/tty 2>&1 | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 		esac | ||||
| 		[ $FOOTER ] && echo $FOOTER | ||||
| 		[[ $EXIT_CODE -eq 0 ]] && EXIT_COLOR='32m' || EXIT_COLOR='31m' | ||||
|  | ||||
| 		[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && [ ! $SUBSCWRYPT ] \ | ||||
| 			&& echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m" | ||||
|  | ||||
| 		return $EXIT_CODE | ||||
| 	} 2>&1 | tee --append "$LOGFILE" | ||||
|  | ||||
| } $@ | ||||
							
								
								
									
										482
									
								
								scwrypts
									
									
									
									
									
								
							
							
						
						
									
										482
									
								
								scwrypts
									
									
									
									
									
								
							| @@ -1,482 +1,2 @@ | ||||
| #!/bin/zsh | ||||
| export EXECUTION_DIR=$(pwd) | ||||
| export SCWRYPTS_RUNTIME_ID=$(uuidgen) | ||||
| source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42 | ||||
| ##################################################################### | ||||
| () { | ||||
| 	cd "$SCWRYPTS_ROOT__scwrypts" | ||||
| 	GIT_SCWRYPTS() { git -C "$SCWRYPTS_ROOT__scwrypts" $@; } | ||||
|  | ||||
|  | ||||
| 	local ERRORS=0 | ||||
| 	local USAGE=' | ||||
| 		usage: scwrypts [...options...] [...patterns...] -- [...script options...] | ||||
|  | ||||
| 		options: | ||||
| 		  selection | ||||
| 		    -m, --name <scwrypt-name>   only run the script if there is an exact match | ||||
| 		                                  (requires type and group) | ||||
| 		    -g, --group <group-name>    only use scripts from the indicated group | ||||
| 		    -t, --type <type-name>      only use scripts of the indicated type | ||||
|  | ||||
| 		  runtime | ||||
| 		    -y, --yes              auto-accept all [yn] prompts through current scwrypt | ||||
| 		    -e, --env <env-name>   set environment; overwrites SCWRYPTS_ENV | ||||
|  | ||||
| 		    -n                      shorthand for "--log-level 0" | ||||
| 		    -v, --log-level <0-4>   set incremental scwrypts log level to one of the following: | ||||
| 		                              0 : only command output and critical failures; skips logfile | ||||
| 		                              1 : include success / failure messages | ||||
| 		                              2 : include status update messages | ||||
| 		                              3 : (default) include warning messages | ||||
| 		                              4 : include debug messages | ||||
|  | ||||
| 		     -o, --output <format>   specify output format; one of: pretty,json (default: pretty) | ||||
|  | ||||
| 		  alternate commands | ||||
| 		    -h, --help          display this message and exit | ||||
| 		    -l, --list          print out command list and exit | ||||
| 		        --list-envs     print out environment list and exit | ||||
| 		        --list-groups   print out configured scwrypts groups and exit | ||||
| 		        --config        "eval"-ed to enable config and "use" import in non-scwrypts environments | ||||
| 		        --root          print out SCWRYPTS_ROOT__scwrypts and exit | ||||
| 		        --update        update scwrypts library to latest version | ||||
| 		        --version       print out scwrypts version and exit | ||||
|  | ||||
| 		patterns: | ||||
| 		  - a list of glob patterns to loose-match a scwrypt by name | ||||
|  | ||||
| 		script options: | ||||
| 		  - everything after "--" is forwarded to the scwrypt you run | ||||
| 		    ("-- --help" will provide more information) | ||||
| 	' | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### cli argument parsing and global configuration ################### | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local ENV_NAME="$SCWRYPTS_ENV" | ||||
| 	local SEARCH_PATTERNS=() | ||||
|  | ||||
| 	local VARSPLIT SEARCH_GROUP SEARCH_TYPE SEARCH_NAME | ||||
|  | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=3 | ||||
|  | ||||
| 	local SHIFT_COUNT | ||||
| 	while [[ $# -gt 0 ]] | ||||
| 	do | ||||
| 		SHIFT_COUNT=1 | ||||
| 		case $1 in | ||||
| 			-[a-z][a-z]* ) | ||||
| 				VARSPLIT=$(echo "$1 " | sed 's/^\(-.\)\(.*\) /\1 -\2/') | ||||
| 				set -- throw-away $(echo " $VARSPLIT ") ${@:2} | ||||
| 				;; | ||||
|  | ||||
| 			### alternate commands ################### | ||||
|  | ||||
| 			-h | --help ) | ||||
| 				USAGE | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			-l | --list ) | ||||
| 				SCWRYPTS__GET_AVAILABLE_SCWRYPTS | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--list-envs ) | ||||
| 				SCWRYPTS__GET_ENV_NAMES | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--list-groups ) | ||||
| 				echo "${SCWRYPTS_GROUPS[@]}" | sed 's/\s\+/\n/g' | sort -u | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			--version ) | ||||
| 				case $SCWRYPTS_INSTALLATION_TYPE in | ||||
| 					manual ) echo "scwrypts $(GIT_SCWRYPTS describe --tags) (via GIT)" ;; | ||||
| 					     * ) echo "scwrypts $(cat "$SCWRYPTS_ROOT__scwrypts/VERSION")" ;; | ||||
| 				esac | ||||
| 				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 ) | ||||
| 				case $SCWRYPTS_INSTALLATION_TYPE in | ||||
| 					aur ) | ||||
| 						SCWRYPTS_LOG_LEVEL=3 REMINDER " | ||||
| 							This installation is built from the AUR. Update through 'makepkg' or use | ||||
| 							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 ) | ||||
| 						GIT_SCWRYPTS fetch --quiet origin main | ||||
| 						GIT_SCWRYPTS fetch --quiet origin main --tags | ||||
| 						local SYNC_STATUS=$? | ||||
|  | ||||
| 						GIT_SCWRYPTS diff --exit-code origin/main -- . >/dev/null 2>&1 | ||||
| 						local DIFF_STATUS=$? | ||||
|  | ||||
| 						[[ $SYNC_STATUS -eq 0 ]] && [[ $DIFF_STATUS -eq 0 ]] && { | ||||
| 							SUCCESS 'already up-to-date with origin/main' | ||||
| 						} || { | ||||
| 							GIT_SCWRYPTS rebase --autostash origin/main \ | ||||
| 								&& SUCCESS 'up-to-date with origin/main' \ | ||||
| 								&& GIT_SCWRYPTS log -n1 \ | ||||
| 								|| { | ||||
| 									GIT_SCWRYPTS rebase --abort | ||||
| 									ERROR 'unable to update scwrypts; please try manual upgrade' | ||||
| 									REMINDER "installation in '$SCWRYPTS_ROOT__scwrypts'" | ||||
| 								} | ||||
| 						} | ||||
| 						;; | ||||
|  | ||||
| 					* ) | ||||
| 						SCWRYPTS_LOG_LEVEL=3 REMINDER " | ||||
| 							This is a managed installation of scwrypts. Please update through your | ||||
| 							system package manager. | ||||
| 							 " | ||||
| 						;; | ||||
| 				esac | ||||
| 				return 0 | ||||
| 				;; | ||||
|  | ||||
| 			### scwrypts filters ##################### | ||||
|  | ||||
| 			-m | --name ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_NAME=$2 | ||||
| 				;; | ||||
|  | ||||
| 			-g | --group ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_GROUP=$2 | ||||
| 				GROUP=$2 | ||||
| 				;; | ||||
|  | ||||
| 			-t | --type ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
| 				SEARCH_TYPE=$2 | ||||
| 				TYPE=$2 | ||||
| 				;; | ||||
|  | ||||
| 			### runtime settings ##################### | ||||
|  | ||||
| 			-y | --yes ) export __SCWRYPTS_YES=1 ;; | ||||
|  | ||||
| 			-n ) SCWRYPTS_LOG_LEVEL=0 ;; | ||||
|  | ||||
| 			-v | --log-level ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				[[ $2 =~ ^[0-4]$ ]] || ERROR "invalid setting for log-level '$2'" | ||||
| 				SCWRYPTS_LOG_LEVEL=$2 | ||||
| 				;; | ||||
|  | ||||
| 			-o | --output ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				export SCWRYPTS_OUTPUT_FORMAT=$2 | ||||
| 				case $SCWRYPTS_OUTPUT_FORMAT in | ||||
| 					pretty | json ) ;; | ||||
| 					* ) ERROR "unsupported format '$SCWRYPTS_OUTPUT_FORMAT'" ;; | ||||
| 				esac | ||||
| 				;; | ||||
|  | ||||
| 			-e | --env ) | ||||
| 				((SHIFT_COUNT+=1)) | ||||
| 				[ $2 ] || { ERROR "missing value for argument $1"; break; } | ||||
|  | ||||
| 				[ $ENV_NAME ] && DEBUG 'overwriting session environment' | ||||
|  | ||||
| 				ENV_NAME="$2" | ||||
| 				STATUS "using CLI environment '$ENV_NAME'" | ||||
| 				;; | ||||
|  | ||||
| 			########################################## | ||||
|  | ||||
| 			--  ) shift 1; break ;; # pass arguments after '--' to the scwrypt | ||||
| 			--* ) ERROR "unrecognized argument '$1'" ;; | ||||
| 			*   ) SEARCH_PATTERNS+=($1) ;; | ||||
| 		esac | ||||
| 		shift $SHIFT_COUNT | ||||
| 	done | ||||
|  | ||||
| 	[ $SCWRYPTS_OUTPUT_FORMAT ] || export SCWRYPTS_OUTPUT_FORMAT=pretty | ||||
|  | ||||
| 	[ $SEARCH_NAME ] && { | ||||
| 		[ $SEARCH_TYPE  ] || ERROR '--name requires --type argument' | ||||
| 		[ $SEARCH_GROUP ] || ERROR '--name requires --group argument' | ||||
| 	} | ||||
|  | ||||
| 	CHECK_ERRORS | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### scwrypts selection / filtering ################################## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local SCWRYPTS_AVAILABLE | ||||
| 	SCWRYPTS_AVAILABLE=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS) | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[ $SEARCH_NAME ] && SCWRYPTS_AVAILABLE=$({ | ||||
| 		echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 		echo $SCWRYPTS_AVAILABLE | sed -e 's/\x1b\[[0-9;]*m//g' | grep "^$SEARCH_NAME *$SEARCH_TYPE *$SEARCH_GROUP\$" | ||||
| 	}) || { | ||||
| 		[ $SEARCH_TYPE ] && { | ||||
| 			SCWRYPTS_AVAILABLE=$(\ | ||||
| 				{ | ||||
| 					echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 					echo $SCWRYPTS_AVAILABLE | grep ' [^/]*'$SEARCH_TYPE'[^/]* ' | ||||
| 				} \ | ||||
| 				| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g'  \ | ||||
| 				| column -ts '^' | ||||
| 			) | ||||
| 		} | ||||
|  | ||||
| 		[ $SEARCH_GROUP ] && { | ||||
| 			SCWRYPTS_AVAILABLE=$( | ||||
| 				{ | ||||
| 					echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 					echo $SCWRYPTS_AVAILABLE | grep "$SEARCH_GROUP"'[^/ 	]*$' | ||||
| 				} \ | ||||
| 				| sed 's/ \+$/'$(printf $__COLOR_RESET)'/; s/ \+/^/g'  \ | ||||
| 				| column -ts '^' | ||||
| 			) | ||||
| 		} | ||||
|  | ||||
| 		[[ ${#SEARCH_PATTERNS[@]} -gt 0 ]] && { | ||||
| 			POTENTIAL_ERROR+="\n   PATTERNS : $SEARCH_PATTERNS" | ||||
| 			local P | ||||
| 			for P in ${SEARCH_PATTERNS[@]} | ||||
| 			do | ||||
| 				SCWRYPTS_AVAILABLE=$( | ||||
| 					{ | ||||
| 						echo $SCWRYPTS_AVAILABLE | head -n1 | ||||
| 						echo $SCWRYPTS_AVAILABLE | grep $P | ||||
| 					} | ||||
| 				) | ||||
| 			done | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -lt 2 ]] && { | ||||
| 		FAIL 1 "$(echo " | ||||
| 		no such scwrypt exists | ||||
| 		  NAME     : '$SEARCH_NAME' | ||||
| 		  TYPE     : '$SEARCH_TYPE' | ||||
| 		  GROUP    : '$SEARCH_GROUP' | ||||
| 		  PATTERNS : '$SEARCH_PATTERNS' | ||||
| 		" | sed "1d; \$d; /''$/d")" | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[[ $(echo $SCWRYPTS_AVAILABLE | wc -l) -eq 2 ]] \ | ||||
| 		&& SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | tail -n1) \ | ||||
| 		|| SCWRYPT_SELECTION=$(echo $SCWRYPTS_AVAILABLE | FZF "select a script to run" --header-lines 1) \ | ||||
| 		; | ||||
|  | ||||
| 	[ $SCWRYPT_SELECTION ] || exit 2 | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	local NAME TYPE GROUP | ||||
| 	SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION | ||||
|  | ||||
| 	export SCWRYPT_NAME=$NAME | ||||
| 	export SCWRYPT_TYPE=$TYPE | ||||
| 	export SCWRYPT_GROUP=$GROUP | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### environment variables and configuration validation ############## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local ENV_REQUIRED=true \ | ||||
| 		&& [ ! $CI ] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/logs ]] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/environment ]] \ | ||||
| 		|| ENV_REQUIRED=false | ||||
|  | ||||
| 	local REQUIRED_ENVIRONMENT_REGEX=$(eval echo '$SCWRYPTS_REQUIRED_ENVIRONMENT_REGEX__'$SCWRYPT_GROUP) | ||||
|  | ||||
| 	[ $ENV_NAME ] && [ $REQUIRED_ENVIRONMENT_REGEX ] && { | ||||
| 		[[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \ | ||||
| 			|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment name to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)" | ||||
| 	} | ||||
|  | ||||
| 	[[ $ENV_REQUIRED =~ true ]] && { | ||||
| 		[ ! $ENV_NAME ] && ENV_NAME=$(SCWRYPTS__SELECT_ENV) | ||||
| 		[ ! $ENV_NAME ] && ABORT | ||||
|  | ||||
| 		export ENV_NAME | ||||
| 		export SCWRYPTS_ENV=$ENV_NAME | ||||
|  | ||||
| 		for GROUP in ${SCWRYPTS_GROUPS[@]} | ||||
| 		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") | ||||
| 			source "$ENV_FILE" || FAIL 5 "missing or invalid environment '$GROUP/$ENV_NAME'" | ||||
|  | ||||
| 			for f in $(eval 'echo $SCWRYPTS_STATIC_CONFIG__'$GROUP) | ||||
| 			do | ||||
| 				source "$f" || FAIL 5 "invalid static config '$f'" | ||||
| 			done | ||||
| 		done | ||||
| 	} | ||||
|  | ||||
| 	[ $REQUIRED_ENVIRONMENT_REGEX ] && { | ||||
| 		[[ $ENV_NAME =~ $REQUIRED_ENVIRONMENT_REGEX ]] \ | ||||
| 			|| FAIL 5 "group '$SCWRYPT_GROUP' requires current environment name to match '$REQUIRED_ENVIRONMENT_REGEX' (currently $ENV_NAME)" | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	[ ! $SUBSCWRYPT ] && export SUBSCWRYPT=0 | ||||
|  | ||||
| 	[[ $SCWRYPTS_INSTALLATION_TYPE =~ ^manual$ ]] && { | ||||
| 		[[ $SUBSCWRYPT -eq 0 ]] && [[ $ENV_NAME =~ prod ]] && [[ $SCWRYPTS_LOG_LEVEL -gt 0 ]] && { | ||||
| 			STATUS "on '$ENV_NAME'; checking diff against origin/main" | ||||
|  | ||||
| 			local WARNING_MESSAGE | ||||
|  | ||||
| 			[ ! $WARNING_MESSAGE ] && { | ||||
| 				GIT_SCWRYPTS fetch --quiet origin main \ | ||||
| 					|| WARNING_MESSAGE='I am unable to verify your scwrypts version' | ||||
| 			} | ||||
|  | ||||
| 			[ ! $WARNING_MESSAGE ] && { | ||||
| 				GIT_SCWRYPTS diff --exit-code origin/main -- . >/dev/null 2>&1 \ | ||||
| 					|| WARNING_MESSAGE='your scwrypts is currently out-of-date' | ||||
| 			} | ||||
|  | ||||
| 			[ $WARNING_MESSAGE ] && { | ||||
| 				[[ $SCWRYPTS_LOG_LEVEL -lt 3 ]] && { | ||||
| 					REMINDER "you are running in ${__BRIGHT_RED}production${__BRIGHT_MAGENTA} and $WARNING_MESSAGE" | ||||
| 				} || { | ||||
| 					GIT_SCWRYPTS diff --exit-code origin/main -- . >&2 | ||||
| 					WARNING "you are trying to run in ${__BRIGHT_RED}production${__YELLOW} but $WARNING_MESSAGE (relevant diffs and errors above)" | ||||
| 					yN 'continue?' || { | ||||
| 						REMINDER "you can use 'scwrypts --update' to quickly update scwrypts to latest" | ||||
| 						ABORT | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	########################################## | ||||
|  | ||||
| 	local RUN_STRING=$(SCWRYPTS__GET_RUNSTRING $SCWRYPT_NAME $SCWRYPT_TYPE $SCWRYPT_GROUP) | ||||
| 	[ "$RUN_STRING" ] || return 42 | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### logging and pretty header/footer setup ########################## | ||||
| 	##################################################################### | ||||
|  | ||||
| 	local LOGFILE \ | ||||
| 		&& [[ $SCWRYPTS_LOG_LEVEL -gt 0 ]] \ | ||||
| 		&& [[ $SUBSCWRYPT -eq 0 ]] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ scwrypts/logs ]] \ | ||||
| 		&& [[ ! $SCWRYPT_NAME =~ interactive ]] \ | ||||
| 		&& LOGFILE="$SCWRYPTS_LOG_PATH/$(echo $GROUP/$TYPE/$NAME | sed 's/^\.\///; s/\//\%/g').log" \ | ||||
| 		|| LOGFILE='/dev/null' \ | ||||
| 		; | ||||
|  | ||||
| 	local RUN_MODE=normal | ||||
| 	[[ $LOGFILE      =~ ^/dev/null$ ]] && RUN_MODE=no-logfile | ||||
| 	[[ $SCWRYPT_NAME =~ interactive ]] && RUN_MODE=interactive | ||||
|  | ||||
| 	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" | ||||
| 				;; | ||||
| 			json ) | ||||
| 				HEADER=$(echo '{}' | jq -c ". | ||||
| 					| .timestamp  = \"$(date +%s)\" | ||||
| 					| .runtime    = \"$SCWRYPTS_RUNTIME_ID\" | ||||
| 					| .scwrypt    = \"start of $SCWRYPT_NAME $SCWRYPT_GROUP $SCWRYPT_TYPE\" | ||||
| 					| .config     = \"$ENV_NAME\" | ||||
| 					| .logLevel   = \"$SCWRYPTS_LOG_LEVEL\" | ||||
| 					| .subscwrypt = $SUBSCWRYPT | ||||
| 					") | ||||
| 				;; | ||||
| 		esac | ||||
| 	} | ||||
|  | ||||
| 	[[ $SUBSCWRYPT -eq 0 ]] || { | ||||
| 		case $SCWRYPTS_OUTPUT_FORMAT in | ||||
| 			pretty ) | ||||
| 				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 | ||||
| 	} | ||||
|  | ||||
| 	##################################################################### | ||||
| 	### run the scwrypt ################################################# | ||||
| 	##################################################################### | ||||
|  | ||||
| 	set -o pipefail | ||||
| 	{ | ||||
| 		[ $HEADER ] && echo $HEADER | ||||
| 		case $RUN_MODE in | ||||
| 			normal ) | ||||
| 				(eval "$RUN_STRING $(printf "%q " "$@")") | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 			no-logfile ) | ||||
| 				eval "$RUN_STRING $(printf "%q " "$@")" | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 			interactive ) | ||||
| 				eval "$RUN_STRING $(printf "%q " "$@")" </dev/tty >/dev/tty 2>&1 | ||||
| 				EXIT_CODE=$? | ||||
| 				;; | ||||
| 		esac | ||||
| 		[ $FOOTER ] && echo $FOOTER | ||||
| 		[[ $EXIT_CODE -eq 0 ]] && EXIT_COLOR='32m' || EXIT_COLOR='31m' | ||||
|  | ||||
| 		[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] && [ ! $SUBSCWRYPT ] \ | ||||
| 			&& echo "terminated with\\033[1;$EXIT_COLOR code $EXIT_CODE\\033[0m" | ||||
|  | ||||
| 		return $EXIT_CODE | ||||
| 	} | tee --append "$LOGFILE" | ||||
| } $@ | ||||
| source "${0:a:h}/run" $@ | ||||
|   | ||||
| @@ -1,223 +1,69 @@ | ||||
| # | ||||
| # 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 | ||||
| # source this file again | ||||
| # | ||||
| # 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() { | ||||
| 	local SCWRYPT_SELECTION=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS | FZF 'select a script' --header-lines 1) | ||||
| 	local NAME | ||||
| 	local TYPE | ||||
| 	local GROUP | ||||
| 	LBUFFER= RBUFFER= | ||||
| 	[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; } | ||||
| 
 | ||||
| : \ | ||||
| 	&& command -v scwrypts &>/dev/null \ | ||||
| 	&& eval "$(scwrypts --config)" \ | ||||
| 	|| { | ||||
| 		echo 'scwrypts must be in PATH and properly configured; skipping zsh plugin setup' >&2 | ||||
| 	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__GET_AVAILABLE_SCWRYPTS | FZF 'select a script' --header-lines 1) | ||||
| 	local NAME | ||||
| 	local TYPE | ||||
| 	local GROUP | ||||
| 	LBUFFER= RBUFFER= | ||||
| 	[ ! $SCWRYPT_SELECTION ] && { zle accept-line; return 0; } | ||||
| 
 | ||||
| 	SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION | ||||
| 
 | ||||
| 	scwrypts --name $NAME --group $GROUP --type $TYPE -- --help >&2 || { | ||||
| 		zle accept-line | ||||
| 		return 0 | ||||
| 	} | ||||
| 	echo | ||||
| 
 | ||||
| __SCWRYPTS_PARSE() { | ||||
| 	SCWRYPT_SELECTION=$(scwrypts --list | fzf --ansi --prompt 'select a script : ' --header-lines 1) | ||||
| 	LBUFFER= RBUFFER= | ||||
| 	[ $SCWRYPT_SELECTION ] || return 1 | ||||
| 	zle reset-prompt | ||||
| 	which scwrypts >/dev/null 2>&1\ | ||||
| 		&& LBUFFER="scwrypts" || LBUFFER="$SCWRYPTS_ROOT/scwrypts" | ||||
| 
 | ||||
| 	NAME=$(echo "$SCWRYPT_SELECTION" | awk '{print $1;}') | ||||
| 	TYPE=$(echo "$SCWRYPT_SELECTION" | awk '{print $2;}') | ||||
| 	GROUP=$(echo "$SCWRYPT_SELECTION" | awk '{print $3;}') | ||||
| 
 | ||||
| 	[ $NAME ] && [ $TYPE ] && [ $GROUP ] | ||||
| 	LBUFFER+=" --name $NAME --group $GROUP --type $TYPE -- " | ||||
| } | ||||
| 
 | ||||
| zle -N scwrypts-builder SCWRYPTS__ZSH_BUILDER_PLUGIN | ||||
| bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder | ||||
| 
 | ||||
| ##################################################################### | ||||
| SCWRYPTS__ZSH_PLUGIN_ENV() { | ||||
| 	local RESET='reset' | ||||
| 	local SELECTED=$(\ | ||||
| 		{ [ $SCWRYPTS_ENV ] && echo $RESET; SCWRYPTS__GET_ENV_NAMES; } \ | ||||
| 			| FZF 'select an environment' \ | ||||
| 	) | ||||
| 
 | ||||
| [ $SCWRYPTS_SHORTCUT ] && { | ||||
| 	SCWRYPTS__ZSH_PLUGIN() { | ||||
| 		local SCWRYPT_SELECTION NAME TYPE GROUP | ||||
| 		__SCWRYPTS_PARSE || { zle accept-line; return 0; } | ||||
| 
 | ||||
| 		RBUFFER="scwrypts --name $NAME --type $TYPE --group $GROUP" | ||||
| 		zle accept-line | ||||
| 	zle clear-command-line | ||||
| 	[ $SELECTED ] && { | ||||
| 		[[ $SELECTED =~ ^$RESET$ ]] \ | ||||
| 			&& RBUFFER='unset SCWRYPTS_ENV' \ | ||||
| 			|| RBUFFER="export SCWRYPTS_ENV=$SELECTED" | ||||
| 	} | ||||
| 
 | ||||
| 	zle -N scwrypts SCWRYPTS__ZSH_PLUGIN | ||||
| 	bindkey $SCWRYPTS_SHORTCUT scwrypts | ||||
| 	unset SCWRYPTS_SHORTCUT | ||||
| 	zle accept-line | ||||
| } | ||||
| 
 | ||||
| ##################################################################### | ||||
| 
 | ||||
| [ $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 | ||||
| zle -N scwrypts-setenv SCWRYPTS__ZSH_PLUGIN_ENV | ||||
| bindkey $SCWRYPTS_ENV_SHORTCUT scwrypts-setenv | ||||
|   | ||||
| @@ -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 | ||||
| @@ -27,9 +27,6 @@ EKS() { | ||||
| 
 | ||||
| 	local CONTEXT="arn:aws:eks:${AWS_REGION}:${AWS_ACCOUNT}:cluster/${CLUSTER_NAME}" | ||||
| 
 | ||||
| 	kubectl config get-contexts | grep -q $CONTEXT \ | ||||
| 		|| EKS__CLUSTER_LOGIN -c $CLUSTER_NAME >/dev/null | ||||
| 
 | ||||
| 	local CONTEXT_ARGS=() | ||||
| 	case $1 in | ||||
| 		helm ) CONTEXT_ARGS+=(--kube-context $CONTEXT) ;; | ||||
| @@ -55,7 +52,6 @@ EKS__CLUSTER_LOGIN() { | ||||
| 	" | ||||
| 	REQUIRED_ENV=(AWS_ACCOUNT AWS_REGION) CHECK_ENVIRONMENT || return 1 | ||||
| 
 | ||||
| 
 | ||||
| 	local CLUSTER_NAME | ||||
| 
 | ||||
| 	while [[ $# -gt 0 ]] | ||||
|   | ||||
							
								
								
									
										10
									
								
								zsh/lib/config.group.zsh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								zsh/lib/config.group.zsh
									
									
									
									
									
										Normal 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 | ||||
| @@ -1,31 +1,12 @@ | ||||
| [[ $__SCWRYPT -eq 1 ]] && return 0 | ||||
| ##################################################################### | ||||
| 
 | ||||
| # Apparently MacOS puts ALL of the homebrew stuff inside of a top level git repository | ||||
| # with bizarre git ignores; so: | ||||
| #  - 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="$(echo "${0:a:h}" | sed -n 's|\(share/scwrypts\).*$|\1|p')" | ||||
| 
 | ||||
| [ $SCWRYPTS_ROOT ] && [ -d "$SCWRYPTS_ROOT" ] || { | ||||
| 	echo "cannot determine scwrypts root path for current installation; aborting" | ||||
| 	exit 1 | ||||
| } | ||||
| 
 | ||||
| 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 \ | ||||
| 	; | ||||
| 
 | ||||
| [ ! $SCWRYPTS_ROOT ] \ | ||||
| 	&& SCWRYPTS_ROOT="$(cd $(dirname "${0:a:h}"); git rev-parse --show-toplevel)" | ||||
| 
 | ||||
| ##################################################################### | ||||
| 
 | ||||
| DEFAULT_CONFIG="$SCWRYPTS_ROOT__scwrypts/zsh/lib/config.user.zsh" | ||||
| DEFAULT_CONFIG="$SCWRYPTS_ROOT/zsh/lib/config.user.zsh" | ||||
| source "$DEFAULT_CONFIG" | ||||
| 
 | ||||
| USER_CONFIG_OVERRIDES="$SCWRYPTS_CONFIG_PATH/config.zsh" | ||||
| @@ -35,13 +16,11 @@ USER_CONFIG_OVERRIDES="$SCWRYPTS_CONFIG_PATH/config.zsh" | ||||
| } | ||||
| source "$USER_CONFIG_OVERRIDES" | ||||
| 
 | ||||
| mkdir -p \ | ||||
| 	"$SCWRYPTS_CONFIG_PATH" \ | ||||
| 	"$SCWRYPTS_DATA_PATH" \ | ||||
| 	"$SCWRYPTS_ENV_PATH" \ | ||||
| 	"$SCWRYPTS_LOG_PATH" \ | ||||
| 	"$SCWRYPTS_OUTPUT_PATH" \ | ||||
| 	; | ||||
| [ ! -d $SCWRYPTS_CONFIG_PATH ] && mkdir -p $SCWRYPTS_CONFIG_PATH | ||||
| [ ! -d $SCWRYPTS_DATA_PATH   ] && mkdir -p $SCWRYPTS_DATA_PATH | ||||
| [ ! -d $SCWRYPTS_ENV_PATH    ] && mkdir -p $SCWRYPTS_ENV_PATH | ||||
| [ ! -d $SCWRYPTS_LOG_PATH    ] && mkdir -p $SCWRYPTS_LOG_PATH | ||||
| [ ! -d $SCWRYPTS_OUTPUT_PATH ] && mkdir -p $SCWRYPTS_OUTPUT_PATH | ||||
| 
 | ||||
| export \ | ||||
| 	SCWRYPTS_GROUPS \ | ||||
| @@ -53,9 +32,11 @@ export \ | ||||
| 	SCWRYPTS_OUTPUT_PATH \ | ||||
| 	; | ||||
| 
 | ||||
| source "$SCWRYPTS_ROOT/scwrypts.scwrypts.zsh" \ | ||||
| 	|| FAIL 69 'failed to set up scwrypts group; aborting' | ||||
| SCWRYPTS_GROUPS+=(scwrypts) # 'scwrypts' group is required! | ||||
| SCWRYPTS_GROUPS=($(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u)) | ||||
| 
 | ||||
| source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \ | ||||
| 	|| FAIL 69 'failed to set up scwrypts group; aborting' | ||||
| 
 | ||||
| ##################################################################### | ||||
| 
 | ||||
| @@ -77,8 +58,7 @@ done | ||||
| 	&& [ ! "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" ] \ | ||||
| 	&& [ $GITHUB_WORKSPACE ] \ | ||||
| 	&& [ ! $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" ] && { | ||||
| 	for GROUP_LOADER in $(find "$SCWRYPTS_AUTODETECT_GROUP_BASEDIR" -type f -name \*scwrypts.zsh) | ||||
| @@ -88,8 +68,5 @@ done | ||||
| } | ||||
| 
 | ||||
| ##################################################################### | ||||
| 
 | ||||
| SCWRYPTS_GROUPS=(scwrypts $(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u | grep -v '^scwrypts$')) | ||||
| 
 | ||||
| ##################################################################### | ||||
| __SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt | ||||
| [ $NO_EXPORT_CONFIG ] || __SCWRYPT=1 # arbitrary; indicates currently inside a scwrypt | ||||
| true | ||||
|   | ||||
| @@ -34,7 +34,7 @@ source "${0:a:h}/config.zsh" | ||||
| 
 | ||||
| use() { | ||||
| 	local SCWRYPTS_LIBRARY SCWRYPTS_LIBRARY_ROOT SCWRYPTS_LIBRARY_GROUP | ||||
| 	local DEFER_ENVIRONMENT_CHECK=true | ||||
| 	local DEFER_ENVIRONMENT_CHECK=1 | ||||
| 
 | ||||
| 	while [[ $# -gt 0 ]] | ||||
| 	do | ||||
| @@ -49,8 +49,8 @@ use() { | ||||
| 				SCWRYPTS_LIBRARY_ROOT=$2 | ||||
| 				shift 1 | ||||
| 				;; | ||||
| 			-c | --check-environment ) | ||||
| 				DEFER_ENVIRONMENT_CHECK=false | ||||
| 			--check-environment ) | ||||
| 				DEFER_ENVIRONMENT_CHECK=0 | ||||
| 				;; | ||||
| 			* ) | ||||
| 				[ ! $SCWRYPTS_LIBRARY ] \ | ||||
| @@ -106,7 +106,7 @@ use() { | ||||
| 		return 1 | ||||
| 	} | ||||
| 
 | ||||
| 	[[ $DEFER_ENVIRONMENT_CHECK =~ false ]] && { | ||||
| 	[[ $DEFER_ENVIRONMENT_CHECK -eq 0 ]] && { | ||||
| 		CHECK_ENVIRONMENT || { | ||||
| 			((IMPORT_ERRORS+=1)) | ||||
| 			ERROR "import error for '$SCWRYPTS_LIBRARY_GROUP/$SCWRYPTS_LIBRARY'" | ||||
|   | ||||
| @@ -12,10 +12,7 @@ SCWRYPTS__RUN() {  # context wrapper to run scwrypts within scwrypts | ||||
| 	local EXIT_CODE=0 | ||||
| 	((SUBSCWRYPT+=1)) | ||||
| 
 | ||||
| 	SCWRYPTS_LOG_LEVEL=$SCWRYPTS_LOG_LEVEL \ | ||||
| 	SUBSCWRYPT=$SUBSCWRYPT \ | ||||
| 		$SCWRYPTS_ROOT__scwrypts/scwrypts $@ | ||||
| 
 | ||||
| 	SUBSCWRYPT=$SUBSCWRYPT $SCWRYPTS_ROOT/run $@ | ||||
| 	EXIT_CODE=$? | ||||
| 
 | ||||
| 	((SUBSCWRYPT-=1)) | ||||
|   | ||||
| @@ -12,7 +12,7 @@ SCWRYPTS__GET_AVAILABLE_SCWRYPTS() { | ||||
| 	local GROUP GROUP_PATH GROUP_COLOR LOOKUP_PIDS=() | ||||
| 	{ | ||||
| 	echo 'NAME^TYPE^GROUP' | ||||
| 	for GROUP in ${SCWRYPTS_GROUPS[@]} | ||||
| 	for GROUP in ${SCWRYPTS_GROUPS} | ||||
| 	do | ||||
| 		GROUP_PATH=$(eval echo '$SCWRYPTS_ROOT__'$GROUP) | ||||
| 		GROUP_COLOR=$(eval echo '$SCWRYPTS_COLOR__'$GROUP) | ||||
| @@ -94,7 +94,7 @@ SCWRYPTS__GET_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') | ||||
| 	[ -f $_VIRTUALENV ] && RUNSTRING="source $_VIRTUALENV; $RUNSTRING" | ||||
| @@ -119,27 +119,6 @@ SCWRYPTS__GET_RUNSTRING__zsh() { | ||||
| 		|| SCWRYPT_FILENAME="$GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \ | ||||
| 		; | ||||
| 
 | ||||
| 	SCWRYPTS__GET_RUNSTRING__zsh__generic "$SCWRYPT_FILENAME" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| SCWRYPTS__GET_RUNSTRING__zsh__generic() { | ||||
| 	# boilerplate to allow | ||||
| 	#    - multiflag splitting (e.g. -abc = -a -b -c) | ||||
| 	#    - help flag injection (e.g. -h | --help) | ||||
| 	#    - default USAGE definition (allows USAGE__options style usage definition) | ||||
| 	#    - required MAIN() function wrapping | ||||
| 	# | ||||
| 	# this is available automatically in SCWRYPTS_GROUP declaration contexts | ||||
| 	# (e.g. my-group.scwrypts.zsh) | ||||
| 	local ZSH_FILENAME="$1" | ||||
| 	[ $ZSH_FILENAME ] || { | ||||
| 		ERROR ' | ||||
| 			to use SCWRYPTS__GET_RUNSTRING__zsh__generic, you must provide a | ||||
| 			ZSH_FILENAME (arg $1) where the MAIN function is defined | ||||
| 			' | ||||
| 		return 1 | ||||
| 	} | ||||
| 	printf " | ||||
| 		source '$SCWRYPT_FILENAME' | ||||
| 		CHECK_ENVIRONMENT | ||||
| @@ -175,6 +154,22 @@ SCWRYPTS__GET_RUNSTRING__zsh__generic() { | ||||
| 			done | ||||
| 			MAIN \${MAIN_ARGS[@]} | ||||
| 		} " | ||||
| 
 | ||||
| 
 | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| SCWRYPTS__GET_RUNSTRING__zsh_v3() { | ||||
| 	WARNING "scwrypts zsh/v3 runstrings are now deprecated; please update to scwrypts v4 format" | ||||
| 
 | ||||
| 	__CHECK_DEPENDENCY zsh || return 1 | ||||
| 
 | ||||
| 	[ $(eval echo '$SCWRYPTS_TYPE__'$SCWRYPT_GROUP) ] \ | ||||
| 		&& echo "source $GROUP_PATH/$SCWRYPT_NAME" \ | ||||
| 		|| echo "source $GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \ | ||||
| 		; | ||||
| 
 | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| SCWRYPTS__GET_RUNSTRING__py() { | ||||
|   | ||||
| @@ -74,8 +74,6 @@ _VIRTUALENV__GET_PATH() { | ||||
| 	local ENV_PATH="$(eval echo '$SCWRYPTS_VIRTUALENV_PATH__'$GROUP 2>/dev/null)" | ||||
| 	[ ! $ENV_PATH ] && ENV_PATH="$SCWRYPTS_VIRTUALENV_PATH__scwrypts" | ||||
| 
 | ||||
| 	mkdir -p "$ENV_PATH/$TYPE" &>/dev/null | ||||
| 
 | ||||
| 	echo $ENV_PATH/$TYPE | ||||
| } | ||||
| 
 | ||||
| @@ -97,7 +95,7 @@ CREATE_VIRTUALENV__scwrypts__py() { | ||||
| 		} | ||||
| 	done | ||||
| 	[ ! $PYTHON ] && { | ||||
| 		ERROR 'python>=3.10 not available; skipping python env' | ||||
| 		ERROR 'python>=3.9 not available; skipping python env' | ||||
| 		return 1 | ||||
| 	} | ||||
| 
 | ||||
| @@ -124,7 +122,7 @@ UPDATE_VIRTUALENV__scwrypts__py() { | ||||
| 	PIP_INSTALL_ARGS+=(--no-cache-dir) | ||||
| 	PIP_INSTALL_ARGS+=(-r requirements.txt) | ||||
| 
 | ||||
| 	cd "$SCWRYPTS_ROOT__scwrypts/py" | ||||
| 	cd "$SCWRYPTS_ROOT/py" | ||||
| 	pip install ${PIP_INSTALL_ARGS[@]} | ||||
| } | ||||
| 
 | ||||
| @@ -161,9 +159,7 @@ ACTIVATE_VIRTUALENV__scwrypts__zx() { | ||||
| UPDATE_VIRTUALENV__scwrypts__zx() { | ||||
| 	local NPM_INSTALL_ARGS=() | ||||
| 
 | ||||
| 	[ $CI ] && NPM_INSTALL_ARGS+=(--ignore-scripts) | ||||
| 
 | ||||
| 	cd "$SCWRYPTS_ROOT__scwrypts/zx" | ||||
| 	cd "$SCWRYPTS_ROOT/zx" | ||||
| 	npm install ${NPM_INSTALL_ARGS[@]} | ||||
| } | ||||
| 
 | ||||
|   | ||||
| @@ -37,7 +37,7 @@ __CHECK_COREUTILS() { | ||||
| 	do | ||||
| 		__CHECK_DEPENDENCY $UTIL || { ((MISSING_DEPENDENCY_COUNT+=1)); continue; } | ||||
| 
 | ||||
| 		$UTIL --version 2>&1 | grep 'GNU' | grep -qv 'BSD' || { | ||||
| 		$UTIL --version 2>&1 | grep -q 'GNU' || { | ||||
| 			WARNING "non-GNU version of $UTIL detected" | ||||
| 			((NON_GNU_DEPENDENCY_COUNT+=1)) | ||||
| 		} | ||||
|   | ||||
| @@ -1,8 +1,5 @@ | ||||
| FZF() { | ||||
| 	[ $CI ] && { | ||||
| 		DEBUG "invoked FZF with $@" | ||||
| 		FAIL 1 'currently in CI, but FZF requires user input' | ||||
| 	} | ||||
| 	[ $CI ] && FAIL 1 'currently in CI, but FZF requires user input' | ||||
| 
 | ||||
| 	local FZF_ARGS=() | ||||
| 
 | ||||
| @@ -43,3 +40,18 @@ FZF_USER_INPUT() { # allow user to type custom answers; reconfirm if ambiguous w | ||||
| 	echo $FZF_OUTPUT | ||||
| 	[ $FZF_OUTPUT ] | ||||
| } | ||||
| 
 | ||||
| ##################################################################### | ||||
| ### vvv DEPRECATED vvv ############################################## | ||||
| ##################################################################### | ||||
| 
 | ||||
| FZF_HEAD() {  # prefer user input over selected | ||||
| 	WARNING 'FZF_HEAD is deprecated and will be unavailable in v4.2; please switch to FZF_USER_INPUT (drop-in fix!)' | ||||
| 	FZF $@ --print-query | sed '/^$/d' | head -n1; | ||||
| } | ||||
| FZF_TAIL() {  # prefer selected over user input | ||||
| 	WARNING 'FZF_TAIL is deprecated and will be unavailable in v4.2; please switch to FZF_USER_INPUT (drop-in fix!)' | ||||
| 	FZF $@ --print-query | sed '/^$/d' | tail -n1; | ||||
| } | ||||
| 
 | ||||
| ##################################################################### | ||||
|   | ||||
| @@ -5,61 +5,34 @@ PRINT() { | ||||
| 	local STDOUT=0 | ||||
| 
 | ||||
| 	local LTRIM=1 | ||||
| 	local FORMAT=$SCWRYPTS_OUTPUT_FORMAT | ||||
| 	local _S | ||||
| 	while [[ $# -gt 0 ]] | ||||
| 	do | ||||
| 		_S=1 | ||||
| 		case $1 in | ||||
| 			-n | --no-trim-tabs ) LTRIM=0 ;; | ||||
| 			-x | --no-line-end  ) LAST_LINE_END='' ;; | ||||
| 			-o | --use-stdout   ) STDOUT=1; STDERR=0 ;; | ||||
| 
 | ||||
| 			-f | --format ) ((_S+=1)); FORMAT=$2 ;; | ||||
| 
 | ||||
| 			* ) MESSAGE+="$(echo $1) " ;; | ||||
| 		esac | ||||
| 		shift $_S | ||||
| 		shift 1 | ||||
| 	done | ||||
| 
 | ||||
| 	[ $FORMAT ] || FORMAT=pretty | ||||
| 	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' | ||||
| 	MESSAGE="$(echo "$MESSAGE" | sed 's/%/%%/g')" | ||||
| 
 | ||||
| 					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') | ||||
| 				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 | ||||
| 			printf "${PREFIX} : $(echo "$line" | sed 's/^	\+//; s/ \+$//')" | ||||
| 
 | ||||
| 			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 | ||||
| 	[[ $STDOUT -eq 1 ]] && printf -- "$STYLED_MESSAGE" | ||||
| 	[[ $STDERR -eq 1 ]] && printf $STYLED_MESSAGE >&2 | ||||
| 	[[ $STDOUT -eq 1 ]] && printf $STYLED_MESSAGE | ||||
| 
 | ||||
| 	return 0 | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,6 @@ source "${0:a:h}/io.print.zsh" | ||||
| [ ! $ERRORS ] && ERRORS=0 | ||||
| 
 | ||||
| ERROR() {  # command encountered an error | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||
| 		&& PREFIX="ERROR    ✖" COLOR=$__RED            PRINT "$@" | ||||
| 	((ERRORS+=1)) | ||||
| @@ -14,47 +13,35 @@ ERROR() {  # command encountered an error | ||||
| } | ||||
| 
 | ||||
| SUCCESS() {  # command completed successfully | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||
| 		&& PREFIX="SUCCESS  ✔" COLOR=$__GREEN          PRINT "$@" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| REMINDER() {  # include sysadmin reminder or other important notice to users | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||
| 		&& PREFIX="REMINDER " COLOR=$__BRIGHT_MAGENTA PRINT "$@" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| STATUS() {  # general status updates (prefer this to generic 'echo') | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] \ | ||||
| 		&& PREFIX="STATUS    " COLOR=$__BLUE           PRINT "$@" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| WARNING() {  # warning-level messages; not errors | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 3 ]] \ | ||||
| 		&& PREFIX="WARNING  " COLOR=$__YELLOW         PRINT "$@" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| DEBUG() {  # helpful during development or (sparingly) to help others' development | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 4 ]] \ | ||||
| 		&& PREFIX="DEBUG    ℹ" COLOR=$__WHITE          PRINT "$@" | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| PROMPT() {  # you probably want to use yN or INPUT from below | ||||
| 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||
| 		&& PREFIX="PROMPT   " COLOR=$__CYAN PRINT "$@" \ | ||||
| 		&& PREFIX="USER     ⌨" COLOR=$__BRIGHT_CYAN PRINT '' --no-line-end \ | ||||
| 		; | ||||
| 	return 0 | ||||
| } | ||||
| 
 | ||||
| FAIL()  { SCWRYPTS_LOG_LEVEL=1 ERROR "${@:2}"; exit $1; } | ||||
| @@ -224,21 +211,15 @@ READ_YN() {  # yes/no read is suprisingly tricky | ||||
| 	local yn | ||||
| 	PROMPT "${USERPROMPT[@]}" | ||||
| 
 | ||||
| 	local PERFORM_FAKE_PROMPT=false | ||||
| 	case $SKIP_USER_INPUT in | ||||
| 		true ) yn=y ;; | ||||
| 		false ) | ||||
| 			[[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] && { | ||||
| 				[[ $FORCE_USER_INPUT =~ false ]] && [ ! -t 0 ] \ | ||||
| 					|| PERFORM_FAKE_PROMPT=true | ||||
| 			} | ||||
| 
 | ||||
| 			[[ $PERFORM_FAKE_PROMPT =~ true ]] \ | ||||
| 			[[ $FORCE_USER_INPUT =~ true ]] && [[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] \ | ||||
| 				&& echo -n "${USERPROMPT[@]} : " >&2 | ||||
| 
 | ||||
| 			READ ${READ_ARGS[@]} -s -k yn | ||||
| 
 | ||||
| 			[[ $PERFORM_FAKE_PROMPT =~ true ]] \ | ||||
| 			[[ $FORCE_USER_INPUT =~ true ]] && [[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] \ | ||||
| 				&& echo $yn >&2 | ||||
| 			;; | ||||
| 	esac | ||||
|   | ||||
| @@ -72,7 +72,7 @@ CHECK_ENVIRONMENT() { | ||||
| 		$E "environment errors found (see above)\n$ERROR_MESSAGE" | ||||
| 	} | ||||
| 
 | ||||
| 	[[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && [[ $__SCWRYPT ]] && { | ||||
| 	[[ $MISSING_ENVIRONMENT_VARIABLES -ne 0 ]] && { | ||||
| 		REMINDER " | ||||
| 			to quickly update missing environment variables, run: | ||||
| 			'scwrypts zsh/scwrypts/environment/edit' | ||||
|   | ||||
							
								
								
									
										6
									
								
								zx/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								zx/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -31,7 +31,6 @@ | ||||
|         "prettier": "^3.2.5", | ||||
|         "ts-jest": "^29.1.2", | ||||
|         "ts-node": "^10.9.2", | ||||
|         "typescript": "^5.3.3", | ||||
|         "uuid": "^9.0.1" | ||||
|       } | ||||
|     }, | ||||
| @@ -4998,6 +4997,7 @@ | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", | ||||
|       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", | ||||
|       "dev": true, | ||||
|       "peer": true, | ||||
|       "bin": { | ||||
|         "tsc": "bin/tsc", | ||||
|         "tsserver": "bin/tsserver" | ||||
| @@ -8596,7 +8596,6 @@ | ||||
|         "prettier": "^3.2.5", | ||||
|         "ts-jest": "^29.1.2", | ||||
|         "ts-node": "^10.9.2", | ||||
|         "typescript": "^5.3.3", | ||||
|         "uuid": "^9.0.1" | ||||
|       } | ||||
|     }, | ||||
| @@ -8885,7 +8884,8 @@ | ||||
|       "version": "5.3.3", | ||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", | ||||
|       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", | ||||
|       "dev": true | ||||
|       "dev": true, | ||||
|       "peer": true | ||||
|     }, | ||||
|     "undici-types": { | ||||
|       "version": "5.26.5", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user