Compare commits
	
		
			21 Commits
		
	
	
		
			v4.0.7
			...
			41da641ab9
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 41da641ab9 | |||
| 6ba628f80e | |||
| 1f10268aa0 | |||
| aefd575539 | |||
| 26992d2f01 | |||
| 487fa65d38 | |||
| 3ff44f8e58 | |||
| f0a6b16a0c | |||
| 74fe48cc4a | |||
| 6fe5b8e26a | |||
| 3d1eb9e03d | |||
| bd554f1460 | |||
| 768bd1444e | |||
| 4ccb79f1e4 | |||
| 6b15491066 | |||
| 8427ad40f0 | |||
| 1d3eb77235 | |||
| 406ee85d46 | |||
| 7709c7e3db | |||
| 8d3e6ae46f | |||
| fec8a7ec94 | 
| @@ -4,7 +4,14 @@ version: 2.1 | |||||||
| orbs: | orbs: | ||||||
|   python: circleci/python@2.1.1 |   python: circleci/python@2.1.1 | ||||||
|  |  | ||||||
|  |  | ||||||
| executors: | executors: | ||||||
|  |   archlinux: | ||||||
|  |     docker: | ||||||
|  |       - image: archlinux:base-devel | ||||||
|  |     resource_class: small | ||||||
|  |     working_directory: / | ||||||
|  |  | ||||||
|   python: |   python: | ||||||
|     docker: |     docker: | ||||||
|       - image: cimg/python:3.11 |       - image: cimg/python:3.11 | ||||||
| @@ -16,30 +23,124 @@ executors: | |||||||
|     resource_class: medium |     resource_class: medium | ||||||
|  |  | ||||||
|  |  | ||||||
| jobs: | commands: | ||||||
|   python-test: |   archlinux-run: | ||||||
|     executor: python |     description: execute command steps in the archlinux container from the CI user | ||||||
|     working_directory: ~/scwrypts/py/lib |     parameters: | ||||||
|  |       _name: | ||||||
|  |         type: string | ||||||
|  |       command: | ||||||
|  |         type: string | ||||||
|  |       working_directory: | ||||||
|  |         type: string | ||||||
|  |         default: /home/ci | ||||||
|     steps: |     steps: | ||||||
|       - checkout: |  | ||||||
|           path: ~/scwrypts |  | ||||||
|       - run: |       - run: | ||||||
|           name: pytest |           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 | ||||||
|  |  | ||||||
|  |     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: | ||||||
|  |     executor: python | ||||||
|  |     steps: | ||||||
|  |       - run: | ||||||
|  |           name: check CIRCLE_TAG for full semantic version | ||||||
|           command: | |           command: | | ||||||
|             : \ |             : \ | ||||||
|               && pip install . .[test] \ |                 && [ $CIRCLE_TAG ] \ | ||||||
|               && pytest \ |                 && [[ $CIRCLE_TAG =~ ^v[0-9]*.[0-9]*.[0-9]*$ ]] \ | ||||||
|               ; |                 ; | ||||||
|       - run: pip install build && python -m build |  | ||||||
|  |  | ||||||
|   python-publish: |   aur-test: | ||||||
|     executor: python |     executor: archlinux | ||||||
|     working_directory: ~/scwrypts/py/lib |  | ||||||
|     steps: |     steps: | ||||||
|       - checkout: |       - *archlinux-prepare | ||||||
|           path: ~/scwrypts |       - *archlinux-clone-aur | ||||||
|       - run: pip install build && python -m build |       - *archlinux-clone-scwrypts | ||||||
|       - run: pip install twine && twine upload dist/* |       - 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 | ||||||
|  |             && scwrypts --version | grep "^scwrypts v$PKGVER$" | ||||||
|  |             ; | ||||||
|  |  | ||||||
|  |   aur-publish: | ||||||
|  |     executor: archlinux | ||||||
|  |     steps: | ||||||
|  |       - *archlinux-prepare | ||||||
|  |       - *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 | ||||||
|  |             ; | ||||||
|  |  | ||||||
|   nodejs-test: |   nodejs-test: | ||||||
|     executor: nodejs |     executor: nodejs | ||||||
| @@ -108,51 +209,83 @@ jobs: | |||||||
|               && pnpm publish --no-git-checks \ |               && 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: | workflows: | ||||||
|   python-dev: |   test: | ||||||
|     jobs: |     jobs: | ||||||
|       - python-test: |       - aur-test: | ||||||
|  |           &dev-filters | ||||||
|           filters: |           filters: | ||||||
|             branches: |             branches: | ||||||
|               ignore: /^main$/ |               ignore: /^main$/ | ||||||
|  |  | ||||||
|   python: |       - python-test: *dev-filters | ||||||
|  |       - nodejs-test: *dev-filters | ||||||
|  |  | ||||||
|  |   publish: | ||||||
|     jobs: |     jobs: | ||||||
|       - python-test: |       - require-full-semver: | ||||||
|           filters: |           filters: | ||||||
|  |             &only-run-on-full-semver-tag-filters | ||||||
|             tags: |             tags: | ||||||
|               only: /^v\d+\.\d+\.\d+.*$/ |               only: /^v\d+\.\d+\.\d+.*$/ | ||||||
|             branches: |             branches: | ||||||
|               ignore: /^.*$/ |               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: |       - python-publish: | ||||||
|           requires: [python-test] |           filters: *only-run-on-full-semver-tag-filters | ||||||
|           context: [pypi-yage] |           context: [pypi-yage] | ||||||
|           filters: |           requires: | ||||||
|             tags: |             - python-test | ||||||
|               only: /^v\d+\.\d+\.\d+.*$/ |  | ||||||
|             branches: |  | ||||||
|               ignore: /^.*$/ |  | ||||||
|  |  | ||||||
|   nodejs-dev: |       - nodejs-test: *only-publish-for-full-semver | ||||||
|     jobs: |  | ||||||
|       - nodejs-test: |  | ||||||
|           filters: |  | ||||||
|             branches: |  | ||||||
|               ignore: /^main$/ |  | ||||||
|  |  | ||||||
|   nodejs: |  | ||||||
|     jobs: |  | ||||||
|       - nodejs-test: |  | ||||||
|           filters: |  | ||||||
|             tags: |  | ||||||
|               only: /^v\d+\.\d+\.\d+.*$/ |  | ||||||
|             branches: |  | ||||||
|               ignore: /^.*$/ |  | ||||||
|       - nodejs-publish: |       - nodejs-publish: | ||||||
|           requires: [nodejs-test] |           filters: *only-run-on-full-semver-tag-filters | ||||||
|           context: [npm-wrynegade] |           context: [npm-wrynegade] | ||||||
|           filters: |           requires: | ||||||
|             tags: |             - nodejs-test | ||||||
|               only: /^v\d+\.\d+\.\d+.*$/ |  | ||||||
|             branches: |  | ||||||
|               ignore: /^.*$/ |  | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								.github/workflows/automatic-release.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								.github/workflows/automatic-release.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  | --- | ||||||
|  | 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,6 +29,7 @@ runs: | |||||||
|         repository: wrynegade/scwrypts |         repository: wrynegade/scwrypts | ||||||
|         path: ./wrynegade/scwrypts |         path: ./wrynegade/scwrypts | ||||||
|         ref: ${{ inputs.version }} |         ref: ${{ inputs.version }} | ||||||
|  |         fetch-tags: true | ||||||
|  |  | ||||||
|     - name: check dependencies |     - name: check dependencies | ||||||
|       shell: bash |       shell: bash | ||||||
| @@ -51,12 +52,11 @@ runs: | |||||||
|         } > $HOME/.scwrypts.apt-get.log 2>&1 |         } > $HOME/.scwrypts.apt-get.log 2>&1 | ||||||
|  |  | ||||||
|         echo "updating virtual dependencies" |         echo "updating virtual dependencies" | ||||||
|         $GITHUB_WORKSPACE/wrynegade/scwrypts/scwrypts -n \ |         $GITHUB_WORKSPACE/wrynegade/scwrypts/scwrypts \ | ||||||
|           --name scwrypts/virtualenv/update-all \ |           --name scwrypts/virtualenv/update-all \ | ||||||
|           --group scwrypts \ |           --group scwrypts \ | ||||||
|           --type zsh \ |           --type zsh \ | ||||||
|           ; |           > $HOME/.scwrypts.virtualenv.log 2>&1 | ||||||
|           #> $HOME/.scwrypts.virtualenv.log 2>&1 |  | ||||||
|  |  | ||||||
|         echo "CI_SCWRYPTS_READY=1" >> $GITHUB_ENV |         echo "CI_SCWRYPTS_READY=1" >> $GITHUB_ENV | ||||||
|         exit 0 |         exit 0 | ||||||
|   | |||||||
| @@ -171,7 +171,7 @@ _SCWRYPTS_KUBECTL_DRIVER() { | |||||||
| 
 | 
 | ||||||
| 			[ $NAMESPACE ] && CLI_ARGS+=(--namespace $NAMESPACE) | 			[ $NAMESPACE ] && CLI_ARGS+=(--namespace $NAMESPACE) | ||||||
| 			[[ $VERBOSE -eq 1 ]] && { | 			[[ $VERBOSE -eq 1 ]] && { | ||||||
| 				INFO " | 				REMINDER " | ||||||
| 					context '$CONTEXT' | 					context '$CONTEXT' | ||||||
| 					namespace '$NAMESPACE' | 					namespace '$NAMESPACE' | ||||||
| 					environment '$SCWRYPTS_ENV' | 					environment '$SCWRYPTS_ENV' | ||||||
| @@ -180,7 +180,7 @@ _SCWRYPTS_KUBECTL_DRIVER() { | |||||||
| 				STATUS "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | 				STATUS "running $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | ||||||
| 			} || { | 			} || { | ||||||
| 				[[ $(_SCWRYPTS_KUBECTL_SETTINGS get context) =~ ^show$ ]] && { | 				[[ $(_SCWRYPTS_KUBECTL_SETTINGS get context) =~ ^show$ ]] && { | ||||||
| 					INFO "$SCWRYPTS_ENV.$SUBSESSION : $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | 					REMINDER "$SCWRYPTS_ENV.$SUBSESSION : $CLI ${CLI_ARGS[@]} ${USER_ARGS[@]}" | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			$CLI ${CLI_ARGS[@]} ${USER_ARGS[@]} | 			$CLI ${CLI_ARGS[@]} ${USER_ARGS[@]} | ||||||
|   | |||||||
| @@ -112,8 +112,8 @@ KUBECTL__SERVE() { | |||||||
| 	SERVICE_PASSWORD="$(KUBECTL__GET_SERVICE_PASSWORD)" | 	SERVICE_PASSWORD="$(KUBECTL__GET_SERVICE_PASSWORD)" | ||||||
| 	KUBECTL__SERVICE_PARSE | 	KUBECTL__SERVICE_PARSE | ||||||
| 
 | 
 | ||||||
| 	INFO "attempting to serve ${NAMESPACE}/${SERVICE_NAME}:${SERVICE_PORT}" | 	REMINDER "attempting to serve ${NAMESPACE}/${SERVICE_NAME}:${SERVICE_PORT}" | ||||||
| 	[ $SERVICE_PASSWORD ] && INFO "password : $SERVICE_PASSWORD" | 	[ $SERVICE_PASSWORD ] && REMINDER "password : $SERVICE_PASSWORD" | ||||||
| 
 | 
 | ||||||
| 	KUBECTL port-forward service/$SERVICE_NAME $SERVICE_PORT | 	KUBECTL port-forward service/$SERVICE_NAME $SERVICE_PORT | ||||||
| } | } | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ class MissingFlagAndEnvironmentVariableError(EnvironmentError, ArgumentError): | |||||||
|  |  | ||||||
| class MissingScwryptsExecutableError(EnvironmentError): | class MissingScwryptsExecutableError(EnvironmentError): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         super().__init__(f'scwrypts must be installed and available on your PATH') |         super().__init__('scwrypts must be installed and available on your PATH') | ||||||
|  |  | ||||||
|  |  | ||||||
| class BadScwryptsLookupError(ValueError): | class BadScwryptsLookupError(ValueError): | ||||||
|   | |||||||
| @@ -5,44 +5,54 @@ from subprocess import run | |||||||
| from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError | from .exceptions import MissingScwryptsExecutableError, BadScwryptsLookupError, MissingScwryptsGroupOrTypeError | ||||||
|  |  | ||||||
|  |  | ||||||
| def scwrypts(*args, patterns=None, name=None, group=None, _type=None, log_level=None): | def scwrypts(patterns=None, args=None, executable_args=None, name=None, group=None, _type=None): | ||||||
|     ''' |     ''' | ||||||
|     top-level scwrypts invoker from python |     top-level scwrypts invoker from python | ||||||
|  |  | ||||||
|     - patterns allows for pattern-based scwrypt lookup |         patterns          str / list   pattern-based scwrypt lookup | ||||||
|     - name/group/type allos for precise-match 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) | ||||||
|  |  | ||||||
|     *args should be a list of strings and is forwarded to the |         name    str   exact scwrypt lookup name (requires group and _type) | ||||||
|     invoked scwrypt |         group   str   exact scwrypt lookup group | ||||||
|  |         _type   str   exact scwrypt lookup type | ||||||
|  |  | ||||||
|  |         SCWRYPTS_EXECUTABLE   configuration variable which defines the full path to scwrypts executable | ||||||
|  |  | ||||||
|     see 'scwrypts --help' for more information |     see 'scwrypts --help' for more information | ||||||
|     ''' |     ''' | ||||||
|     executable = which('scwrypts') |  | ||||||
|     if executable is None: |  | ||||||
|         raise MissingScwryptsExecutableError() |  | ||||||
|  |  | ||||||
|     if patterns is None and name is None: |     if patterns is None and name is None: | ||||||
|         raise BadScwryptsLookupError() |         raise BadScwryptsLookupError() | ||||||
|  |  | ||||||
|     pre_args = [] |     if name is not None and (group is None or _type is None): | ||||||
|  |         raise MissingScwryptsGroupOrTypeError(group, _type) | ||||||
|  |  | ||||||
|     if name is None: |     executable = which(getenv('SCWRYPTS_EXECUTABLE', 'scwrypts')) | ||||||
|         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: |     if executable is None: | ||||||
|         pre_args += ['--log-level', log_level] |         raise MissingScwryptsExecutableError() | ||||||
|  |  | ||||||
|  |     lookup = _parse(patterns) if name is None else f'--name {name} --group {group} --type {_type}' | ||||||
|  |  | ||||||
|     depth = getenv('SUBSCWRYPT', '') |     depth = getenv('SUBSCWRYPT', '') | ||||||
|     if depth != '': |     if depth != '': | ||||||
|         depth = int(depth) + 1 |         depth = int(depth) + 1 | ||||||
|  |  | ||||||
|     return run( |     return run( | ||||||
|         f'SUBSCWRYPT={depth} {executable} {" ".join(pre_args)} -- {" ".join(args)}', |         f'SUBSCWRYPT={depth} {executable} {_parse(executable_args)} {lookup} -- {_parse(args)}', | ||||||
|         shell=True, |         shell=True, | ||||||
|         executable='/bin/zsh', |         executable='/bin/zsh', | ||||||
|         check=False, |         check=False, | ||||||
|  |         capture_output=True, | ||||||
|  |         text=True, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  | def _parse(string_or_list_args): | ||||||
|  |     if string_or_list_args is None: | ||||||
|  |         return '' | ||||||
|  |  | ||||||
|  |     if isinstance(string_or_list_args, list): | ||||||
|  |         return ' '.join(string_or_list_args) | ||||||
|  |  | ||||||
|  |     return str(string_or_list_args) | ||||||
|   | |||||||
							
								
								
									
										184
									
								
								py/lib/scwrypts/scwrypts/test_scwrypts.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								py/lib/scwrypts/scwrypts/test_scwrypts.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | |||||||
|  | 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', |         'generate', | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
| from .generate import generate | from .generate import generate, get_generator | ||||||
|  |  | ||||||
| from .character_set import * | from .character_set import * | ||||||
|   | |||||||
| @@ -45,6 +45,21 @@ DEFAULT_OPTIONS = { | |||||||
|         'requests_response_status_code': status_codes.codes[200], |         'requests_response_status_code': status_codes.codes[200], | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | def get_generator(default_options=None): | ||||||
|  |     if default_options is None: | ||||||
|  |         default_options = {} | ||||||
|  |  | ||||||
|  |     def generator_function(data_type=None, options_overrides=None): | ||||||
|  |         if options_overrides is None: | ||||||
|  |             options_overrides = {} | ||||||
|  |  | ||||||
|  |         return generate( | ||||||
|  |                 data_type = data_type, | ||||||
|  |                 options = default_options | options_overrides, | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |     return generator_function | ||||||
|  |  | ||||||
| def generate(data_type=None, options=None): | def generate(data_type=None, options=None): | ||||||
|     ''' |     ''' | ||||||
|     generate random data with the call of a function |     generate random data with the call of a function | ||||||
|   | |||||||
							
								
								
									
										388
									
								
								run
									
									
									
									
									
								
							
							
						
						
									
										388
									
								
								run
									
									
									
									
									
								
							| @@ -1,388 +0,0 @@ | |||||||
| #!/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" |  | ||||||
|  |  | ||||||
| } $@ |  | ||||||
							
								
								
									
										425
									
								
								scwrypts
									
									
									
									
									
								
							
							
						
						
									
										425
									
								
								scwrypts
									
									
									
									
									
								
							| @@ -1,2 +1,425 @@ | |||||||
| #!/bin/zsh | #!/bin/zsh | ||||||
| source "${0:a:h}/run" $@ | export EXECUTION_DIR=$(pwd) | ||||||
|  | source "$(dirname $(readlink -f "$0"))/zsh/lib/import.driver.zsh" || exit 42 | ||||||
|  | ##################################################################### | ||||||
|  | () { | ||||||
|  | 	cd "$SCWRYPTS_ROOT__scwrypts" | ||||||
|  | 	GIT_SCWRYPTS() { git -C "$SCWRYPTS_ROOT__scwrypts" $@; } | ||||||
|  |  | ||||||
|  | 	local INSTALLATION_TYPE | ||||||
|  | 	[ ! -d "$SCWRYPTS_ROOT__scwrypts/.git" ] && [ ! -f "$SCWRYPTS_ROOT__scwrypts/.git" ] \ | ||||||
|  | 		&& INSTALLATION_TYPE=$(cat "$SCWRYPTS_ROOT__scwrypts/MANAGED_BY" 2>/dev/null) \ | ||||||
|  | 		|| INSTALLATION_TYPE=manual \ | ||||||
|  | 		; | ||||||
|  |  | ||||||
|  | 	local ERRORS=0 | ||||||
|  | 	local 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 | ||||||
|  |  | ||||||
|  | 		  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=3 | ||||||
|  |  | ||||||
|  | 	while [[ $# -gt 0 ]] | ||||||
|  | 	do | ||||||
|  | 		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 | ||||||
|  | 				;; | ||||||
|  |  | ||||||
|  | 			--version ) | ||||||
|  | 				case $INSTALLATION_TYPE in | ||||||
|  | 					manual ) echo "scwrypts $(GIT_SCWRYPTS describe --tags) (via GIT)" ;; | ||||||
|  | 					     * ) echo scwrypts $(cat "$SCWRYPTS_ROOT__scwrypts/VERSION")   ;; | ||||||
|  | 				esac | ||||||
|  | 				return 0 | ||||||
|  | 				;; | ||||||
|  |  | ||||||
|  | 			--update ) | ||||||
|  | 				case $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') | ||||||
|  | 							 " | ||||||
|  | 						;; | ||||||
|  |  | ||||||
|  | 					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 ) | ||||||
|  | 				[ $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_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) | ||||||
|  |  | ||||||
|  | 		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 ] && export SUBSCWRYPT=0 | ||||||
|  |  | ||||||
|  | 	[[ $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 ]] && { | ||||||
|  | 		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 -eq 0 ]] || { | ||||||
|  | 		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 ################################################# | ||||||
|  | 	##################################################################### | ||||||
|  |  | ||||||
|  | 	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" | ||||||
|  | } $@ | ||||||
|   | |||||||
| @@ -1,8 +1,16 @@ | |||||||
|  | ##################################################################### | ||||||
|  | 
 | ||||||
|  | command -v scwrypts &>/dev/null || { | ||||||
|  | 	echo 'scwrypts is required in your PATH in order to use the zsh plugins; skipping' >&2 | ||||||
|  | 	return 0 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| NO_EXPORT_CONFIG=1 source "${0:a:h}/zsh/lib/import.driver.zsh" || return 42 | NO_EXPORT_CONFIG=1 source "${0:a:h}/zsh/lib/import.driver.zsh" || return 42 | ||||||
| 
 | 
 | ||||||
| ##################################################################### | ##################################################################### | ||||||
|  | 
 | ||||||
| SCWRYPTS__ZSH_PLUGIN() { | SCWRYPTS__ZSH_PLUGIN() { | ||||||
| 	local SCWRYPT_SELECTION=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS | FZF 'select a script' --header-lines 1) | 	local SCWRYPT_SELECTION=$(scwrypts --list | FZF 'select a script' --header-lines 1) | ||||||
| 	local NAME | 	local NAME | ||||||
| 	local TYPE | 	local TYPE | ||||||
| 	local GROUP | 	local GROUP | ||||||
| @@ -22,8 +30,10 @@ zle -N scwrypts SCWRYPTS__ZSH_PLUGIN | |||||||
| bindkey $SCWRYPTS_SHORTCUT scwrypts | bindkey $SCWRYPTS_SHORTCUT scwrypts | ||||||
| 
 | 
 | ||||||
| ##################################################################### | ##################################################################### | ||||||
|  | 
 | ||||||
| SCWRYPTS__ZSH_BUILDER_PLUGIN() { | SCWRYPTS__ZSH_BUILDER_PLUGIN() { | ||||||
| 	local SCWRYPT_SELECTION=$(SCWRYPTS__GET_AVAILABLE_SCWRYPTS | FZF 'select a script' --header-lines 1) | 	local SCWRYPT_SELECTION=$(scwrypts --list  | FZF 'select a script' --header-lines 1) | ||||||
|  | 	echo $SCWRYPT_SELECTION >&2 | ||||||
| 	local NAME | 	local NAME | ||||||
| 	local TYPE | 	local TYPE | ||||||
| 	local GROUP | 	local GROUP | ||||||
| @@ -32,7 +42,7 @@ SCWRYPTS__ZSH_BUILDER_PLUGIN() { | |||||||
| 
 | 
 | ||||||
| 	SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION | 	SCWRYPTS__SEPARATE_SCWRYPT_SELECTION $SCWRYPT_SELECTION | ||||||
| 
 | 
 | ||||||
| 	scwrypts --name $NAME --group $GROUP --type $TYPE -- --help >&2 || { | 	scwrypts -n --name $NAME --group $GROUP --type $TYPE -- --help >&2 || { | ||||||
| 		zle accept-line | 		zle accept-line | ||||||
| 		return 0 | 		return 0 | ||||||
| 	} | 	} | ||||||
| @@ -49,6 +59,7 @@ zle -N scwrypts-builder SCWRYPTS__ZSH_BUILDER_PLUGIN | |||||||
| bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder | bindkey $SCWRYPTS_BUILDER_SHORTCUT scwrypts-builder | ||||||
| 
 | 
 | ||||||
| ##################################################################### | ##################################################################### | ||||||
|  | 
 | ||||||
| SCWRYPTS__ZSH_PLUGIN_ENV() { | SCWRYPTS__ZSH_PLUGIN_ENV() { | ||||||
| 	local RESET='reset' | 	local RESET='reset' | ||||||
| 	local SELECTED=$(\ | 	local SELECTED=$(\ | ||||||
|   | |||||||
| @@ -27,6 +27,9 @@ EKS() { | |||||||
| 
 | 
 | ||||||
| 	local CONTEXT="arn:aws:eks:${AWS_REGION}:${AWS_ACCOUNT}:cluster/${CLUSTER_NAME}" | 	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=() | 	local CONTEXT_ARGS=() | ||||||
| 	case $1 in | 	case $1 in | ||||||
| 		helm ) CONTEXT_ARGS+=(--kube-context $CONTEXT) ;; | 		helm ) CONTEXT_ARGS+=(--kube-context $CONTEXT) ;; | ||||||
| @@ -52,6 +55,7 @@ EKS__CLUSTER_LOGIN() { | |||||||
| 	" | 	" | ||||||
| 	REQUIRED_ENV=(AWS_ACCOUNT AWS_REGION) CHECK_ENVIRONMENT || return 1 | 	REQUIRED_ENV=(AWS_ACCOUNT AWS_REGION) CHECK_ENVIRONMENT || return 1 | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| 	local CLUSTER_NAME | 	local CLUSTER_NAME | ||||||
| 
 | 
 | ||||||
| 	while [[ $# -gt 0 ]] | 	while [[ $# -gt 0 ]] | ||||||
|   | |||||||
| @@ -2,7 +2,12 @@ | |||||||
| ##################################################################### | ##################################################################### | ||||||
| 
 | 
 | ||||||
| [ ! $SCWRYPTS_ROOT ] \ | [ ! $SCWRYPTS_ROOT ] \ | ||||||
| 	&& SCWRYPTS_ROOT="$(cd $(dirname "${0:a:h}"); git rev-parse --show-toplevel)" | 	&& SCWRYPTS_ROOT="$(cd $(dirname "${0:a:h}"); git rev-parse --show-toplevel 2>/dev/null)" | ||||||
|  | 
 | ||||||
|  | [ ! $SCWRYPTS_ROOT ] && [ -d /usr/share/scwrypts ] \ | ||||||
|  | 	&& SCWRYPTS_ROOT=/usr/share/scwrypts | ||||||
|  | 
 | ||||||
|  | export SCWRYPTS_ROOT__scwrypts="$SCWRYPTS_ROOT" | ||||||
| 
 | 
 | ||||||
| ##################################################################### | ##################################################################### | ||||||
| 
 | 
 | ||||||
| @@ -32,8 +37,7 @@ export \ | |||||||
| 	SCWRYPTS_OUTPUT_PATH \ | 	SCWRYPTS_OUTPUT_PATH \ | ||||||
| 	; | 	; | ||||||
| 
 | 
 | ||||||
| SCWRYPTS_GROUPS+=(scwrypts) # 'scwrypts' group is required! | SCWRYPTS_GROUPS=(scwrypts $(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u)) | ||||||
| SCWRYPTS_GROUPS=($(echo $SCWRYPTS_GROUPS | sed 's/\s\+/\n/g' | sort -u)) |  | ||||||
| 
 | 
 | ||||||
| source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \ | source "$SCWRYPTS_ROOT/zsh/lib/config.group.zsh" \ | ||||||
| 	|| FAIL 69 'failed to set up scwrypts group; aborting' | 	|| FAIL 69 'failed to set up scwrypts group; aborting' | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ SCWRYPTS__RUN() {  # context wrapper to run scwrypts within scwrypts | |||||||
| 	local EXIT_CODE=0 | 	local EXIT_CODE=0 | ||||||
| 	((SUBSCWRYPT+=1)) | 	((SUBSCWRYPT+=1)) | ||||||
| 
 | 
 | ||||||
| 	SUBSCWRYPT=$SUBSCWRYPT $SCWRYPTS_ROOT/run $@ | 	SUBSCWRYPT=$SUBSCWRYPT $SCWRYPTS_ROOT/scwrypts $@ | ||||||
| 	EXIT_CODE=$? | 	EXIT_CODE=$? | ||||||
| 
 | 
 | ||||||
| 	((SUBSCWRYPT-=1)) | 	((SUBSCWRYPT-=1)) | ||||||
|   | |||||||
| @@ -119,6 +119,27 @@ SCWRYPTS__GET_RUNSTRING__zsh() { | |||||||
| 		|| SCWRYPT_FILENAME="$GROUP_PATH/$SCWRYPT_TYPE/$SCWRYPT_NAME" \ | 		|| 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 " | 	printf " | ||||||
| 		source '$SCWRYPT_FILENAME' | 		source '$SCWRYPT_FILENAME' | ||||||
| 		CHECK_ENVIRONMENT | 		CHECK_ENVIRONMENT | ||||||
| @@ -154,22 +175,6 @@ SCWRYPTS__GET_RUNSTRING__zsh() { | |||||||
| 			done | 			done | ||||||
| 			MAIN \${MAIN_ARGS[@]} | 			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() { | SCWRYPTS__GET_RUNSTRING__py() { | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ __CHECK_COREUTILS() { | |||||||
| 	do | 	do | ||||||
| 		__CHECK_DEPENDENCY $UTIL || { ((MISSING_DEPENDENCY_COUNT+=1)); continue; } | 		__CHECK_DEPENDENCY $UTIL || { ((MISSING_DEPENDENCY_COUNT+=1)); continue; } | ||||||
| 
 | 
 | ||||||
| 		$UTIL --version 2>&1 | grep -q 'GNU' || { | 		$UTIL --version 2>&1 | grep 'GNU' | grep -qv 'BSD' || { | ||||||
| 			WARNING "non-GNU version of $UTIL detected" | 			WARNING "non-GNU version of $UTIL detected" | ||||||
| 			((NON_GNU_DEPENDENCY_COUNT+=1)) | 			((NON_GNU_DEPENDENCY_COUNT+=1)) | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -40,18 +40,3 @@ FZF_USER_INPUT() { # allow user to type custom answers; reconfirm if ambiguous w | |||||||
| 	echo $FZF_OUTPUT | 	echo $FZF_OUTPUT | ||||||
| 	[ $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; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| ##################################################################### |  | ||||||
|   | |||||||
| @@ -6,6 +6,7 @@ source "${0:a:h}/io.print.zsh" | |||||||
| [ ! $ERRORS ] && ERRORS=0 | [ ! $ERRORS ] && ERRORS=0 | ||||||
| 
 | 
 | ||||||
| ERROR() {  # command encountered an error | ERROR() {  # command encountered an error | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||||
| 		&& PREFIX="ERROR    ✖" COLOR=$__RED            PRINT "$@" | 		&& PREFIX="ERROR    ✖" COLOR=$__RED            PRINT "$@" | ||||||
| 	((ERRORS+=1)) | 	((ERRORS+=1)) | ||||||
| @@ -13,35 +14,47 @@ ERROR() {  # command encountered an error | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| SUCCESS() {  # command completed successfully | SUCCESS() {  # command completed successfully | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||||
| 		&& PREFIX="SUCCESS  ✔" COLOR=$__GREEN          PRINT "$@" | 		&& PREFIX="SUCCESS  ✔" COLOR=$__GREEN          PRINT "$@" | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| REMINDER() {  # include sysadmin reminder or other important notice to users | REMINDER() {  # include sysadmin reminder or other important notice to users | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||||
| 		&& PREFIX="REMINDER " COLOR=$__BRIGHT_MAGENTA PRINT "$@" | 		&& PREFIX="REMINDER " COLOR=$__BRIGHT_MAGENTA PRINT "$@" | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| STATUS() {  # general status updates (prefer this to generic 'echo') | STATUS() {  # general status updates (prefer this to generic 'echo') | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 2 ]] \ | ||||||
| 		&& PREFIX="STATUS    " COLOR=$__BLUE           PRINT "$@" | 		&& PREFIX="STATUS    " COLOR=$__BLUE           PRINT "$@" | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| WARNING() {  # warning-level messages; not errors | WARNING() {  # warning-level messages; not errors | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 3 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 3 ]] \ | ||||||
| 		&& PREFIX="WARNING  " COLOR=$__YELLOW         PRINT "$@" | 		&& PREFIX="WARNING  " COLOR=$__YELLOW         PRINT "$@" | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| DEBUG() {  # helpful during development or (sparingly) to help others' development | DEBUG() {  # helpful during development or (sparingly) to help others' development | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 4 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 4 ]] \ | ||||||
| 		&& PREFIX="DEBUG    ℹ" COLOR=$__WHITE          PRINT "$@" | 		&& PREFIX="DEBUG    ℹ" COLOR=$__WHITE          PRINT "$@" | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PROMPT() {  # you probably want to use yN or INPUT from below | PROMPT() {  # you probably want to use yN or INPUT from below | ||||||
|  | 	[ ! $SCWRYPTS_LOG_LEVEL ] && local SCWRYPTS_LOG_LEVEL=4 | ||||||
| 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | 	[[ $SCWRYPTS_LOG_LEVEL -ge 1 ]] \ | ||||||
| 		&& PREFIX="PROMPT   " COLOR=$__CYAN PRINT "$@" \ | 		&& PREFIX="PROMPT   " COLOR=$__CYAN PRINT "$@" \ | ||||||
| 		&& PREFIX="USER     ⌨" COLOR=$__BRIGHT_CYAN PRINT '' --no-line-end \ | 		&& PREFIX="USER     ⌨" COLOR=$__BRIGHT_CYAN PRINT '' --no-line-end \ | ||||||
| 		; | 		; | ||||||
|  | 	return 0 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| FAIL()  { SCWRYPTS_LOG_LEVEL=1 ERROR "${@:2}"; exit $1; } | FAIL()  { SCWRYPTS_LOG_LEVEL=1 ERROR "${@:2}"; exit $1; } | ||||||
| @@ -211,15 +224,21 @@ READ_YN() {  # yes/no read is suprisingly tricky | |||||||
| 	local yn | 	local yn | ||||||
| 	PROMPT "${USERPROMPT[@]}" | 	PROMPT "${USERPROMPT[@]}" | ||||||
| 
 | 
 | ||||||
|  | 	local PERFORM_FAKE_PROMPT=false | ||||||
| 	case $SKIP_USER_INPUT in | 	case $SKIP_USER_INPUT in | ||||||
| 		true ) yn=y ;; | 		true ) yn=y ;; | ||||||
| 		false ) | 		false ) | ||||||
| 			[[ $FORCE_USER_INPUT =~ true ]] && [[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] \ | 			[[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] && { | ||||||
|  | 				[[ $FORCE_USER_INPUT =~ false ]] && [ ! -t 0 ] \ | ||||||
|  | 					|| PERFORM_FAKE_PROMPT=true | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			[[ $PERFORM_FAKE_PROMPT =~ true ]] \ | ||||||
| 				&& echo -n "${USERPROMPT[@]} : " >&2 | 				&& echo -n "${USERPROMPT[@]} : " >&2 | ||||||
| 
 | 
 | ||||||
| 			READ ${READ_ARGS[@]} -s -k yn | 			READ ${READ_ARGS[@]} -s -k yn | ||||||
| 
 | 
 | ||||||
| 			[[ $FORCE_USER_INPUT =~ true ]] && [[ $SCWRYPTS_LOG_LEVEL -lt 1 ]] \ | 			[[ $PERFORM_FAKE_PROMPT =~ true ]] \ | ||||||
| 				&& echo $yn >&2 | 				&& echo $yn >&2 | ||||||
| 			;; | 			;; | ||||||
| 	esac | 	esac | ||||||
|   | |||||||
| @@ -1,100 +0,0 @@ | |||||||
| { |  | ||||||
| 	"name": "scwrypts", |  | ||||||
| 	"main": "dist/index.js", |  | ||||||
| 	"type": "module", |  | ||||||
| 	"files": [ |  | ||||||
| 		"dist" |  | ||||||
| 	], |  | ||||||
| 	"description": "scwrypts integration for typescript", |  | ||||||
| 	"scripts": { |  | ||||||
| 		"build": "rm -rf ./dist && tsc", |  | ||||||
| 		"test": "jest", |  | ||||||
| 		"lint": "eslint . && prettier --check src/", |  | ||||||
| 		"format": "prettier --write src/" |  | ||||||
| 	}, |  | ||||||
| 	"author": "Wryn (yage) Wagner", |  | ||||||
| 	"license": "GPL-3.0", |  | ||||||
| 	"devDependencies": { |  | ||||||
| 		"@jest/globals": "^29.7.0", |  | ||||||
| 		"@types/jest": "^29.5.12", |  | ||||||
| 		"@types/node": "^20.11.19", |  | ||||||
| 		"@types/uuid": "^9.0.8", |  | ||||||
| 		"@typescript-eslint/eslint-plugin": "^7.0.2", |  | ||||||
| 		"@typescript-eslint/parser": "^7.0.2", |  | ||||||
| 		"eslint": "^8.56.0", |  | ||||||
| 		"jest": "^29.7.0", |  | ||||||
| 		"prettier": "^3.2.5", |  | ||||||
| 		"ts-jest": "^29.1.2", |  | ||||||
| 		"ts-node": "^10.9.2", |  | ||||||
| 		"typescript": "^5.3.3", |  | ||||||
| 		"uuid": "^9.0.1" |  | ||||||
| 	}, |  | ||||||
| 	"eslintConfig": { |  | ||||||
| 		"ignorePatterns": [ |  | ||||||
| 			"dist", |  | ||||||
| 			"node_modules" |  | ||||||
| 		], |  | ||||||
| 		"env": { |  | ||||||
| 			"node": true, |  | ||||||
| 			"es2021": true |  | ||||||
| 		}, |  | ||||||
| 		"extends": [ |  | ||||||
| 			"eslint:recommended", |  | ||||||
| 			"plugin:@typescript-eslint/recommended" |  | ||||||
| 		], |  | ||||||
| 		"overrides": [ |  | ||||||
| 			{ |  | ||||||
| 				"env": { |  | ||||||
| 					"node": true |  | ||||||
| 				}, |  | ||||||
| 				"files": [ |  | ||||||
| 					".eslintrc.{js,cjs}" |  | ||||||
| 				], |  | ||||||
| 				"parserOptions": { |  | ||||||
| 					"sourceType": "script" |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		], |  | ||||||
| 		"parser": "@typescript-eslint/parser", |  | ||||||
| 		"parserOptions": { |  | ||||||
| 			"ecmaVersion": "latest", |  | ||||||
| 			"sourceType": "module" |  | ||||||
| 		}, |  | ||||||
| 		"plugins": [ |  | ||||||
| 			"@typescript-eslint" |  | ||||||
| 		], |  | ||||||
| 		"rules": { |  | ||||||
| 			"linebreak-style": [ |  | ||||||
| 				"error", |  | ||||||
| 				"unix" |  | ||||||
| 			], |  | ||||||
| 			"quotes": [ |  | ||||||
| 				"error", |  | ||||||
| 				"single" |  | ||||||
| 			], |  | ||||||
| 			"semi": [ |  | ||||||
| 				"error", |  | ||||||
| 				"always" |  | ||||||
| 			], |  | ||||||
| 			"comma-dangle": [ |  | ||||||
| 				"error", |  | ||||||
| 				"always-multiline" |  | ||||||
| 			] |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"prettier": { |  | ||||||
| 		"printWidth": 120, |  | ||||||
| 		"singleQuote": true, |  | ||||||
| 		"trailingComma": "all" |  | ||||||
| 	}, |  | ||||||
| 	"jest": { |  | ||||||
| 		"preset": "ts-jest", |  | ||||||
| 		"clearMocks": true, |  | ||||||
| 		"moduleNameMapper": { |  | ||||||
| 			"^(\\.{1,2}/.*)\\.js$": "$1" |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	"dependencies": { |  | ||||||
| 		"execa": "^8.0.1" |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										86
									
								
								zx/lib/package.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								zx/lib/package.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | --- | ||||||
|  | name: scwrypts | ||||||
|  | author: Wryn (yage) Wagner | ||||||
|  | description: scwrypts integration for typescript | ||||||
|  | license: GPL-3.0 | ||||||
|  | type: module | ||||||
|  | main: dist/index.js | ||||||
|  |  | ||||||
|  | files: | ||||||
|  |   - dist | ||||||
|  |  | ||||||
|  | scripts: | ||||||
|  |   build: rm -rf ./dist && tsc | ||||||
|  |   test: jest | ||||||
|  |   lint: eslint . && prettier --check src/ | ||||||
|  |   format: prettier --write src/ | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | dependencies: | ||||||
|  |   execa: ^8.0.1 | ||||||
|  |  | ||||||
|  | devDependencies: | ||||||
|  |   '@jest/globals': ^29.7.0 | ||||||
|  |   '@types/jest': ^29.5.12 | ||||||
|  |   '@types/node': ^20.11.19 | ||||||
|  |   '@types/uuid': ^9.0.8 | ||||||
|  |   '@typescript-eslint/eslint-plugin': ^7.0.2 | ||||||
|  |   '@typescript-eslint/parser': ^7.0.2 | ||||||
|  |   eslint: ^8.56.0 | ||||||
|  |   jest: ^29.7.0 | ||||||
|  |   prettier: ^3.2.5 | ||||||
|  |   ts-jest: ^29.1.2 | ||||||
|  |   ts-node: ^10.9.2 | ||||||
|  |   typescript: ^5.3.3 | ||||||
|  |   uuid: ^9.0.1 | ||||||
|  |  | ||||||
|  | ##################################################################### | ||||||
|  |  | ||||||
|  | eslintConfig: | ||||||
|  |   ignorePatterns: | ||||||
|  |     - dist | ||||||
|  |     - node_modules | ||||||
|  |   env: | ||||||
|  |     node: true | ||||||
|  |     es2021: true | ||||||
|  |   extends: | ||||||
|  |     - eslint:recommended | ||||||
|  |     - plugin:@typescript-eslint/recommended | ||||||
|  |   overrides: | ||||||
|  |     - env: | ||||||
|  |         node: true | ||||||
|  |       files: | ||||||
|  |         - .eslintrc.{js,cjs} | ||||||
|  |       parserOptions: | ||||||
|  |         sourceType: script | ||||||
|  |   parser: '@typescript-eslint/parser' | ||||||
|  |   parserOptions: | ||||||
|  |     ecmaVersion: latest | ||||||
|  |     sourceType: module | ||||||
|  |   plugins: | ||||||
|  |     - '@typescript-eslint' | ||||||
|  |   rules: | ||||||
|  |     linebreak-style: | ||||||
|  |       - error | ||||||
|  |       - unix | ||||||
|  |     quotes: | ||||||
|  |       - error | ||||||
|  |       - single | ||||||
|  |     semi: | ||||||
|  |       - error | ||||||
|  |       - always | ||||||
|  |     comma-dangle: | ||||||
|  |       - error | ||||||
|  |       - always-multiline | ||||||
|  |  | ||||||
|  | prettier: | ||||||
|  |   printWidth: 120 | ||||||
|  |   singleQuote: true | ||||||
|  |   trailingComma: all | ||||||
|  |  | ||||||
|  | jest: | ||||||
|  |   preset: ts-jest | ||||||
|  |   clearMocks: true | ||||||
|  |   moduleNameMapper: | ||||||
|  |     ^(\.{1,2}/.*)\.js$: $1 | ||||||
							
								
								
									
										6
									
								
								zx/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6
									
								
								zx/package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -31,6 +31,7 @@ | |||||||
|         "prettier": "^3.2.5", |         "prettier": "^3.2.5", | ||||||
|         "ts-jest": "^29.1.2", |         "ts-jest": "^29.1.2", | ||||||
|         "ts-node": "^10.9.2", |         "ts-node": "^10.9.2", | ||||||
|  |         "typescript": "^5.3.3", | ||||||
|         "uuid": "^9.0.1" |         "uuid": "^9.0.1" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
| @@ -4997,7 +4998,6 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", |       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", | ||||||
|       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", |       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", | ||||||
|       "dev": true, |       "dev": true, | ||||||
|       "peer": true, |  | ||||||
|       "bin": { |       "bin": { | ||||||
|         "tsc": "bin/tsc", |         "tsc": "bin/tsc", | ||||||
|         "tsserver": "bin/tsserver" |         "tsserver": "bin/tsserver" | ||||||
| @@ -8596,6 +8596,7 @@ | |||||||
|         "prettier": "^3.2.5", |         "prettier": "^3.2.5", | ||||||
|         "ts-jest": "^29.1.2", |         "ts-jest": "^29.1.2", | ||||||
|         "ts-node": "^10.9.2", |         "ts-node": "^10.9.2", | ||||||
|  |         "typescript": "^5.3.3", | ||||||
|         "uuid": "^9.0.1" |         "uuid": "^9.0.1" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
| @@ -8884,8 +8885,7 @@ | |||||||
|       "version": "5.3.3", |       "version": "5.3.3", | ||||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", |       "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", | ||||||
|       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", |       "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", | ||||||
|       "dev": true, |       "dev": true | ||||||
|       "peer": true |  | ||||||
|     }, |     }, | ||||||
|     "undici-types": { |     "undici-types": { | ||||||
|       "version": "5.26.5", |       "version": "5.26.5", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user