├── .DS_Store ├── .github ├── CODEOWNERS ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── ask_question.yml │ ├── feature_request.yml │ └── bug_report.yml ├── dependabot.yml ├── CONTRIBUTING.md ├── workflows │ ├── greetings.yml │ ├── security-hardening.yml │ ├── cicd.yml │ ├── purge-deprecated-workflow-runs.yml │ ├── generate-test-release.yml │ ├── generate-release.yml │ ├── stale.yml │ ├── dependabot.yml │ ├── delete-old-workflow-runs.yml │ ├── citation-validation.yml │ ├── repository-validation.yml │ └── document-validation.yml ├── PULL_REQUEST_TEMPLATE.md ├── scripts │ └── check-jobs.sh ├── SECURITY.md └── CODE_OF_CONDUCT.md ├── .gitignore ├── src ├── variable-replace │ ├── test.sh │ └── variable-replace.sh ├── sudo-librarian-puppet │ └── sudo-librarian-puppet.sh ├── abs │ └── abs.sh ├── untag │ └── untag.sh ├── get-version-string │ └── get-version-string.sh ├── stacktrace │ └── stacktrace.sh ├── countdown │ └── countdown.sh ├── contains │ └── contains.sh ├── get-terraform-version │ └── get-terraform-version.sh ├── using-colour │ └── using-colour.sh ├── array-contains │ └── array-contains.sh ├── using-set │ └── using-set.sh ├── center-text │ └── center-text.sh ├── array-to-string │ └── array-to-string.sh ├── check-prerequisites │ └── check-prerequisites.sh ├── get-confirmation │ └── get-confirmation.sh ├── verbose-mode │ └── verbose-mode.sh ├── is-git-repo │ └── is-git-repo.sh ├── terminal-or-not │ └── terminal-or-not.sh ├── get-script-info │ └── get-script-info.sh ├── get-git-root │ └── get-git-root.sh ├── error-messages │ └── error-messages.sh ├── strict-mode │ └── strict-mode.sh ├── rollingback │ └── rollingback.sh └── compare-versions │ └── compare-versions.sh ├── CITATION.cff ├── .yamllint ├── LICENSE.md └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DevelopersToolbox/bash-snippets/HEAD/.DS_Store -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # 2 | # These owners will be the default owners for everything in the repo. 3 | # 4 | * @TGWolf 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Hard Coded Minimums ### 2 | # 3 | # Because I use a Mac 4 | # 5 | **/.DS-Store 6 | 7 | # 8 | # Ignore Awesomebot output 9 | # 10 | **/ab-results* 11 | 12 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # Funding 2 | # https://help.github.com/en/github/administering-a-repository/displaying-a-sponsor-button-in-your-repository 3 | 4 | github: [WolfSoftware,TGWolf] 5 | -------------------------------------------------------------------------------- /src/variable-replace/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | USERNAME='{{ USERNAME_PLACE_HOLDER }}' 4 | PASSWORD='{{ PASSWORD_PLACE_HOLDER }}' 5 | 6 | echo "Username: ${USERNAME}" 7 | echo "Password: ${PASSWORD}" 8 | -------------------------------------------------------------------------------- /src/sudo-librarian-puppet/sudo-librarian-puppet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | sudo -i < This project has a [code of conduct](CODE_OF_CONDUCT.md). By interacting 14 | with this repository, organization, or community you agree to abide by its terms. 15 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | extends: default 4 | 5 | rules: 6 | braces: 7 | level: warning 8 | max-spaces-inside: 1 9 | brackets: 10 | level: warning 11 | max-spaces-inside: 1 12 | colons: 13 | level: warning 14 | commas: 15 | level: warning 16 | comments-indentation: disable 17 | document-start: disable 18 | empty-lines: 19 | level: warning 20 | hyphens: 21 | level: warning 22 | indentation: 23 | level: warning 24 | indent-sequences: consistent 25 | line-length: disable 26 | truthy: disable 27 | -------------------------------------------------------------------------------- /.github/workflows/greetings.yml: -------------------------------------------------------------------------------- 1 | name: Greetings 2 | 3 | on: 4 | pull_request: 5 | issues: 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | greetings: 15 | name: Handle Greetings 16 | permissions: 17 | issues: write 18 | pull-requests: write 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Handle Greetings 23 | uses: actions/first-interaction@34f15e814fe48ac9312ccf29db4e74fa767cbab7 # v1.3.0 24 | with: 25 | repo-token: ${{ secrets.GITHUB_TOKEN }} 26 | issue-message: "Thank you for raising your first issue - all contributions to this project are welcome!" 27 | pr-message: "Thank you for raising your first pull request - all contributions to this project are welcome!" 28 | -------------------------------------------------------------------------------- /.github/workflows/security-hardening.yml: -------------------------------------------------------------------------------- 1 | name: Security Hardening 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'dependabot/**' 7 | paths-ignore: 8 | - '**/*.md' 9 | - '**/*.cff' 10 | pull_request: 11 | branches: 12 | - '**' 13 | paths-ignore: 14 | - '**/*.md' 15 | - '**/*.cff' 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | permissions: read-all 22 | 23 | jobs: 24 | security-hardening: 25 | name: Harden Security 26 | runs-on: ubuntu-latest 27 | 28 | steps: 29 | - name: Checkout the Repository 30 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 31 | 32 | - name: Ensure SHA Pinned Actions 33 | uses: zgosalvez/github-actions-ensure-sha-pinned-actions@fc87bb5b5a97953d987372e74478de634726b3e5 # v3.0.25 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ask_question.yml: -------------------------------------------------------------------------------- 1 | name: Ask a question 2 | description: If you don't have a specific issue or bug to report you can still ask us questions and we will do our best to answer them 3 | title: "[Question]: " 4 | labels: ["type: question", "state: triage"] 5 | assignees: 6 | - tgwolf 7 | body: 8 | - type: textarea 9 | id: question 10 | attributes: 11 | label: What is your question? 12 | description: Please give us time to review your question and formulate an answer. 13 | validations: 14 | required: true 15 | - type: checkboxes 16 | id: terms 17 | attributes: 18 | label: Code of Conduct 19 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/DevelopersToolbox/bash-snippets/blob/master/.github/CODE_OF_CONDUCT.md) 20 | options: 21 | - label: I agree to follow this project's Code of Conduct 22 | required: true 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Thank You 2 | 3 | Thanks for submitting a pull request! Please provide enough information so that 4 | others can review your pull request: 5 | 6 | ## Summary 7 | 8 | 9 | 10 | This PR fixes/implements the following **bugs/features** 11 | 12 | * [ ] Bug 1 13 | * [ ] Feature 1 14 | * [ ] Breaking changes 15 | 16 | 18 | 19 | Explain the **motivation** for making this change. What existing problem does 20 | the pull request solve? 21 | 22 | 24 | 25 | ## Test plan (required) 26 | 27 | Demonstrate the code is solid. Example: The exact commands you ran and their 28 | output, screenshots help greatly. 29 | 30 | 31 | 32 | ## Closing issues 33 | 34 | 36 | Fixes # 37 | -------------------------------------------------------------------------------- /.github/scripts/check-jobs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script receives a JSON string containing job results and checks for any failures. 4 | 5 | # Check if jq is available 6 | if ! command -v jq &> /dev/null; then 7 | echo "jq could not be found, please install jq to run this script." 8 | exit 1 9 | fi 10 | 11 | # Read the JSON string from the first script argument 12 | job_results_json=$1 13 | 14 | # Check if the job results JSON is not empty 15 | if [[ -z "$job_results_json" ]]; then 16 | echo "No job results JSON provided." 17 | exit 1 18 | fi 19 | 20 | # Set default state 21 | failed_jobs=false 22 | 23 | # Use jq to parse the JSON and check each job's result 24 | while IFS= read -r line; do 25 | job_name=$(echo "$line" | awk '{print $1}') 26 | result=$(echo "$line" | awk '{print $3}') 27 | 28 | if [ "$result" != "success" ]; then 29 | echo "$job_name failed." 30 | failed_jobs=true 31 | else 32 | echo "$job_name succeed." 33 | fi 34 | done <<< "$( echo "$job_results_json" | jq -r 'to_entries[] | "\(.key) result: \(.value.result)"' )" 35 | 36 | if [ "$failed_jobs" = true ] ; then 37 | exit 1 38 | fi 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2009-2024` `Wolf Software` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /.github/workflows/cicd.yml: -------------------------------------------------------------------------------- 1 | name: CI/CD Pipeline 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'dependabot/**' 7 | paths-ignore: 8 | - '**/*.md' 9 | - '**/*.cff' 10 | 11 | pull_request: 12 | branches: 13 | - '**' 14 | paths-ignore: 15 | - '**/*.md' 16 | - '**/*.cff' 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | permissions: read-all 23 | 24 | jobs: 25 | shellcheck: 26 | name: ShellCheck 27 | runs-on: ubuntu-latest 28 | 29 | steps: 30 | - name: Checkout the Repository 31 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 32 | 33 | - name: Perform ShellCheck Analysis 34 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/shellcheck/master/pipeline.sh) 35 | 36 | cicd-pipeline: 37 | if: always() 38 | name: CI/CD Pipeline 39 | needs: 40 | - shellcheck 41 | runs-on: ubuntu-latest 42 | 43 | steps: 44 | - name: Checkout the Repository 45 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 46 | 47 | - name: Check Job Statuses 48 | run: .github/scripts/check-jobs.sh '${{ toJson(needs) }}' 49 | -------------------------------------------------------------------------------- /.github/workflows/purge-deprecated-workflow-runs.yml: -------------------------------------------------------------------------------- 1 | name: Purge Deprecated Workflow Runs 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | schedule: 7 | - cron: '57 2 * * 1' 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | permissions: read-all 14 | 15 | jobs: 16 | purge-obsolete-workflows: 17 | name: Purge Deprecated Workflow Runs 18 | permissions: 19 | actions: write 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Purge Deprecated Workflow Runs 24 | uses: otto-de/purge-deprecated-workflow-runs@6fcf966b89e5907a9965946adb9a9d89dc312220 # v 3.0.4 25 | with: 26 | token: ${{ secrets.GITHUB_TOKEN }} 27 | remove-obsolete: true 28 | remove-cancelled: true 29 | remove-failed: true 30 | remove-skipped: true 31 | 32 | slack-workflow-status: 33 | if: always() 34 | name: Slack Post Workflow Notification 35 | needs: 36 | - purge-obsolete-workflows 37 | runs-on: ubuntu-latest 38 | 39 | steps: 40 | - name: Slack Workflow Notifications 41 | if: ${{ github.event_name == 'schedule' && needs.purge-obsolete-workflows.result != 'success'}} 42 | uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a # v1.3.0 43 | with: 44 | repo_token: ${{ secrets.GITHUB_TOKEN }} 45 | slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} 46 | include_jobs: on-failure 47 | include_commit_message: true 48 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policies and Procedures 2 | 3 | This document outlines security procedures and general policies for this project. 4 | 5 | * [Reporting a Bug](#reporting-a-bug) 6 | * [Disclosure Policy](#disclosure-policy) 7 | * [Comments on this Policy](#comments-on-this-policy) 8 | 9 | ## Reporting a Bug 10 | 11 | We take **ALL** security related bugs and issues very seriously. 12 | 13 | If you think you have identified a security related issue, please 14 | [report it immediately](mailto:disclose@wolfsoftware.com) and include 15 | the word "SECURITY" in the subject line. If you are not sure, don’t worry. 16 | Better safe than sorry – just send an email. 17 | 18 | * Please provide as much information as you can. 19 | * Please do not open issues related to any security concerns publicly. 20 | * Please do not include anyone else on the disclosure email. 21 | 22 | Report security bugs in third-party modules to the person or team maintaining 23 | the module. 24 | 25 | ## Disclosure Policy 26 | 27 | When a security report is received, we will carry out the following steps: 28 | 29 | * Confirm the problem and determine the affected versions. 30 | * Audit code to find any potential similar problems. 31 | * Prepare fixes for all releases still under maintenance. These fixes will be 32 | released as fast as possible. 33 | 34 | We will endeavour to keep you informed of the progress towards a fix and full 35 | announcement, and may ask for additional information or guidance. 36 | 37 | ## Comments on this Policy 38 | 39 | If you have suggestions on how this process could be improved please submit a 40 | pull request. 41 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Request a new feature 2 | description: Got an idea for a new feature? Let us know what you want and we will see if we can add it 3 | title: "[Feature Request]: " 4 | labels: ["type: feature", "state: triage"] 5 | assignees: 6 | - tgwolf 7 | body: 8 | - type: textarea 9 | id: releated-to 10 | attributes: 11 | label: Is your feature request related to a problem? 12 | description: A clear and concise description of what the problem is. E.g. I'm always frustrated when ... 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: suggested-solution 17 | attributes: 18 | label: Suggested Solution 19 | description: A clear and concise description of what you want to see implemented. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: alternatives 24 | attributes: 25 | label: Describe alternatives you've considered 26 | description: A clear and concise description of any alternative solutions or features you've considered. 27 | validations: 28 | required: true 29 | - type: textarea 30 | id: additional-information 31 | attributes: 32 | label: Additional information 33 | description: Please provide any additional information that you think will help us to resolve this bug. 34 | validations: 35 | required: false 36 | - type: checkboxes 37 | id: terms 38 | attributes: 39 | label: Code of Conduct 40 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/DevelopersToolbox/bash-snippets/blob/master/.github/CODE_OF_CONDUCT.md) 41 | options: 42 | - label: I agree to follow this project's Code of Conduct 43 | required: true 44 | -------------------------------------------------------------------------------- /.github/workflows/generate-test-release.yml: -------------------------------------------------------------------------------- 1 | name: Generate a TEST Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v[0-9].[0-9]+.[0-9]+rc[0-9]+' 7 | 8 | concurrency: 9 | group: ${{ github.workflow }}-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | permissions: read-all 13 | 14 | jobs: 15 | set-release-version: 16 | name: Set Release Version 17 | runs-on: ubuntu-latest 18 | outputs: 19 | release-version: ${{ steps.set-release-version.outputs.release-version }} 20 | 21 | steps: 22 | - name: Checkout the repository 23 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: Set the release version 28 | id: set-release-version 29 | run: echo "release-version=${GITHUB_REF#refs/*/}" >> "${GITHUB_OUTPUT}" 30 | 31 | create-release: 32 | name: Create Release 33 | permissions: 34 | contents: write 35 | runs-on: ubuntu-latest 36 | needs: 37 | - set-release-version 38 | 39 | steps: 40 | - name: Checkout the Repository 41 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 42 | with: 43 | fetch-depth: 0 44 | 45 | - name: Generate Changelog 46 | uses: Bullrich/generate-release-changelog@6b60f004b4bf12ff271603dc32dbd261965ad2f2 # v2.0.2 47 | id: Changelog 48 | env: 49 | REPO: ${{ github.repository }} 50 | 51 | - name: Create a Release 52 | id: create_release 53 | uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 54 | with: 55 | token: ${{ secrets.GITHUB_TOKEN }} 56 | tag_name: ${{ github.ref }} 57 | name: ${{ needs.set-release-version.outputs.release-version }} 58 | body: ${{ steps.Changelog.outputs.changelog }} 59 | draft: false 60 | prerelease: true 61 | -------------------------------------------------------------------------------- /.github/workflows/generate-release.yml: -------------------------------------------------------------------------------- 1 | name: Generate a Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v[0-9].[0-9]+.[0-9]+' 7 | - '!v[0-9].[0-9]+.[0-9]+rc[0-9]+' 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | permissions: read-all 14 | 15 | jobs: 16 | set-release-version: 17 | name: Set Release Version 18 | runs-on: ubuntu-latest 19 | outputs: 20 | release-version: ${{ steps.set-release-version.outputs.release-version }} 21 | 22 | steps: 23 | - name: Checkout the Repository 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 25 | with: 26 | fetch-depth: 0 27 | 28 | - name: Set the Release Version 29 | id: set-release-version 30 | run: | 31 | echo "release-version=${GITHUB_REF#refs/*/}" >> "${GITHUB_OUTPUT}" 32 | 33 | create-release: 34 | name: Create a Release 35 | permissions: 36 | contents: write 37 | runs-on: ubuntu-latest 38 | needs: 39 | - set-release-version 40 | 41 | steps: 42 | - name: Checkout the Repository 43 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 44 | with: 45 | fetch-depth: 0 46 | 47 | - name: Generate Changelog 48 | uses: Bullrich/generate-release-changelog@6b60f004b4bf12ff271603dc32dbd261965ad2f2 # v2.0.2 49 | id: Changelog 50 | env: 51 | REPO: ${{ github.repository }} 52 | 53 | - name: Create a Release 54 | id: create_release 55 | uses: softprops/action-gh-release@5be0e66d93ac7ed76da52eca8bb058f665c3a5fe # v2.4.2 56 | with: 57 | token: ${{ secrets.GITHUB_TOKEN }} 58 | tag_name: ${{ github.ref }} 59 | name: ${{ needs.set-release-version.outputs.release-version }} 60 | body: ${{ steps.Changelog.outputs.changelog }} 61 | draft: false 62 | prerelease: false 63 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Report a bug 2 | description: Found a bug? Let us knonw what the issue is and we will attempt to fix it 3 | title: "[Bug]: " 4 | labels: ["type: bug", "state: triage"] 5 | assignees: 6 | - tgwolf 7 | body: 8 | - type: textarea 9 | id: what-happened 10 | attributes: 11 | label: What happened? 12 | description: A clear and concise description of what the bug is. 13 | validations: 14 | required: true 15 | - type: textarea 16 | id: expected-behavior 17 | attributes: 18 | label: Expected behavior 19 | description: A clear and concise description of what you expected to happen. 20 | validations: 21 | required: true 22 | - type: textarea 23 | id: reproduce 24 | attributes: 25 | label: How do we reproduct the bug? 26 | description: What are the steps we need to take to reproduce the behavior? 27 | validations: 28 | required: true 29 | - type: textarea 30 | id: logs 31 | attributes: 32 | label: Relevant log output 33 | description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. 34 | render: shell 35 | validations: 36 | required: false 37 | - type: textarea 38 | id: screenshoots 39 | attributes: 40 | label: Screeenshots 41 | description: Upload any screenshots that might help demonstrate the bug. 42 | validations: 43 | required: false 44 | - type: textarea 45 | id: additional-information 46 | attributes: 47 | label: Additional information 48 | description: Please provide any additional information that you think will help us to resolve this bug. 49 | validations: 50 | required: false 51 | - type: checkboxes 52 | id: terms 53 | attributes: 54 | label: Code of Conduct 55 | description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/DevelopersToolbox/bash-snippets/blob/master/.github/CODE_OF_CONDUCT.md) 56 | options: 57 | - label: I agree to follow this project's Code of Conduct 58 | required: true 59 | -------------------------------------------------------------------------------- /src/stacktrace/stacktrace.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to generate a stack trace. # 7 | # -------------------------------------------------------------------------------- # 8 | # shellcheck disable=2120 9 | 10 | function stacktrace 11 | { 12 | local start_from=${1:-0} 13 | local i=0 14 | 15 | while caller $i > /dev/null 16 | do 17 | if (( "$i" + 1 >= "${start_from}" )); then 18 | caller $i 19 | fi 20 | ((i=i+1)) 21 | done 22 | } 23 | 24 | function test_wrapper() 25 | { 26 | stacktrace 27 | } 28 | 29 | # -------------------------------------------------------------------------------- # 30 | # Run Tests # 31 | # -------------------------------------------------------------------------------- # 32 | # A VERY simple test function to ensure that it all works # 33 | # -------------------------------------------------------------------------------- # 34 | 35 | function run_test() 36 | { 37 | test_wrapper 38 | } 39 | 40 | # -------------------------------------------------------------------------------- # 41 | # Main() # 42 | # -------------------------------------------------------------------------------- # 43 | # This is the actual 'script' and the functions/sub routines are called in order. # 44 | # -------------------------------------------------------------------------------- # 45 | 46 | run_test "$@" 47 | 48 | # -------------------------------------------------------------------------------- # 49 | # End of Script # 50 | # -------------------------------------------------------------------------------- # 51 | # This is the end - nothing more to see here. # 52 | # -------------------------------------------------------------------------------- # 53 | 54 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | name: Stale Issue & PR Handler 2 | 3 | on: 4 | schedule: 5 | - cron: '13 4 * * *' 6 | 7 | concurrency: 8 | group: ${{ github.workflow }}-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | stale: 15 | name: Handle Stale Issues & PRs 16 | permissions: 17 | contents: write 18 | issues: write 19 | pull-requests: write 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Handle Stale Issues & PRs 24 | uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9.1.0 25 | id: stale-issues 26 | with: 27 | stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.' 28 | close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.' 29 | days-before-issue-stale: 30 30 | days-before-issue-close: 5 31 | stale-issue-label: 'state: stale' 32 | close-issue-label: 'resolution: closed' 33 | exempt-issue-labels: 'state: blocked,state: keep' 34 | stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.' 35 | close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.' 36 | days-before-pr-stale: 45 37 | days-before-pr-close: 10 38 | stale-pr-label: 'state: stale' 39 | close-pr-label: 'resolution: closed' 40 | exempt-pr-labels: 'state: blocked,state: keep' 41 | 42 | slack-workflow-status: 43 | if: always() 44 | name: Slack Post Workflow Notification 45 | needs: 46 | - stale 47 | runs-on: ubuntu-latest 48 | 49 | steps: 50 | - name: Slack Workflow Notifications 51 | if: ${{ github.event_name == 'schedule' && needs.stale.result != 'success'}} 52 | uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a # v1.3.0 53 | with: 54 | repo_token: ${{ secrets.GITHUB_TOKEN }} 55 | slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} 56 | include_jobs: on-failure 57 | include_commit_message: true 58 | -------------------------------------------------------------------------------- /.github/workflows/dependabot.yml: -------------------------------------------------------------------------------- 1 | name: Dependabot Pull Request Approve & Merge 2 | 3 | on: pull_request 4 | 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | permissions: read-all 10 | 11 | jobs: 12 | dependabot: 13 | name: Dependabot 14 | permissions: 15 | contents: write 16 | pull-requests: write 17 | runs-on: ubuntu-latest 18 | 19 | if: ${{ github.actor == 'dependabot[bot]' }} 20 | steps: 21 | - name: Fetch Metadata 22 | id: dependabot-metadata 23 | uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 24 | with: 25 | github-token: "${{ secrets.GITHUB_TOKEN }}" 26 | 27 | - name: Approve PR 28 | if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch' || steps.dependabot-metadata.outputs.update-type == 'version-update:semver-minor' }} 29 | run: | 30 | gh pr review --approve "${PR_URL}" -b "I'm **approving** this pull request because it includes a patch or minor update" 31 | gh pr edit "${PR_URL}" --add-label "dependabot: auto approve" 32 | env: 33 | PR_URL: ${{ github.event.pull_request.html_url }} 34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 35 | 36 | - name: Auto-Merge Non-Major Updates 37 | if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-patch' || steps.dependabot-metadata.outputs.update-type == 'version-update:semver-minor' }} 38 | run: | 39 | gh pr comment "${PR_URL}" --body "I'm automatically merging this PR because it includes a patch or minor update" 40 | gh pr merge --auto --squash --delete-branch "${PR_URL}" 41 | gh pr edit "${PR_URL}" --add-label "dependabot: auto merge" 42 | env: 43 | PR_URL: ${{ github.event.pull_request.html_url }} 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Comment & Label Major Updates 47 | if: ${{ steps.dependabot-metadata.outputs.update-type == 'version-update:semver-major' }} 48 | run: | 49 | gh pr comment "${PR_URL}" --body "I'm **NOT** automatically merging this PR because it includes a major update of a dependency" 50 | gh pr edit "${PR_URL}" --add-label "dependabot: manual merge" 51 | env: 52 | PR_URL: ${{ github.event.pull_request.html_url }} 53 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 54 | -------------------------------------------------------------------------------- /.github/workflows/delete-old-workflow-runs.yml: -------------------------------------------------------------------------------- 1 | name: Delete Old Workflow Runs 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | days: 7 | description: 'Number of days to retain workflow runs.' 8 | required: true 9 | default: '30' 10 | minimum-runs: 11 | description: 'The minimum number of runs to keep for each workflow.' 12 | required: true 13 | default: '6' 14 | 15 | schedule: 16 | - cron: '3 3 * * *' 17 | 18 | concurrency: 19 | group: ${{ github.workflow }}-${{ github.ref }} 20 | cancel-in-progress: true 21 | 22 | env: 23 | DAYS: 30 24 | MINIMUM_RUNS: 6 25 | 26 | permissions: read-all 27 | 28 | jobs: 29 | set-runtime-values: 30 | name: Set Runtime Values 31 | runs-on: ubuntu-latest 32 | outputs: 33 | days: ${{ steps.set-output-defaults.outputs.days }} 34 | minimum-runs: ${{ steps.set-output-defaults.outputs.minimum-runs }} 35 | 36 | steps: 37 | - name: Set Runtime Values 38 | id: set-output-defaults 39 | run: | 40 | echo "days=${{ github.event.inputs.days || env.DAYS }}" >> "${GITHUB_OUTPUT}" 41 | echo "minimum-runs=${{ github.event.inputs.minimum-runs || env.MINIMUM_RUNS }}" >> "${GITHUB_OUTPUT}" 42 | 43 | delete-old-workflows: 44 | name: Delete Old Workflow Runs 45 | runs-on: ubuntu-latest 46 | permissions: 47 | actions: write 48 | needs: 49 | - set-runtime-values 50 | 51 | steps: 52 | - name: Delete Old Workflow Runs 53 | uses: Mattraks/delete-workflow-runs@01b65895d680fc9900871fd63cb37caf1a58567c # v2.1.0 54 | with: 55 | token: ${{ secrets.GITHUB_TOKEN }} 56 | repository: ${{ github.repository }} 57 | retain_days: ${{ needs.set-runtime-values.outputs.days }} 58 | keep_minimum_runs: ${{ needs.set-runtime-values.outputs.minimum-runs }} 59 | 60 | slack-workflow-status: 61 | if: always() 62 | name: Slack Post Workflow Notification 63 | needs: 64 | - delete-old-workflows 65 | runs-on: ubuntu-latest 66 | 67 | steps: 68 | - name: Slack Workflow Notifications 69 | if: ${{ github.event_name == 'schedule' && needs.delete-old-workflows.result != 'success'}} 70 | uses: Gamesight/slack-workflow-status@68bf00d0dbdbcb206c278399aa1ef6c14f74347a # v1.3.0 71 | with: 72 | repo_token: ${{ secrets.GITHUB_TOKEN }} 73 | slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }} 74 | include_jobs: on-failure 75 | include_commit_message: true 76 | -------------------------------------------------------------------------------- /.github/workflows/citation-validation.yml: -------------------------------------------------------------------------------- 1 | name: Citation Validation 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'dependabot/**' 7 | paths: 8 | - 'CITATION.cff' 9 | pull_request: 10 | branches: 11 | - '**' 12 | paths: 13 | - 'CITATION.cff' 14 | 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | permissions: read-all 20 | 21 | jobs: 22 | get-ruby-version: 23 | name: Get Latest Ruby Version 24 | runs-on: ubuntu-latest 25 | outputs: 26 | version: ${{ steps.get-language-versions.outputs.latest-versions }} 27 | 28 | steps: 29 | - name: Get Required Version 30 | uses: ActionsToolbox/get-language-versions-action@446919617fd774095b5dd3ed71c39dd3fd0d8f4f # v0.1.3 31 | id: get-language-versions 32 | with: 33 | language: "ruby" 34 | highest-only: true 35 | remove-patch-version: true 36 | 37 | awesomebot: 38 | name: Awesomebot 39 | needs: get-ruby-version 40 | runs-on: ubuntu-latest 41 | 42 | steps: 43 | - name: Checkout the Repository 44 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 45 | 46 | - name: Setup Ruby ${{ needs.get-ruby-version.outputs.version }} 47 | uses: ruby/setup-ruby@8aeb6ff8030dd539317f8e1769a044873b56ea71 # v1.268.0 48 | with: 49 | ruby-version: ${{ needs.get-ruby-version.outputs.version }} 50 | 51 | - name: Perform Awesomebot Analysis 52 | env: 53 | FLAGS: "default" 54 | WHITELIST: "https://img.shields.io" 55 | INCLUDE_FILES: "CITATION.cff" 56 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/awesomebot/master/pipeline.sh) 57 | 58 | validate-citation-file: 59 | name: Validate CITATION.cff 60 | runs-on: ubuntu-latest 61 | 62 | steps: 63 | - name: Checkout the Repository 64 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 65 | 66 | - name: Validate CITATION.cff 67 | uses: citation-file-format/cffconvert-github-action@4cf11baa70a673bfdf9dad0acc7ee33b3f4b6084 # v2.0.0 68 | with: 69 | args: "--validate" 70 | 71 | citation-validation-pipeline: 72 | if: always() 73 | name: Citation Validation Pipeline 74 | needs: 75 | - awesomebot 76 | - validate-citation-file 77 | runs-on: ubuntu-latest 78 | 79 | steps: 80 | - name: Checkout the Repository 81 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 82 | 83 | - name: Check Job Statuses 84 | run: .github/scripts/check-jobs.sh '${{ toJson(needs) }}' 85 | -------------------------------------------------------------------------------- /src/countdown/countdown.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to display a countdown timeer with optional message. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Countdown # 11 | # -------------------------------------------------------------------------------- # 12 | # Loop for the required numbers of seconds and display the message. We have to # 13 | # re-eval each time to ensure that the string is updated correctly. # 14 | # -------------------------------------------------------------------------------- # 15 | 16 | function countdown() 17 | { 18 | local seconds=${1:-0} 19 | local message=${2:-''} 20 | 21 | while [ "${seconds}" -gt 0 ]; do 22 | eval_message=$(eval "echo ${message}") 23 | echo -ne "${eval_message}\033[0K\r" 24 | sleep 1 25 | : $((seconds--)) 26 | done 27 | echo 28 | } 29 | 30 | # -------------------------------------------------------------------------------- # 31 | # Test # 32 | # -------------------------------------------------------------------------------- # 33 | # A VERY simple test function to ensure that it all works # 34 | # -------------------------------------------------------------------------------- # 35 | 36 | function run_tests() 37 | { 38 | # shellcheck disable=SC2016 39 | countdown 3 'Processing will start in $seconds seconds. Press Ctrl+C to abort' 40 | } 41 | 42 | # -------------------------------------------------------------------------------- # 43 | # Main() # 44 | # -------------------------------------------------------------------------------- # 45 | # This is the actual 'script' and the functions/sub routines are called in order. # 46 | # -------------------------------------------------------------------------------- # 47 | 48 | run_tests 49 | 50 | # -------------------------------------------------------------------------------- # 51 | # End of Script # 52 | # -------------------------------------------------------------------------------- # 53 | # This is the end - nothing more to see here. # 54 | # -------------------------------------------------------------------------------- # 55 | -------------------------------------------------------------------------------- /src/contains/contains.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to check to see if one string contains another. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Contains (string, substring) # 11 | # -------------------------------------------------------------------------------- # 12 | # This is a simple function that will check if one string contains another. # 13 | # # 14 | # Returns 0 if the specified string contains the specified substring, otherwise 1. # 15 | # -------------------------------------------------------------------------------- # 16 | 17 | function contains() 18 | { 19 | string="$1" 20 | substring="$2" 21 | 22 | if test "${string#*"$substring"}" != "$string"; then 23 | return 0 # $substring is in $string 24 | else 25 | return 1 # $substring is not in $string 26 | fi 27 | } 28 | 29 | # -------------------------------------------------------------------------------- # 30 | # Test # 31 | # -------------------------------------------------------------------------------- # 32 | # A VERY simple test function to ensure that it all works # 33 | # -------------------------------------------------------------------------------- # 34 | 35 | function run_tests() 36 | { 37 | local haystack="this is a test string" 38 | local needle="test" 39 | 40 | if contains "${haystack}" "${needle}"; then 41 | echo "We found a needle in a haystack" 42 | else 43 | echo "We did NOT found a needle in a haystack" 44 | fi 45 | } 46 | 47 | # -------------------------------------------------------------------------------- # 48 | # Main() # 49 | # -------------------------------------------------------------------------------- # 50 | # This is the actual 'script' and the functions/sub routines are called in order. # 51 | # -------------------------------------------------------------------------------- # 52 | 53 | run_tests 54 | 55 | # -------------------------------------------------------------------------------- # 56 | # End of Script # 57 | # -------------------------------------------------------------------------------- # 58 | # This is the end - nothing more to see here. # 59 | # -------------------------------------------------------------------------------- # 60 | 61 | -------------------------------------------------------------------------------- /src/get-terraform-version/get-terraform-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # A simple script to show how to programatically get the terraform version. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Get Terraform Version # 11 | # -------------------------------------------------------------------------------- # 12 | # Programatically get the terraform version. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | function get_terraform_version() 16 | { 17 | local terraform_version 18 | 19 | command=$(command -v "terraform") 20 | if [[ -z $command ]]; then 21 | echo "Terraform is not installed - Aborting" 22 | exit 23 | fi 24 | 25 | terraform_version=$(terraform --version | head -n 1) 26 | terraform_version=${terraform_version##* } # retain the part after the last space 27 | terraform_version=${terraform_version#?} # strip the first letter 28 | 29 | if [[ -z ${terraform_version} ]]; then 30 | echo "Could not determine terraform version - Aborting" 31 | exit 32 | fi 33 | 34 | echo "${terraform_version}" 35 | } 36 | 37 | # -------------------------------------------------------------------------------- # 38 | # Run Tests # 39 | # -------------------------------------------------------------------------------- # 40 | # A VERY simple test function to ensure that it all works # 41 | # -------------------------------------------------------------------------------- # 42 | 43 | function run_tests() 44 | { 45 | tf_version=$(get_terraform_version) 46 | echo "${tf_version}" 47 | } 48 | 49 | # -------------------------------------------------------------------------------- # 50 | # Main() # 51 | # -------------------------------------------------------------------------------- # 52 | # This is the actual 'script' and the functions/sub routines are called in order. # 53 | # -------------------------------------------------------------------------------- # 54 | 55 | run_tests 56 | 57 | # -------------------------------------------------------------------------------- # 58 | # End of Script # 59 | # -------------------------------------------------------------------------------- # 60 | # This is the end - nothing more to see here. # 61 | # -------------------------------------------------------------------------------- # 62 | 63 | -------------------------------------------------------------------------------- /src/using-colour/using-colour.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a demonstration on how to use colours. # 7 | # # 8 | # NOTE: This is a truncated example and a full working solution is avaiable at # 9 | # https://github.com/WolfSoftware/bash-colour-include. # 10 | # -------------------------------------------------------------------------------- # 11 | 12 | function set_colours() 13 | { 14 | # Foreground Colours 15 | fgRed='' 16 | fgYellow='' 17 | 18 | # Background Colours 19 | bgBlack='' 20 | bgWhite='' 21 | 22 | # Misc Features 23 | reset='' 24 | 25 | # Test to see if the terminal has colour support and if so set the variables to 26 | # the corresponding control codes. 27 | if test -t 1; then 28 | 29 | # see if it supports colors... 30 | ncolors=$(tput colors) 31 | 32 | if test -n "${ncolors}" && test "${ncolors}" -ge 8; then 33 | fgRed=$(tput setaf 1) 34 | fgYellow=$(tput setaf 3) 35 | 36 | bgBlack=$(tput setab 0) 37 | bgWhite=$(tput setab 7) 38 | 39 | reset=$(tput sgr0) 40 | fi 41 | fi 42 | 43 | } 44 | 45 | # -------------------------------------------------------------------------------- # 46 | # Run Tests # 47 | # -------------------------------------------------------------------------------- # 48 | # A VERY simple test function to ensure that it all works # 49 | # -------------------------------------------------------------------------------- # 50 | 51 | function run_tests() 52 | { 53 | set_colours 54 | 55 | echo "${bgBlack}${fgRed}This should be red text${reset}" 56 | echo "${bgBlack}${fgYellow}This should be yellow text${reset}" 57 | echo "${bgWhite}${fgRed}This should be red on a white background${reset}" 58 | } 59 | 60 | # -------------------------------------------------------------------------------- # 61 | # Main() # 62 | # -------------------------------------------------------------------------------- # 63 | # This is the actual 'script' and the functions/sub routines are called in order. # 64 | # -------------------------------------------------------------------------------- # 65 | 66 | run_tests 67 | 68 | # -------------------------------------------------------------------------------- # 69 | # End of Script # 70 | # -------------------------------------------------------------------------------- # 71 | # This is the end - nothing more to see here. # 72 | # -------------------------------------------------------------------------------- # 73 | -------------------------------------------------------------------------------- /src/array-contains/array-contains.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to check to see if an array contains a value. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Contains (string, substring) # 11 | # -------------------------------------------------------------------------------- # 12 | # This is a simple function that will check if and array contains a value. # 13 | # # 14 | # Returns 0 if the specified string contains the specified substring, otherwise 1. # 15 | # -------------------------------------------------------------------------------- # 16 | 17 | function array_contains() 18 | { 19 | local -n haystack=$1 20 | local needle=$2 21 | 22 | for i in "${haystack[@]}"; do 23 | if [[ $i == "${needle}" ]]; then 24 | return 0 25 | fi 26 | done 27 | 28 | return 1 29 | } 30 | 31 | # -------------------------------------------------------------------------------- # 32 | # Test # 33 | # -------------------------------------------------------------------------------- # 34 | # A VERY simple test function to ensure that it all works # 35 | # -------------------------------------------------------------------------------- # 36 | 37 | function run_tests() 38 | { 39 | # shellcheck disable=SC2034 40 | array_of_numbers=( "1" "2" "3" ) 41 | local needle1="3" 42 | local needle2="4" 43 | 44 | if ! array_contains array_of_numbers "${needle1}"; then 45 | echo "$needle1 not found" 46 | else 47 | echo "$needle1 found" 48 | fi 49 | 50 | if ! array_contains array_of_numbers "${needle2}"; then 51 | echo "$needle1 not found" 52 | else 53 | echo "$needle1 found" 54 | fi 55 | } 56 | 57 | # -------------------------------------------------------------------------------- # 58 | # Main() # 59 | # -------------------------------------------------------------------------------- # 60 | # This is the actual 'script' and the functions/sub routines are called in order. # 61 | # -------------------------------------------------------------------------------- # 62 | 63 | run_tests 64 | 65 | # -------------------------------------------------------------------------------- # 66 | # End of Script # 67 | # -------------------------------------------------------------------------------- # 68 | # This is the end - nothing more to see here. # 69 | # -------------------------------------------------------------------------------- # 70 | 71 | -------------------------------------------------------------------------------- /src/using-set/using-set.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a list of 'set' options and details of their specific usage. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Errexit # 11 | # -------------------------------------------------------------------------------- # 12 | # Exit on error. Append "|| true" if you expect an error # 13 | # -------------------------------------------------------------------------------- # 14 | set -o errexit 15 | 16 | # -------------------------------------------------------------------------------- # 17 | # Errtrace # 18 | # -------------------------------------------------------------------------------- # 19 | # Exit on error inside any functions or subshells # 20 | # -------------------------------------------------------------------------------- # 21 | set -o errtrace 22 | 23 | # -------------------------------------------------------------------------------- # 24 | # Nounset # 25 | # -------------------------------------------------------------------------------- # 26 | # Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR # 27 | # -------------------------------------------------------------------------------- # 28 | set -o nounset 29 | 30 | # -------------------------------------------------------------------------------- # 31 | # Pipefail # 32 | # -------------------------------------------------------------------------------- # 33 | # Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip` # 34 | # -------------------------------------------------------------------------------- # 35 | set -o pipefail 36 | 37 | # -------------------------------------------------------------------------------- # 38 | # Xtrace # 39 | # -------------------------------------------------------------------------------- # 40 | # Turn on traces, useful while debugging but commented out by default # 41 | # -------------------------------------------------------------------------------- # 42 | set -o xtrace 43 | 44 | # -------------------------------------------------------------------------------- # 45 | # End of Script # 46 | # -------------------------------------------------------------------------------- # 47 | # This is the end - nothing more to see here. # 48 | # -------------------------------------------------------------------------------- # 49 | -------------------------------------------------------------------------------- /src/center-text/center-text.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to display some text in the center of the screen. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Center text # 11 | # -------------------------------------------------------------------------------- # 12 | # This is a simple function that will center text on a screen, be calculating the # 13 | # correct amount of padding based on the 'screen_width' and the length of the # 14 | # text supplied to the function. # 15 | # -------------------------------------------------------------------------------- # 16 | 17 | function center_text() 18 | { 19 | textsize=${#1} 20 | span=$(((screen_width + textsize) / 2)) 21 | 22 | printf '%*s\n' "${span}" "$1" 23 | } 24 | 25 | # -------------------------------------------------------------------------------- # 26 | # Get Screen Width # 27 | # -------------------------------------------------------------------------------- # 28 | # A very simple wrapper which can dynamically get the screen width using tput. # 29 | # -------------------------------------------------------------------------------- # 30 | 31 | function get_screen_width() 32 | { 33 | screen_width=$(tput cols) 34 | declare -g screen_width 35 | } 36 | 37 | # -------------------------------------------------------------------------------- # 38 | # Test # 39 | # -------------------------------------------------------------------------------- # 40 | # A VERY simple test function to ensure that it all works # 41 | # -------------------------------------------------------------------------------- # 42 | 43 | function run_tests() 44 | { 45 | get_screen_width 46 | 47 | center_text "This is an example" 48 | } 49 | 50 | # -------------------------------------------------------------------------------- # 51 | # Main() # 52 | # -------------------------------------------------------------------------------- # 53 | # This is the actual 'script' and the functions/sub routines are called in order. # 54 | # -------------------------------------------------------------------------------- # 55 | 56 | run_tests 57 | 58 | # -------------------------------------------------------------------------------- # 59 | # End of Script # 60 | # -------------------------------------------------------------------------------- # 61 | # This is the end - nothing more to see here. # 62 | # -------------------------------------------------------------------------------- # 63 | 64 | -------------------------------------------------------------------------------- /src/array-to-string/array-to-string.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to check to see if an array contains a value. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Array to string (string, substring) # 11 | # -------------------------------------------------------------------------------- # 12 | # This is a simple function that will take an array and a seperator and create a # 13 | # string of values. # 14 | # -------------------------------------------------------------------------------- # 15 | 16 | function array_to_string() 17 | { 18 | separator="$1" 19 | local -n arr=$2 20 | 21 | regex="$( printf "${separator}%s" "${arr[@]}" )" 22 | regex="${regex:${#separator}}" # remove leading separator 23 | 24 | if [[ -n $3 ]]; then 25 | if [[ $regex = *"$separator"* ]]; then 26 | prefix=${regex%"$separator"*} # Extract content before the last instance 27 | suffix=${regex#"$prefix"} # Extract content *after* our prefix 28 | regex=${prefix}${suffix/"$separator"/"$3"} # Append unmodified prefix w/ suffix w/ replacement 29 | fi 30 | fi 31 | 32 | echo "${regex}" 33 | } 34 | 35 | # -------------------------------------------------------------------------------- # 36 | # Test # 37 | # -------------------------------------------------------------------------------- # 38 | # A VERY simple test function to ensure that it all works # 39 | # -------------------------------------------------------------------------------- # 40 | 41 | function run_tests() 42 | { 43 | # shellcheck disable=SC2034 44 | array_of_numbers=( "1" "2" "3" ) 45 | 46 | array_to_string ', ' array_of_numbers 47 | array_to_string ', ' array_of_numbers ' and ' 48 | array_to_string ', ' array_of_numbers ' or ' 49 | } 50 | 51 | # -------------------------------------------------------------------------------- # 52 | # Main() # 53 | # -------------------------------------------------------------------------------- # 54 | # This is the actual 'script' and the functions/sub routines are called in order. # 55 | # -------------------------------------------------------------------------------- # 56 | 57 | run_tests 58 | 59 | # -------------------------------------------------------------------------------- # 60 | # End of Script # 61 | # -------------------------------------------------------------------------------- # 62 | # This is the end - nothing more to see here. # 63 | # -------------------------------------------------------------------------------- # 64 | 65 | -------------------------------------------------------------------------------- /src/check-prerequisites/check-prerequisites.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to check prerequisite commands exist. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Required commands # 11 | # -------------------------------------------------------------------------------- # 12 | # These commands MUST exist in order for the script to correctly run. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | COMMANDS=( "curl" "top" "IwillFail" ) 16 | 17 | # -------------------------------------------------------------------------------- # 18 | # Check Prerequisites # 19 | # -------------------------------------------------------------------------------- # 20 | # Check to ensure that the prerequisite commmands exist. # 21 | # -------------------------------------------------------------------------------- # 22 | 23 | function check_prereqs() 24 | { 25 | local error_count=0 26 | 27 | for i in "${COMMANDS[@]}" 28 | do 29 | command=$(command -v "${i}") 30 | if [[ -z $command ]]; then 31 | printf '%s is not in your command path\n' "${i}" 32 | error_count=$((error_count+1)) 33 | fi 34 | done 35 | 36 | if [[ $error_count -gt 0 ]]; then 37 | printf '%d errors located - fix before re-running\n' ${error_count}; 38 | exit 1; 39 | fi 40 | } 41 | 42 | # -------------------------------------------------------------------------------- # 43 | # Run Tests # 44 | # -------------------------------------------------------------------------------- # 45 | # A VERY simple test function to ensure that it all works # 46 | # -------------------------------------------------------------------------------- # 47 | 48 | function run_tests() 49 | { 50 | check_prereqs 51 | } 52 | 53 | # -------------------------------------------------------------------------------- # 54 | # Main() # 55 | # -------------------------------------------------------------------------------- # 56 | # This is the actual 'script' and the functions/sub routines are called in order. # 57 | # -------------------------------------------------------------------------------- # 58 | 59 | run_tests 60 | 61 | # -------------------------------------------------------------------------------- # 62 | # End of Script # 63 | # -------------------------------------------------------------------------------- # 64 | # This is the end - nothing more to see here. # 65 | # -------------------------------------------------------------------------------- # 66 | 67 | -------------------------------------------------------------------------------- /src/get-confirmation/get-confirmation.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to request confirmation from a user. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Get Confirmation # 11 | # -------------------------------------------------------------------------------- # 12 | # A simple function which prompts the user for a yes/no response. # 13 | # # 14 | # A default prompt is used if one is not supplied, and the function will loop # 15 | # until a valid response is given. # 16 | # -------------------------------------------------------------------------------- # 17 | 18 | function get_confirmation() 19 | { 20 | local valid_response=false 21 | local return_value=0 22 | 23 | while [[ "$valid_response" = false ]] 24 | do 25 | read -r -p "${1:-Are you sure? [y/N]} " response 26 | case $response in 27 | [yY][eE][sS]|[yY]) 28 | valid_response=true 29 | return_value=1 30 | ;; 31 | [nN][oO]|[nN]) 32 | valid_response=true 33 | return_value=0 34 | ;; 35 | *) 36 | ;; 37 | esac 38 | done 39 | echo $return_value 40 | } 41 | 42 | # -------------------------------------------------------------------------------- # 43 | # Test # 44 | # -------------------------------------------------------------------------------- # 45 | # A VERY simple test function to ensure that it all works # 46 | # -------------------------------------------------------------------------------- # 47 | 48 | function run_tests() 49 | { 50 | response=0 51 | 52 | while [[ $response == 0 ]] 53 | do 54 | response=$(get_confirmation "Do you want to exit? [y/N]") 55 | done 56 | } 57 | 58 | # -------------------------------------------------------------------------------- # 59 | # Main() # 60 | # -------------------------------------------------------------------------------- # 61 | # This is the actual 'script' and the functions/sub routines are called in order. # 62 | # -------------------------------------------------------------------------------- # 63 | 64 | run_tests 65 | 66 | 67 | # -------------------------------------------------------------------------------- # 68 | # End of Script # 69 | # -------------------------------------------------------------------------------- # 70 | # This is the end - nothing more to see here. # 71 | # -------------------------------------------------------------------------------- # 72 | 73 | -------------------------------------------------------------------------------- /.github/workflows/repository-validation.yml: -------------------------------------------------------------------------------- 1 | name: Repository Validation 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'dependabot/**' 7 | paths-ignore: 8 | - '**/*.md' 9 | - '**/*.cff' 10 | pull_request: 11 | branches: 12 | - '**' 13 | paths-ignore: 14 | - '**/*.md' 15 | - '**/*.cff' 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.ref }} 19 | cancel-in-progress: true 20 | 21 | permissions: read-all 22 | 23 | jobs: 24 | get-go-version: 25 | name: Get Latest Go Version 26 | runs-on: ubuntu-latest 27 | outputs: 28 | version: ${{ steps.get-language-versions.outputs.latest-versions }} 29 | 30 | steps: 31 | - name: Get Required Versions 32 | uses: ActionsToolbox/get-language-versions-action@446919617fd774095b5dd3ed71c39dd3fd0d8f4f # V0.1.3 33 | id: get-language-versions 34 | with: 35 | language: "go" 36 | highest-only: true 37 | remove-patch-version: true 38 | 39 | get-python-version: 40 | name: Get Latest Python Version 41 | runs-on: ubuntu-latest 42 | outputs: 43 | version: ${{ steps.get-language-versions.outputs.latest-versions }} 44 | 45 | steps: 46 | - name: Get Required Versions 47 | uses: ActionsToolbox/get-language-versions-action@446919617fd774095b5dd3ed71c39dd3fd0d8f4f # V0.1.3 48 | id: get-language-versions 49 | with: 50 | language: "python" 51 | highest-only: true 52 | remove-patch-version: true 53 | 54 | action-lint: 55 | name: Action Lint 56 | needs: get-go-version 57 | runs-on: ubuntu-latest 58 | 59 | steps: 60 | - name: Checkout the Repository 61 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # V4.2.2 62 | 63 | - name: Setup Go ${{ needs.get-go-version.outputs.version }} 64 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # V5.5.0 65 | with: 66 | go-version: ${{ needs.get-go-version.outputs.version }} 67 | 68 | - name: Perform Action Lint Analysis 69 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/action-lint/master/pipeline.sh) 70 | 71 | yaml-lint: 72 | name: YAML Lint 73 | needs: get-python-version 74 | runs-on: ubuntu-latest 75 | steps: 76 | - name: Checkout the Repository 77 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # V4.2.2 78 | 79 | - name: Set up Python ${{ needs.get-python-version.outputs.version }} 80 | uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # V5.6.0 81 | with: 82 | python-version: ${{ needs.get-python-version.outputs.version }} 83 | 84 | - name: Perform YAML Lint Analysis 85 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/yaml-lint/master/pipeline.sh) 86 | 87 | repository-validation-pipeline: 88 | if: always() 89 | name: Repository Validation Pipeline 90 | needs: 91 | - action-lint 92 | - yaml-lint 93 | runs-on: ubuntu-latest 94 | 95 | steps: 96 | - name: Checkout the Repository 97 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # V4.2.2 98 | 99 | - name: Check Job Statuses 100 | run: .github/scripts/check-jobs.sh '${{ toJson(needs) }}' 101 | -------------------------------------------------------------------------------- /.github/workflows/document-validation.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Validation 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - 'dependabot/**' 7 | paths: 8 | - '**/*.md' 9 | pull_request: 10 | branches: 11 | - '**' 12 | paths: 13 | - '**/*.md' 14 | 15 | concurrency: 16 | group: ${{ github.workflow }}-${{ github.ref }} 17 | cancel-in-progress: true 18 | 19 | permissions: read-all 20 | 21 | jobs: 22 | get-node-version: 23 | name: Get Latest Node Version 24 | runs-on: ubuntu-latest 25 | outputs: 26 | version: ${{ steps.get-language-versions.outputs.latest-versions }} 27 | 28 | steps: 29 | - name: Get Required Version 30 | uses: ActionsToolbox/get-language-versions-action@446919617fd774095b5dd3ed71c39dd3fd0d8f4f # v0.1.3 31 | id: get-language-versions 32 | with: 33 | language: "node" 34 | highest-only: true 35 | remove-patch-version: true 36 | 37 | get-ruby-version: 38 | name: Get Latest Ruby Version 39 | runs-on: ubuntu-latest 40 | outputs: 41 | version: ${{ steps.get-language-versions.outputs.latest-versions }} 42 | 43 | steps: 44 | - name: Get Required Version 45 | uses: ActionsToolbox/get-language-versions-action@446919617fd774095b5dd3ed71c39dd3fd0d8f4f # v0.1.3 46 | id: get-language-versions 47 | with: 48 | language: "ruby" 49 | highest-only: true 50 | remove-patch-version: true 51 | 52 | awesomebot: 53 | name: Awesomebot 54 | needs: get-ruby-version 55 | runs-on: ubuntu-latest 56 | steps: 57 | - name: Checkout the Repository 58 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 59 | 60 | - name: Setup Ruby ${{ needs.get-ruby-version.outputs.version }} 61 | uses: ruby/setup-ruby@8aeb6ff8030dd539317f8e1769a044873b56ea71 # v1.268.0 62 | with: 63 | ruby-version: ${{ needs.get-ruby-version.outputs.version }} 64 | 65 | - name: Perform Awesomebot Analysis 66 | env: 67 | FLAGS: "default" 68 | WHITELIST: "https://img.shields.io" 69 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/awesomebot/master/pipeline.sh) 70 | 71 | markdown-lint: 72 | name: Markdown Lint 73 | needs: get-node-version 74 | runs-on: ubuntu-latest 75 | steps: 76 | - name: Checkout the Repository 77 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 78 | 79 | - name: Setup Node ${{ needs.get-node-version.outputs.version }} 80 | uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 81 | with: 82 | node-version: ${{ needs.get-node-version.outputs.version }} 83 | 84 | - name: Perform Markdown Lint Analysis 85 | run: bash <(curl -s https://raw.githubusercontent.com/CICDToolbox/markdown-lint/master/pipeline.sh) 86 | env: 87 | EXCLUDE_FILES: "README.md,CHANGELOG.md" 88 | 89 | repository-validation-pipeline: 90 | if: always() 91 | name: Documentation Validation Pipeline 92 | needs: 93 | - awesomebot 94 | - markdown-lint 95 | runs-on: ubuntu-latest 96 | 97 | steps: 98 | - name: Checkout the Repository 99 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 100 | 101 | - name: Check Job Statuses 102 | run: .github/scripts/check-jobs.sh '${{ toJson(needs) }}' 103 | -------------------------------------------------------------------------------- /.github/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behaviour that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behaviour by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behaviour and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behaviour. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behaviour may be 58 | reported by contacting the project team at . All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the 71 | [Contributor Covenant](https://www.contributor-covenant.org), version 1.4, 72 | available at 73 | 74 | For answers to common questions about this code of conduct, see 75 | 76 | -------------------------------------------------------------------------------- /src/verbose-mode/verbose-mode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to display some text in the center of the screen. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | VERBOSE=false 10 | 11 | # -------------------------------------------------------------------------------- # 12 | # Set Verbose Mode # 13 | # -------------------------------------------------------------------------------- # 14 | # This is a simple function that will enable verbose mode based on a global # 15 | # variable. It does this by cloning stdout and stderr and then redirecting the # 16 | # original file descriptors to /dev/null. # 17 | # -------------------------------------------------------------------------------- # 18 | 19 | function set_verbose_mode() 20 | { 21 | exec 3>&1 22 | exec 4>&2 23 | 24 | if [[ "${VERBOSE}" = true ]]; then 25 | echo "Verbose output enabled" 26 | else 27 | exec 1>/dev/null 28 | exec 2>/dev/null 29 | fi 30 | } 31 | 32 | # -------------------------------------------------------------------------------- # 33 | # Output Wrapper # 34 | # -------------------------------------------------------------------------------- # 35 | # A wrapper to use instead of echo which will handle the forcing of messages to be # 36 | # displayed even when verbose mode is off. # 37 | # -------------------------------------------------------------------------------- # 38 | 39 | function output() 40 | { 41 | if [[ -n $1 ]]; then 42 | if [[ -n $2 ]] && [[ "${2}" = forced ]]; then 43 | echo "$1" 1>&3 2>&4 44 | else 45 | echo "$1" 46 | fi 47 | fi 48 | } 49 | 50 | # -------------------------------------------------------------------------------- # 51 | # Run the Tests # 52 | # -------------------------------------------------------------------------------- # 53 | # -------------------------------------------------------------------------------- # 54 | 55 | function run_tests() 56 | { 57 | set_verbose_mode 58 | 59 | output "I won't be visible when verbose=false" 60 | output "I will be visible no matter what" forced 61 | } 62 | 63 | # -------------------------------------------------------------------------------- # 64 | # Main() # 65 | # -------------------------------------------------------------------------------- # 66 | # This is the actual 'script' and the functions/sub routines are called in order. # 67 | # -------------------------------------------------------------------------------- # 68 | 69 | run_tests 70 | 71 | # -------------------------------------------------------------------------------- # 72 | # End of Script # 73 | # -------------------------------------------------------------------------------- # 74 | # This is the end - nothing more to see here. # 75 | # -------------------------------------------------------------------------------- # 76 | 77 | -------------------------------------------------------------------------------- /src/is-git-repo/is-git-repo.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # A script to work out if a directory contains a git repo. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Is Git Repo # 11 | # -------------------------------------------------------------------------------- # 12 | # Look at a supplied dir to see if it cointains a git repo. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | function is_git_repo() 16 | { 17 | local retval 18 | 19 | # 20 | # Execute everything as a subshell to avoid messing up users current directory position 21 | # 22 | ( 23 | # 24 | # If we are checking a directory which is not the current one then cd to the specificed directory 25 | # 26 | if [[ -n $1 ]]; then 27 | if [[ ! -d $1 ]]; then 28 | return 1 29 | fi 30 | cd "${1}" || return 1 31 | fi 32 | 33 | # 34 | # Check to see if we are in a real git repo dir or not 35 | # 36 | # The return value is always true if you are in a git repo. 37 | # 38 | # The output can be true or false depending where in the repo you are so we ignore this 39 | # 40 | if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then 41 | retval=0 42 | else 43 | retval=1 44 | fi 45 | return $retval 46 | ) 47 | } 48 | 49 | # -------------------------------------------------------------------------------- # 50 | # Run Tests # 51 | # -------------------------------------------------------------------------------- # 52 | # A VERY simple test function to ensure that it all works # 53 | # -------------------------------------------------------------------------------- # 54 | 55 | function run_test() 56 | { 57 | declare -a dirs=('./' '/home' '/thiswillerror') 58 | 59 | ## now loop through the above array 60 | for i in "${dirs[@]}" 61 | do 62 | echo -n "${i} is " 63 | if is_git_repo "${i}"; then 64 | echo "a git repo" 65 | else 66 | echo "not a git repo" 67 | fi 68 | done 69 | } 70 | 71 | # -------------------------------------------------------------------------------- # 72 | # Main() # 73 | # -------------------------------------------------------------------------------- # 74 | # This is the actual 'script' and the functions/sub routines are called in order. # 75 | # -------------------------------------------------------------------------------- # 76 | 77 | run_test "$@" 78 | 79 | # -------------------------------------------------------------------------------- # 80 | # End of Script # 81 | # -------------------------------------------------------------------------------- # 82 | # This is the end - nothing more to see here. # 83 | # -------------------------------------------------------------------------------- # 84 | 85 | -------------------------------------------------------------------------------- /src/terminal-or-not/terminal-or-not.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a script to check if your script attached to in a terminal or not. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # in_terminal # 11 | # -------------------------------------------------------------------------------- # 12 | # Returns true if we are attached to a terminal or false if not. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | function in_terminal() 16 | { 17 | [[ -t 1 ]] && return 0 || return 1; 18 | } 19 | 20 | # -------------------------------------------------------------------------------- # 21 | # in_pipe # 22 | # -------------------------------------------------------------------------------- # 23 | # Returns true if we are attached to a pipe or false if not. # 24 | # -------------------------------------------------------------------------------- # 25 | 26 | function in_pipe() 27 | { 28 | [[ -p /dev/stdout ]] && return 0 || return 1; 29 | } 30 | 31 | # -------------------------------------------------------------------------------- # 32 | # in_redirection # 33 | # -------------------------------------------------------------------------------- # 34 | # Returns true if we are attached to a redirection or false if not. # 35 | # -------------------------------------------------------------------------------- # 36 | 37 | function in_redirection() 38 | { 39 | [[ ! -t 1 && ! -p /dev/stdout ]] && return 0 || return 1; 40 | } 41 | 42 | # -------------------------------------------------------------------------------- # 43 | # Run Tests # 44 | # -------------------------------------------------------------------------------- # 45 | # A VERY simple test function to ensure that it all works # 46 | # -------------------------------------------------------------------------------- # 47 | 48 | function run_test() 49 | { 50 | in_terminal && echo 'STDOUT is attached to TTY' 51 | 52 | in_pipe && echo 'STDOUT is attached to a pipe' 53 | 54 | in_redirection && echo 'STDOUT is attached to a redirection' 55 | } 56 | 57 | # -------------------------------------------------------------------------------- # 58 | # Main() # 59 | # -------------------------------------------------------------------------------- # 60 | # This is the actual 'script' and the functions/sub routines are called in order. # 61 | # -------------------------------------------------------------------------------- # 62 | 63 | run_test 64 | 65 | # -------------------------------------------------------------------------------- # 66 | # End of Script # 67 | # -------------------------------------------------------------------------------- # 68 | # This is the end - nothing more to see here. # 69 | # -------------------------------------------------------------------------------- # 70 | -------------------------------------------------------------------------------- /src/variable-replace/variable-replace.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # Replace template variables in a file with values from an associative array. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Ref Array # 11 | # -------------------------------------------------------------------------------- # 12 | # Take the name of an array and create a vaid reference to it. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | function ref_array() 16 | { 17 | local varname="$1" 18 | local export_as="$2" 19 | local code 20 | 21 | code=$(declare -p "$varname") 22 | 23 | echo "${code/$varname/$export_as}" 24 | } 25 | 26 | # -------------------------------------------------------------------------------- # 27 | # Replace Variables # 28 | # -------------------------------------------------------------------------------- # 29 | # Take the name of an array and create a vaid reference to it. # 30 | # -------------------------------------------------------------------------------- # 31 | 32 | function replace_variables() 33 | { 34 | eval "$(ref_array "$1" array)" 35 | filename="${2}" 36 | 37 | local i 38 | local search 39 | local replace 40 | 41 | # shellcheck disable=SC2154 42 | for i in "${!array[@]}"; do 43 | search="${i}" 44 | replace="${array[$i]}" 45 | 46 | if grep -q "${search}" "${filename}"; then 47 | sed -i '' "s/${search}/${replace}/g" "${filename}" 48 | printf "Replaced %s with %s\n" "${search}" "${replace}" 49 | fi 50 | done 51 | } 52 | 53 | # -------------------------------------------------------------------------------- # 54 | # Run Tests # 55 | # -------------------------------------------------------------------------------- # 56 | # A VERY simple test function to ensure that it all works # 57 | # -------------------------------------------------------------------------------- # 58 | 59 | function run_tests() 60 | { 61 | declare -A config 62 | 63 | # shellcheck disable=SC2034 64 | config=( 65 | ['{{ USERNAME_PLACE_HOLDER }}']='admin' 66 | ['{{ PASSWORD_PLACE_HOLDER }}']='password' 67 | ) 68 | 69 | replace_variables "config" "test.sh" 70 | } 71 | 72 | # -------------------------------------------------------------------------------- # 73 | # Main() # 74 | # -------------------------------------------------------------------------------- # 75 | # This is the actual 'script' and the functions/sub routines are called in order. # 76 | # -------------------------------------------------------------------------------- # 77 | 78 | run_tests "$@" 79 | 80 | # -------------------------------------------------------------------------------- # 81 | # End of Script # 82 | # -------------------------------------------------------------------------------- # 83 | # This is the end - nothing more to see here. # 84 | # -------------------------------------------------------------------------------- # 85 | -------------------------------------------------------------------------------- /src/get-script-info/get-script-info.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to show how to get get the script base path and name. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | READONLY_INFO=true # Set the script info to READONLY 10 | 11 | # -------------------------------------------------------------------------------- # 12 | # Get Script Info # 13 | # -------------------------------------------------------------------------------- # 14 | # Work out some basic facts about the script, how it was called, where it lives, # 15 | # what it is called etc. # 16 | # -------------------------------------------------------------------------------- # 17 | 18 | function get_script_info() 19 | { 20 | local ro=${READONLY_INFO:-false} 21 | 22 | [[ $0 != "${BASH_SOURCE[0]}" ]] && IS_SOURCED=true || IS_SOURCED=false 23 | 24 | READONLY=false 25 | INVOKED_FILE="${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}" 26 | INVOKED_PATH="$(dirname "${BASH_SOURCE[${#BASH_SOURCE[@]} - 1]}")" 27 | FULL_PATH="$( cd -P "$(dirname "${BASH_SOURCE[0]}")" && pwd )" 28 | FILE_NAME=$(basename "${BASH_SOURCE[0]}") 29 | 30 | if [[ $# -gt 0 ]]; then 31 | SCRIPT_ARGS=$(printf "'%s', " "${@}") 32 | SCRIPT_ARGS=${SCRIPT_ARGS::-2} # Trim off the last comma and space 33 | else 34 | SCRIPT_ARGS="None" 35 | fi 36 | 37 | if [[ "${ro}" = true ]] 38 | then 39 | readonly IS_SOURCED 40 | readonly INVOKED_FILE 41 | readonly INVOKED_PATH 42 | readonly FULL_PATH 43 | readonly FILE_NAME 44 | readonly SCRIPT_ARGS 45 | fi 46 | 47 | export READONLY 48 | export IS_SOURCED 49 | export INVOKED_FILE 50 | export INVOKED_PATH 51 | export FULL_PATH 52 | export FILE_NAME 53 | export SCRIPT_ARGS 54 | } 55 | 56 | # -------------------------------------------------------------------------------- # 57 | # Run Tests # 58 | # -------------------------------------------------------------------------------- # 59 | # A VERY simple test function to ensure that it all works # 60 | # -------------------------------------------------------------------------------- # 61 | 62 | function run_tests() 63 | { 64 | get_script_info "${@}" 65 | 66 | echo "Read Only? : ${READONLY}" 67 | echo "Sourced? : ${IS_SOURCED}" 68 | echo "Invoked File: ${INVOKED_FILE}" 69 | echo "Invoked Path: ${INVOKED_PATH}" 70 | echo "Full Path: ${FULL_PATH}" 71 | echo "Script Name: ${FILE_NAME}" 72 | echo "Script Args: ${SCRIPT_ARGS}" 73 | } 74 | 75 | # -------------------------------------------------------------------------------- # 76 | # Main() # 77 | # -------------------------------------------------------------------------------- # 78 | # This is the actual 'script' and the functions/sub routines are called in order. # 79 | # -------------------------------------------------------------------------------- # 80 | 81 | run_tests "$@" 82 | 83 | # -------------------------------------------------------------------------------- # 84 | # End of Script # 85 | # -------------------------------------------------------------------------------- # 86 | # This is the end - nothing more to see here. # 87 | # -------------------------------------------------------------------------------- # 88 | 89 | -------------------------------------------------------------------------------- /src/get-git-root/get-git-root.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # A script to work out the root of a given git repo. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Get Git Root # 11 | # -------------------------------------------------------------------------------- # 12 | # Look at a supplied dir to see if it cointains a git repo and if so calculate the # 13 | # root of that repo. # 14 | # -------------------------------------------------------------------------------- # 15 | 16 | function get_git_root() 17 | { 18 | local root 19 | local retval 20 | 21 | # 22 | # Execute everything as a subshell to avoid messing up users current directory position 23 | # 24 | ( 25 | # 26 | # If we are checking a directory which is not the current one then cd to the specificed directory 27 | # 28 | if [[ -n $1 ]]; then 29 | if [[ ! -d $1 ]]; then 30 | echo "$1 is not a valid directory" 31 | return 1 32 | fi 33 | cd "${1}" || return 1 34 | fi 35 | 36 | # 37 | # If we are in a .git directory we need to get out of it 38 | # 39 | if git rev-parse --is-inside-git-dir > /dev/null 2>&1; then 40 | while [[ $(git rev-parse --is-inside-git-dir) == true ]]; do 41 | cd .. 42 | done 43 | fi 44 | 45 | # 46 | # Check to see if we are in a real git repo dir or not 47 | # 48 | if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then 49 | root=$(git rev-parse --show-toplevel) 50 | retval=0 51 | else 52 | root="${PWD} is not a git repo" 53 | retval=1 54 | fi 55 | 56 | echo "${root}" 57 | return $retval 58 | ) 59 | } 60 | 61 | # -------------------------------------------------------------------------------- # 62 | # Run Tests # 63 | # -------------------------------------------------------------------------------- # 64 | # A VERY simple test function to ensure that it all works # 65 | # -------------------------------------------------------------------------------- # 66 | 67 | function run_test() 68 | { 69 | declare -a dirs=('./' '/home' '/thiswillerror') 70 | 71 | ## now loop through the above array 72 | for i in "${dirs[@]}" 73 | do 74 | echo "Testing: ${i}" 75 | if root=$(get_git_root "${i}"); then 76 | echo "Repo Root = $root" 77 | else 78 | echo "Error: $root" 79 | fi 80 | done 81 | } 82 | 83 | # -------------------------------------------------------------------------------- # 84 | # Main() # 85 | # -------------------------------------------------------------------------------- # 86 | # This is the actual 'script' and the functions/sub routines are called in order. # 87 | # -------------------------------------------------------------------------------- # 88 | 89 | run_test "$@" 90 | 91 | # -------------------------------------------------------------------------------- # 92 | # End of Script # 93 | # -------------------------------------------------------------------------------- # 94 | # This is the end - nothing more to see here. # 95 | # -------------------------------------------------------------------------------- # 96 | 97 | -------------------------------------------------------------------------------- /src/error-messages/error-messages.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to display errors, warning and success messages. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | 10 | # -------------------------------------------------------------------------------- # 11 | # Show Error # 12 | # -------------------------------------------------------------------------------- # 13 | # A simple wrapper function to show something was an error. # 14 | # -------------------------------------------------------------------------------- # 15 | 16 | function show_error() 17 | { 18 | if [[ -n $1 ]]; then 19 | printf '%s%s%s\n' "${red}" "${*}" "${reset}" 1>&2 20 | fi 21 | } 22 | 23 | # -------------------------------------------------------------------------------- # 24 | # Show Warning # 25 | # -------------------------------------------------------------------------------- # 26 | # A simple wrapper function to show something was a warning. # 27 | # -------------------------------------------------------------------------------- # 28 | 29 | function show_warning() 30 | { 31 | if [[ -n $1 ]]; then 32 | printf '%s%s%s\n' "${yellow}" "${*}" "${reset}" 1>&2 33 | fi 34 | } 35 | 36 | # -------------------------------------------------------------------------------- # 37 | # Show Success # 38 | # -------------------------------------------------------------------------------- # 39 | # A simple wrapper function to show something was a success. # 40 | # -------------------------------------------------------------------------------- # 41 | 42 | function show_success() 43 | { 44 | if [[ -n $1 ]]; then 45 | printf '%s%s%s\n' "${green}" "${*}" "${reset}" 1>&2 46 | fi 47 | } 48 | 49 | # -------------------------------------------------------------------------------- # 50 | # Get Colours # 51 | # -------------------------------------------------------------------------------- # 52 | # A very simple wrapper which can dynamically get the required colours. # 53 | # -------------------------------------------------------------------------------- # 54 | 55 | function get_colours() 56 | { 57 | local ncolors 58 | 59 | red='' 60 | yellow='' 61 | green='' 62 | reset='' 63 | 64 | if ! test -t 1; then 65 | return 66 | fi 67 | 68 | if ! tput longname > /dev/null 2>&1; then 69 | return 70 | fi 71 | 72 | ncolors=$(tput colors) 73 | 74 | if ! test -n "${ncolors}" || test "${ncolors}" -le 7; then 75 | return 76 | fi 77 | 78 | red=$(tput setaf 1) 79 | yellow=$(tput setaf 3) 80 | green=$(tput setaf 2) 81 | reset=$(tput sgr0) 82 | 83 | readonly red 84 | readonly yellow 85 | readonly green 86 | readonly reset 87 | 88 | declare -g red 89 | declare -g yellow 90 | declare -g green 91 | declare -g reset 92 | 93 | } 94 | 95 | # -------------------------------------------------------------------------------- # 96 | # Run Tests # 97 | # -------------------------------------------------------------------------------- # 98 | # A VERY simple test function to ensure that it all works # 99 | # -------------------------------------------------------------------------------- # 100 | 101 | function run_test() 102 | { 103 | get_colours 104 | 105 | show_error "This is an error" 106 | show_warning "This is a warning" 107 | show_success "This is a success" 108 | } 109 | 110 | # -------------------------------------------------------------------------------- # 111 | # Main() # 112 | # -------------------------------------------------------------------------------- # 113 | # This is the actual 'script' and the functions/sub routines are called in order. # 114 | # -------------------------------------------------------------------------------- # 115 | 116 | run_test 117 | 118 | # -------------------------------------------------------------------------------- # 119 | # End of Script # 120 | # -------------------------------------------------------------------------------- # 121 | # This is the end - nothing more to see here. # 122 | # -------------------------------------------------------------------------------- # 123 | 124 | -------------------------------------------------------------------------------- /src/strict-mode/strict-mode.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is an example of the header of a bash script running in 'strict' mode. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Errexit # 11 | # -------------------------------------------------------------------------------- # 12 | # Exit on error. Append "|| true" if you expect an error # 13 | # # 14 | # Shortcut: set -e # 15 | # -------------------------------------------------------------------------------- # 16 | set -o errexit 17 | 18 | # -------------------------------------------------------------------------------- # 19 | # Nounset # 20 | # -------------------------------------------------------------------------------- # 21 | # Do not allow use of undefined vars. Use ${VAR:-} to use an undefined VAR # 22 | # # 23 | # Shortcut: set -u # 24 | # -------------------------------------------------------------------------------- # 25 | set -o nounset 26 | 27 | # -------------------------------------------------------------------------------- # 28 | # Pipefail # 29 | # -------------------------------------------------------------------------------- # 30 | # Catch the error in case mysqldump fails (but gzip succeeds) in `mysqldump |gzip` # 31 | # # 32 | # Shortcut: none # 33 | # -------------------------------------------------------------------------------- # 34 | set -o pipefail 35 | 36 | # -------------------------------------------------------------------------------- # 37 | # Xtrace # 38 | # -------------------------------------------------------------------------------- # 39 | # Turn on traces, useful while debugging but commented out by default # 40 | # # 41 | # Shortcut: set -x # 42 | # -------------------------------------------------------------------------------- # 43 | [[ -n ${DEBUG:-} ]] && set -o xtrace 44 | 45 | # -------------------------------------------------------------------------------- # 46 | # IFS # 47 | # -------------------------------------------------------------------------------- # 48 | # Defines newlines and tabs as delimiters for splitting words and iterating arrays # 49 | # -------------------------------------------------------------------------------- # 50 | IFS=$'\n\t' 51 | 52 | # -------------------------------------------------------------------------------- # 53 | # Run Tests # 54 | # -------------------------------------------------------------------------------- # 55 | # A VERY simple test function to ensure that it all works # 56 | # -------------------------------------------------------------------------------- # 57 | 58 | function run_tests() 59 | { 60 | local filename="strict-mode.sh" 61 | local string="test" 62 | 63 | # Gotcha Number 1: 64 | 65 | # Under strict mode, the next line aborts with an error: 66 | # count=$(grep -c "${string}" "${filename}") 67 | 68 | # But this one behaves more nicely: 69 | count=$(grep -c "${string}" "${filename}" || true) 70 | 71 | echo "count: $count" 72 | 73 | # Gotcha Number 2: 74 | 75 | # Testing for non-existant variables cannot simply be done with a -z 76 | # as this will error for an unbounded variable. Use ${name:-} instead 77 | 78 | [[ -z "${UNDECLARED_VARIABLE:-}" ]] && echo "I am undeclared!" 79 | } 80 | 81 | # -------------------------------------------------------------------------------- # 82 | # Main() # 83 | # -------------------------------------------------------------------------------- # 84 | # This is the actual 'script' and the functions/sub routines are called in order. # 85 | # -------------------------------------------------------------------------------- # 86 | 87 | run_tests 88 | 89 | # -------------------------------------------------------------------------------- # 90 | # End of Script # 91 | # -------------------------------------------------------------------------------- # 92 | # This is the end - nothing more to see here. # 93 | # -------------------------------------------------------------------------------- # 94 | -------------------------------------------------------------------------------- /src/rollingback/rollingback.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to demonstrate how rollbacks can be used. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Global Variables # 11 | # -------------------------------------------------------------------------------- # 12 | # This is an array that is used to store the rollback functions that need to run. # 13 | # -------------------------------------------------------------------------------- # 14 | 15 | rollback_stack=( ) 16 | 17 | # -------------------------------------------------------------------------------- # 18 | # ABC # 19 | # -------------------------------------------------------------------------------- # 20 | # A dummy demo rollback function. # 21 | # -------------------------------------------------------------------------------- # 22 | 23 | function abc() 24 | { 25 | echo "abc----$1"; 26 | } 27 | 28 | # -------------------------------------------------------------------------------- # 29 | # DEF # 30 | # -------------------------------------------------------------------------------- # 31 | # A dummy demo rollback function. # 32 | # -------------------------------------------------------------------------------- # 33 | 34 | function def() 35 | { 36 | echo "def----$1"; 37 | } 38 | 39 | # -------------------------------------------------------------------------------- # 40 | # Add Rollback # 41 | # -------------------------------------------------------------------------------- # 42 | # Add a rollback function to the stack. # 43 | # -------------------------------------------------------------------------------- # 44 | 45 | function add_rollback() 46 | { 47 | rollback_stack[${#rollback_stack[*]}]=$1; 48 | } 49 | 50 | # -------------------------------------------------------------------------------- # 51 | # Run Rollback # 52 | # -------------------------------------------------------------------------------- # 53 | # Run all of the rollback function. # 54 | # # 55 | # It is important to understand that rollbacks are run in the opposite order to # 56 | # which they are added as the rollback is a 'stack' [aka a LIFO]. # 57 | # # 58 | # It is 'important' to unset the traps before running the rollback otherwise # 59 | # errors in the rollback code could trigger another rollback and a possible loop. # 60 | # -------------------------------------------------------------------------------- # 61 | 62 | function run_rollbacks() 63 | { 64 | unset_traps 65 | 66 | printf '\nTrap Triggers - Running Rollbacks\n\n' 67 | 68 | while [ ${#rollback_stack[@]} -ge 1 ]; do 69 | ${rollback_stack[${#rollback_stack[@]}-1]} rollback 70 | unset "rollback_stack[${#rollback_stack[@]}-1]" 71 | done 72 | 73 | exit 74 | } 75 | 76 | # -------------------------------------------------------------------------------- # 77 | # Set Traps # 78 | # -------------------------------------------------------------------------------- # 79 | # We only want the rollbacks to run on error - so we set up traps to catch the # 80 | # errors and handle the rollbacks. # 81 | # -------------------------------------------------------------------------------- # 82 | 83 | function set_traps() 84 | { 85 | trap run_rollbacks INT TERM EXIT 86 | } 87 | 88 | # -------------------------------------------------------------------------------- # 89 | # Unset Traps # 90 | # -------------------------------------------------------------------------------- # 91 | # Once everything has run cleanly we want to reset the traps, otherwise exiting # 92 | # the script will cause the rollbacks to run undoing all the scripts good work. # 93 | # -------------------------------------------------------------------------------- # 94 | 95 | function unset_traps() 96 | { 97 | trap - INT TERM EXIT 98 | } 99 | 100 | # -------------------------------------------------------------------------------- # 101 | # Run Tests # 102 | # -------------------------------------------------------------------------------- # 103 | # A VERY simple test function to ensure that it all works. # 104 | # -------------------------------------------------------------------------------- # 105 | 106 | function run_tests() 107 | { 108 | set_traps 109 | 110 | add_rollback abc 111 | add_rollback def 112 | 113 | printf '\nSleeping for the next 10 seconds - try hitting '\''control C'\'' to see the rollbacks in action\n\n' 114 | sleep 10 115 | printf '\nSleeping Over - Exiting cleanly\n\n' 116 | 117 | unset_traps 118 | } 119 | 120 | # -------------------------------------------------------------------------------- # 121 | # Main() # 122 | # -------------------------------------------------------------------------------- # 123 | # This is the actual 'script' and the functions/sub routines are called in order. # 124 | # -------------------------------------------------------------------------------- # 125 | 126 | run_tests 127 | 128 | # -------------------------------------------------------------------------------- # 129 | # End of Script # 130 | # -------------------------------------------------------------------------------- # 131 | # This is the end - nothing more to see here. # 132 | # -------------------------------------------------------------------------------- # 133 | -------------------------------------------------------------------------------- /src/compare-versions/compare-versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # -------------------------------------------------------------------------------- # 4 | # Description # 5 | # -------------------------------------------------------------------------------- # 6 | # This is a simple script to compare 2 version strings. # 7 | # -------------------------------------------------------------------------------- # 8 | 9 | # -------------------------------------------------------------------------------- # 10 | # Compare Version # 11 | # -------------------------------------------------------------------------------- # 12 | # Compare 2 version strings, they can be different lengths, and the delimiter can # 13 | # also be specificed. # 14 | # # 15 | # Caveat: This only works for numeric version strings. # 16 | # -------------------------------------------------------------------------------- # 17 | 18 | function compare_versions() 19 | { 20 | if [[ $1 == "${2}" ]]; then 21 | return 0 22 | fi 23 | 24 | if (($# == 3)); then 25 | IFS=$3 26 | else 27 | IFS=. 28 | fi 29 | 30 | local i ver1 ver2 31 | 32 | read -r -a ver1 <<< "${1}" 33 | read -r -a ver2 <<< "${2}" 34 | 35 | max=$(( ${#ver1[@]} > ${#ver2[@]} ? ${#ver1[@]} : ${#ver2[@]} )) 36 | 37 | for ((i=0; i 10#${ver2[i]:-0})); then 42 | return 1 43 | fi 44 | done 45 | #if [ "$arem" '<' "$brem" ]; then 46 | # return 2 47 | #elif [ "$arem" '>' "$brem" ]; then 48 | # return 1 49 | #fi 50 | return 0 51 | } 52 | 53 | function test_wrapper() 54 | { 55 | if (($# < 2)) || (($# > 4)); then 56 | echo "Incorrect number of arguments" 57 | return 255 58 | fi 59 | 60 | if (($# == 4)); then 61 | compare_versions "${1}" "${2}" "${4}" 62 | else 63 | compare_versions "${1}" "${2}" 64 | fi 65 | 66 | case $? in 67 | 255) op='!!';; 68 | 0) op='=';; 69 | 1) op='>';; 70 | 2) op='<';; 71 | *) 72 | esac 73 | 74 | if [[ $3 =~ ${op} ]]; then 75 | echo " Pass: '$1 $3 $2'" 76 | else 77 | echo " FAIL: Expected '$3', Actual '${op}', Arg1 '$1', Arg2 '$2'" 78 | fi 79 | } 80 | 81 | # -------------------------------------------------------------------------------- # 82 | # Run Tests # 83 | # -------------------------------------------------------------------------------- # 84 | # A VERY simple test function to ensure that it all works # 85 | # -------------------------------------------------------------------------------- # 86 | 87 | function run_test() 88 | { 89 | echo "Simple Equivalence tests" 90 | test_wrapper "1" "1" "=" 91 | test_wrapper "5.6.7" "5.6.7" "=" 92 | echo 93 | 94 | echo "Advanced Equivalence tests" 95 | test_wrapper "1.01.1" "1.1.1" "=" 96 | test_wrapper "1.1.1" "1.01.1" "=" 97 | test_wrapper "1" "1.0" "=" 98 | test_wrapper "1.0" "1" "=" 99 | test_wrapper "1.0.2.0" "1.0.2" "=" 100 | test_wrapper "1..0" "1.0" "=" 101 | test_wrapper "1.0" "1..0" "=" 102 | echo 103 | 104 | echo "Less than tests" 105 | test_wrapper "1.2" "2.1" "<" 106 | test_wrapper "2.1" "2.2" "<" 107 | test_wrapper "4.08" "4.08.01" "<" 108 | test_wrapper "3.2" "3.2.1.9.8144" "<" 109 | test_wrapper "1.0" "1..1" "<" 110 | echo 111 | 112 | echo "Greater than tests" 113 | test_wrapper "2.1" "1.2" ">" 114 | test_wrapper "2.2" "2.1" ">" 115 | test_wrapper "3.0.4.10" "3.0.4.2" ">" 116 | test_wrapper "3.2.1.9.8144" "3.2" ">" 117 | test_wrapper "1..1" "1.0" ">" 118 | test_wrapper "3.0.4.10" "3.0.4.2" ">" 119 | echo 120 | 121 | echo "Less than or equal to tests" 122 | test_wrapper "1.2" "1.2" "<=" 123 | test_wrapper "1.2" "2.1" "<=" 124 | test_wrapper "4.08" "4.08.01" "<=" 125 | test_wrapper "3.2" "3.2.1.9.8144" "<=" 126 | test_wrapper "1.0" "1..1" "<=" 127 | test_wrapper "1.0" "1..0" "<=" 128 | echo 129 | 130 | echo "Greater than tests" 131 | test_wrapper "1.2" "1.2" ">=" 132 | test_wrapper "2.1" "1.2" ">=" 133 | test_wrapper "3.0.4.10" "3.0.4.2" ">=" 134 | test_wrapper "3.2.1.9.8144" "3.2" ">=" 135 | test_wrapper "1..1" "1.0" ">=" 136 | test_wrapper "1.0" "1..0" ">=" 137 | echo 138 | 139 | echo "Not Equal to tests" 140 | test_wrapper "2.1" "1.2" "<>" 141 | test_wrapper "2.2" "2.1" "<>" 142 | test_wrapper "3.0.4.10" "3.0.4.2" "<>" 143 | test_wrapper "3.2.1.9.8144" "3.2" "<>" 144 | test_wrapper "1..1" "1.0" "<>" 145 | echo 146 | 147 | echo "Custom delimiter tests" 148 | test_wrapper "1|01|1" "1|1|1" "=" "|" 149 | test_wrapper "4-08" "4-08-01" "<" "-" 150 | test_wrapper "3-2" "3-2-1-9-8144" "<" "-" 151 | test_wrapper "2/1" "1/2" ">" "/" 152 | test_wrapper "2#1" "2#2" "<" "#" 153 | test_wrapper "3=0=4=10" "3=0=4=2" ">" "=" 154 | test_wrapper "3^2^1^9^8144" "3^2" ">=" "^" 155 | test_wrapper "1##1" "1#0" "<>" "#" 156 | echo 157 | } 158 | 159 | # -------------------------------------------------------------------------------- # 160 | # Main() # 161 | # -------------------------------------------------------------------------------- # 162 | # This is the actual 'script' and the functions/sub routines are called in order. # 163 | # -------------------------------------------------------------------------------- # 164 | 165 | run_test "$@" 166 | 167 | # -------------------------------------------------------------------------------- # 168 | # End of Script # 169 | # -------------------------------------------------------------------------------- # 170 | # This is the end - nothing more to see here. # 171 | # -------------------------------------------------------------------------------- # 172 | 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | DevelopersToolbox logo 5 | 6 |
7 | 8 | Github Build Status 9 | 10 | 11 | License 12 | 13 | 14 | Created 15 | 16 |
17 | 18 | Release 19 | 20 | 21 | Released 22 | 23 | 24 | Commits since release 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |

40 | 41 | ## Overview 42 | 43 | This is a collection of useful(ish) bash snippets. The snippets are all simple self-contained pieces of code (a class or subroutine), but non of them are large enough to require having a repository in their own right. 44 | 45 | ## Bash Snippets 46 | 47 | | Name | Description | 48 | | ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | 49 | | [abs.sh](src/abs/abs.sh) | The Math. abs() function returns the absolute value of a number. That is, it returns x if x is positive or zero, and the negation of x if x is negative. | 50 | | [array-contains.sh](src/array-contains/array-contains.sh) | Check to see if an array contains a specific value. | 51 | | [array-to-string.sh](src/array-to-string/array-to-string.sh) | Convert an array to a string with a custom separator and a final optional value. | 52 | | [center-text.sh](src/center-text/center-text.sh) | Center any given text on the screen (optional define the screen width). | 53 | | [check-prerequisites.sh](src/check-prerequisites/check-prerequisites.sh) | Check prerequisite commands are installed. | 54 | | [compare-versions.sh](src/compare-versions/compare-versions.sh) | Compare two version strings with optional custom delimiter. | 55 | | [contains.sh](src/contains/contains.sh) | Check to see if one string contains another. | 56 | | [countdown.sh](src/countdown/countdown.sh) | Display a simple countdown timer and message. | 57 | | [error-messages.sh](src/error-messages/error-messages.sh) | Display error, warning and success messages. | 58 | | [get-confirmation.sh](src/get-confirmation/get-confirmation.sh) | Get user confirmation for an action. | 59 | | [get-git-root.sh](src/get-git-root/get-git-root.sh) | Get the root directory of a given git repo (and handle correctly when it isn't a git repo). | 60 | | [get-script-info.sh](src/get-script-info/get-script-info.sh) | Get information about a script (full path and script name). | 61 | | [get-terraform-version.sh](src/get-terraform-version/get-terraform-version.sh) | Get the current terraform version. | 62 | | [get-version-string.sh](src/get-version-string/get-version-string.sh) | Extract a semver version from a string. | 63 | | [is-git-repo.sh](src/is-git-repo/is-git-repo.sh) | Check if a given directory contains a git repo. | 64 | | [rollingback.sh](src/rollingback/rollingback.sh) | Using signals to create rollback functions for cleaner scripting. | 65 | | [stacktrace.sh](src/stacktrace/stacktrace.sh) | Provide a stack trace for from main to the point of of calling the stacktrace. | 66 | | [strict-mode.sh](src/strict-mode/strict-mode.sh) | An example of a 'strict' mode setup for bash scripts. | 67 | | [sudo-librarian-puppet.sh](src/sudo-librarian-puppet/sudo-librarian-puppet.sh ) | Run librarian-puppet via sudo without changing default sudoers file (Debian 9 / Puppet 5). | 68 | | [terminal-or-not.sh](src/terminal-or-not/terminal-or-not.sh) | A script to allow to determine if your script is attached to a terminal, pipe or redirection. | 69 | | [untag.sh](src/untag/untag.sh) | A simple script to remove ALL tags from a git repo. | 70 | | [using-colour.sh](src/using-colour/using-colour.sh) | An example of how to use colour (see [bash-colour-include](https://github.com/DevelopersToolbox/bash-colour-include) for a full working solution). | 71 | | [using-set.sh](src/using-set/using-set.sh) | Using 'set' for more robust shell scripting. | 72 | | [variable-replace.sh](src/variable-replace/variable-replace.sh) | Replace template variables in a file with values from an associative array. | 73 | | [verbose-mode.sh](src/verbose-mode/verbose-mode.sh) | Demonstration of script wide verbose/silent mode. | 74 | 75 |
76 |

77 | --------------------------------------------------------------------------------