diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..a862cd4 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at **[EMAIL REQUIRED]**. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [https://www.contributor-covenant.org/version/1/4/code-of-conduct.html](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html) + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..d6be7cd --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,24 @@ +# Contributing + +Thanks for your interest in contributing to the **PSPreworkout Project**. + +Whether it's a bug report, new feature, correction, or additional documentation, your feedback and contributions are appreciated. + +Please read through this document before submitting any issues or pull requests to ensure all the necessary information is provided to effectively respond to your bug report or contribution. + +Please note there is a code of conduct, please follow it in all your interactions with the project. + +## Reporting Bugs/Feature Requests + +## Contributing via Pull Requests + +## Finding contributions to work on + +## Code of Conduct + +This project has a [Code of Conduct](CODE_OF_CONDUCT.md). + +## Licensing + +See the [LICENSE](LICENSE.txt) file for our project's licensing. + diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 01bb2d6..67f3c29 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -1,38 +1,39 @@ ---- -name: Bug Report -about: Create a report to help us improve -title: '' -labels: bug -assignees: SamErde - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. +--- +name: Bug report +about: Submit a new bug +title: Bug report +labels: 'bug' +assignees: '' + +--- + + + +### Expected Behavior + + +### Current Behavior + + +### Possible Solution + + +### Steps to Reproduce + + + +1. +2. +3. +4. + +### Context (Environment) + + +* Operating System and version as reported by `$PSVersionTable.OS`: +* PowerShell versions as reported by `$PSVersionTable.PSEdition`: + + + +### Detailed Description + diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index acd6a9a..0000000 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature Request -about: Suggest an idea for this project -title: '' -labels: enhancement -assignees: SamErde - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..cb1a9fb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: 'Feature request' +labels: 'enhancement' +assignees: '' + +--- + +### Description + + +### Describe the solution you'd like + + +### Describe any alternatives you've considered + + +### Additional context + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..a7660f8 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,13 @@ +# Pull Request + +## Issue + +Issue #, if available: + +## Description + +Description of changes: + +## License + +By submitting this pull request, I confirm that my contribution is made under the terms of the projects associated license. diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..3b7b6fd --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,19 @@ +# Security Policy + +## Reporting a Vulnerability + + + +If you discover a vulnerability in PSPreworkout, please follow the _following process_: + +1. Open a generic bug issue advising you have discovered a vulnerability. + - Avoid sharing specifics or details of the vulnerability in an open GitHub issue. +2. A repo owner will reach out to you to establish a private form of communication. +3. We will evaluate the vulnerability and, if necessary, release a fix or mitigating steps to address it. We will contact you to let you know the outcome, and will credit you in the report. + + Please **do not disclose the vulnerability publicly** until a fix is released! + +4. Once we have either a) published a fix, or b) declined to address the vulnerability for whatever reason, you are free to publicly disclose it. + diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml deleted file mode 100644 index 7b6c4d8..0000000 --- a/.github/workflows/mega-linter.yml +++ /dev/null @@ -1,179 +0,0 @@ -# MegaLinter GitHub Action configuration file -# More info at https://megalinter.io ---- -name: MegaLinter - -# Trigger mega-linter at every push. Action will also be visible from Pull -# Requests to main -on: - # Comment this line to trigger action only on pull-requests - # (not recommended if you don't pay for GH Actions) - push: - - pull_request: - branches: - - main - - master - -# Comment env block if you do not want to apply fixes -env: - # Apply linter fixes configuration - # - # When active, APPLY_FIXES must also be defined as environment variable - # (in github/workflows/mega-linter.yml or other CI tool) - APPLY_FIXES: all - - # Decide which event triggers application of fixes in a commit or a PR - # (pull_request, push, all) - APPLY_FIXES_EVENT: pull_request - - # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) - # or posted in a PR (pull_request) - APPLY_FIXES_MODE: commit - -concurrency: - group: ${{ github.ref }}-${{ github.workflow }} - cancel-in-progress: true - -jobs: - megalinter: - name: MegaLinter - runs-on: ubuntu-latest - - # Give the default GITHUB_TOKEN write permission to commit and push, comment - # issues & post new PR; remove the ones you do not need - permissions: - contents: write - issues: write - pull-requests: write - - steps: - - # Git Checkout - - name: Checkout Code - uses: actions/checkout@v4 - with: - token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} - - # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to - # improve performance - fetch-depth: 0 - - # MegaLinter - - name: MegaLinter - - # You can override MegaLinter flavor used to have faster performances - # More info at https://megalinter.io/flavors/ - uses: oxsecurity/megalinter/flavors/dotnet@v7.7.0 - - id: ml - - # All available variables are described in documentation - # https://megalinter.io/configuration/ - env: - - # Validates all source when push on main, else just the git diff with - # main. Override with true if you always want to lint all sources - # - # To validate the entire codebase, set to: - # VALIDATE_ALL_CODEBASE: true - # - # To validate only diff with main, set to: - # VALIDATE_ALL_CODEBASE: >- - # ${{ - # github.event_name == 'push' && - # contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref) - # }} - VALIDATE_ALL_CODEBASE: >- - ${{ - github.event_name == 'push' && - contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref) - }} - - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # ADD YOUR CUSTOM ENV VARIABLES HERE OR DEFINE THEM IN A FILE - # .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY - - # Uncomment to disable copy-paste and spell checks - # DISABLE: COPYPASTE,SPELL - DISABLE_ERRORS: true - DISABLE_LINTERS: SPELL_LYCHEE - # Uncomment DISABLE_ERRORS_LINTERS if you want to turn errors back on selectively. - # DISABLE_ERRORS_LINTERS: REPOSITORY_DEVSKIM,REPOSITORY_KICS,REPOSITORY_CHECKOV,POWERSHELL_POWERSHELL,SPELL_CSPELL - - # Upload MegaLinter artifacts - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - if: success() || failure() - with: - name: MegaLinter reports - path: | - megalinter-reports - mega-linter.log - - # Set APPLY_FIXES_IF var for use in future steps - - name: Set APPLY_FIXES_IF var - run: | - printf 'APPLY_FIXES_IF=%s\n' "${{ - steps.ml.outputs.has_updated_sources == 1 && - ( - env.APPLY_FIXES_EVENT == 'all' || - env.APPLY_FIXES_EVENT == github.event_name - ) && - ( - github.event_name == 'push' || - github.event.pull_request.head.repo.full_name == github.repository - ) - }}" >> "${GITHUB_ENV}" - - # Set APPLY_FIXES_IF_* vars for use in future steps - - name: Set APPLY_FIXES_IF_* vars - run: | - printf 'APPLY_FIXES_IF_PR=%s\n' "${{ - env.APPLY_FIXES_IF == 'true' && - env.APPLY_FIXES_MODE == 'pull_request' - }}" >> "${GITHUB_ENV}" - printf 'APPLY_FIXES_IF_COMMIT=%s\n' "${{ - env.APPLY_FIXES_IF == 'true' && - env.APPLY_FIXES_MODE == 'commit' && - (!contains(fromJSON('["refs/heads/main", "refs/heads/master"]'), github.ref)) - }}" >> "${GITHUB_ENV}" - - # Create pull request if applicable - # (for now works only on PR from same repository, not from forks) - - name: Create Pull Request with applied fixes - uses: peter-evans/create-pull-request@v5 - id: cpr - if: env.APPLY_FIXES_IF_PR == 'true' - with: - token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} - commit-message: "[MegaLinter] Apply linters automatic fixes" - title: "[MegaLinter] Apply linters automatic fixes" - labels: bot - - - name: Create PR output - if: env.APPLY_FIXES_IF_PR == 'true' - run: | - echo "PR Number - ${{ steps.cpr.outputs.pull-request-number }}" - echo "PR URL - ${{ steps.cpr.outputs.pull-request-url }}" - - # Push new commit if applicable - # (for now works only on PR from same repository, not from forks) - - name: Prepare commit - if: env.APPLY_FIXES_IF_COMMIT == 'true' - run: sudo chown -Rc $UID .git/ - - - name: Commit and push applied linter fixes - uses: stefanzweifel/git-auto-commit-action@v4 - if: env.APPLY_FIXES_IF_COMMIT == 'true' - with: - branch: >- - ${{ - github.event.pull_request.head.ref || - github.head_ref || - github.ref - }} - commit_message: "[MegaLinter] Apply linters fixes" - commit_user_name: megalinter-bot - commit_user_email: samuel.erde@gmail.com diff --git a/.github/workflows/powershell.yml b/.github/workflows/powershell.yml deleted file mode 100644 index 2d3b4bd..0000000 --- a/.github/workflows/powershell.yml +++ /dev/null @@ -1,49 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. -# -# https://github.com/microsoft/action-psscriptanalyzer -# For more information on PSScriptAnalyzer in general, see -# https://github.com/PowerShell/PSScriptAnalyzer - -name: PSScriptAnalyzer - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - schedule: - - cron: '39 17 * * 2' - -permissions: - contents: read - -jobs: - build: - permissions: - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/upload-sarif to upload SARIF results - actions: read # only required for a private repository by github/codeql-action/upload-sarif to get the Action run status - name: PSScriptAnalyzer - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - - name: Run PSScriptAnalyzer - uses: microsoft/psscriptanalyzer-action@6b2948b1944407914a58661c49941824d149734f - with: - # Check https://github.com/microsoft/action-psscriptanalyzer for more info about the options. - # The below set up runs PSScriptAnalyzer to your entire repository and runs some basic security rules. - path: .\ - recurse: true - # Include your own basic security rules. Removing this option will run all the rules - includeRule: '"PSAvoidGlobalAliases", "PSAvoidUsingConvertToSecureStringWithPlainText"' - output: results.sarif - - # Upload the SARIF file generated in the previous step - - name: Upload SARIF results file - uses: github/codeql-action/upload-sarif@v2 - with: - sarif_file: results.sarif diff --git a/.github/workflows/wf_MacOS.yml b/.github/workflows/wf_MacOS.yml new file mode 100644 index 0000000..68744d8 --- /dev/null +++ b/.github/workflows/wf_MacOS.yml @@ -0,0 +1,55 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: PSPreworkout-MacOS +on: + pull_request: + paths-ignore: + - '**.md' + - 'docs/**' + push: + paths-ignore: + - '**.md' + - 'docs/**' +jobs: + test: + name: Run Tests + runs-on: macOS-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v3 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + # uncomment below to explore what modules/variables/env variables are available in the build image + # - name: Modules and Variables Display + # shell: pwsh + # run: Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\PSPreworkout.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v3 + with: + name: pester-results + path: ./src/Artifacts/testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v3 + with: + name: zip-archive + path: ./src/Archive + if-no-files-found: warn + diff --git a/.github/workflows/wf_Windows_Core.yml b/.github/workflows/wf_Windows_Core.yml new file mode 100644 index 0000000..00d074c --- /dev/null +++ b/.github/workflows/wf_Windows_Core.yml @@ -0,0 +1,55 @@ +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/software-installed-on-github-hosted-runners +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#using-a-specific-shell +# https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions +# https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-powershell +# https://github.com/actions/upload-artifact#where-does-the-upload-go +name: PSPreworkout-Windows-pwsh +on: + pull_request: + paths-ignore: + - '**.md' + - 'docs/**' + push: + paths-ignore: + - '**.md' + - 'docs/**' +jobs: + test: + name: Run Tests + runs-on: windows-latest + strategy: + fail-fast: false + steps: + - name: Check out repository + uses: actions/checkout@v3 + - name: Display the path + shell: pwsh + run: echo ${env:PATH} + - name: Version Display + shell: pwsh + run: $PSVersionTable + # uncomment below to explore what modules/variables/env variables are available in the build image + # - name: Modules and Variables Display + # shell: pwsh + # run: Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String + - name: Bootstrap + shell: pwsh + run: ./actions_bootstrap.ps1 + - name: Test and Build + shell: pwsh + run: Invoke-Build -File .\src\PSPreworkout.build.ps1 + - name: Upload pester results + uses: actions/upload-artifact@v3 + with: + name: pester-results + path: .\src\Artifacts\testOutput + if-no-files-found: warn + - name: Upload zip module archive build + uses: actions/upload-artifact@v3 + with: + name: zip-archive + path: .\src\Archive + if-no-files-found: warn + diff --git a/.gitignore b/.gitignore index daf7536..ea04428 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,18 @@ -.DS_Store -desktop.ini -/Artefacts -/Artefacts/* -/Ignore -/Ignore/* +Archive +Artifacts +cov.xml +coverage.xml +/Artefacts +/Artefacts/* +/Ignore +/Ignore/* +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +desktop.ini +ehthumbs.db +Thumbs.db diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..da0338c --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,25 @@ +# https://docs.readthedocs.io/en/stable/config-file/index.html + +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +mkdocs: + configuration: mkdocs.yml + +python: + install: + - requirements: docs/requirements.txt + +# # Build PDF & ePub +formats: all +# - epub +# - pdf diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 38a6df4..7380068 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,7 +1,9 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "ms-vscode.PowerShell" - ] -} +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "ms-vscode.PowerShell", + "ryanluker.vscode-coverage-gutters", + "DavidAnson.vscode-markdownlint" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index aabfd89..b6d2d10 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,33 +1,9 @@ -// Place your settings in this file to overwrite default and user settings. -{ - "[*]": { - "editor.tabSize": 4, - "files.trimTrailingWhitespace": false, - "editor.insertSpaces": true, - "files.insertFinalNewline": true - }, - "[markdown]": { - "editor.tabSize": 2, - }, - "[json]": { - "editor.tabSize": 2, - }, +{ + // When enabled, will trim trailing whitespace when you save a file. + "files.trimTrailingWhitespace": true, + // specifies the location of the explicitly ScriptAnalyzer settings file + "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1", + // specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81) + "powershell.codeFormatting.preset":"OTBS" +} - // Sets the codeformatting options to follow the given indent style in a way that is compatible with PowerShell syntax. For more information about the brace styles please refer to https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81. - "powershell.codeFormatting.preset": "OTBS", - - // Adds a space between a keyword and its associated scriptblock expression. - "powershell.codeFormatting.whitespaceBeforeOpenBrace": true, - - // Adds a space between a keyword (if, elseif, while, switch, etc) and its associated conditional expression. - "powershell.codeFormatting.whitespaceBeforeOpenParen": true, - - // Adds spaces before and after an operator ('=', '+', '-', etc.). - "powershell.codeFormatting.whitespaceAroundOperator": true, - - // Adds a space after a separator (',' and ';'). - "powershell.codeFormatting.whitespaceAfterSeparator": true, - - // Omnisharp : Enable EditorConfig support - "omnisharp.enableEditorConfigSupport": true -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..a40ffa9 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,269 @@ +// Portions of this file were generated using New-VSCodeTask.ps1 +// Modify the build script or tasks-merge.json and recreate. +// https://code.visualstudio.com/docs/editor/tasks +// Available variables which can be used inside of strings. +// https://code.visualstudio.com/docs/editor/variables-reference#_predefined-variables +// ${workspaceFolder}: path of the folder opened in VS Code +// ${workspaceFolderBasename} - name of the folder opened in VS Code without any slashes (/) +// ${file}: current opened file +// ${fileWorkspaceFolder} - current opened file's workspace folder +// ${relativeFile}: the current opened file relative to workspaceFolder +// ${relativeFileDirname}: current opened file's dirname relative to workspaceFolder +// ${fileBasename}: current opened file's basename +// ${fileBasenameNoExtension} - current opened file's basename with no file extension +// ${fileDirname}: current opened file's dirname +// ${fileExtname}: current opened file's extension +// ${cwd}: the current working directory of the spawned process +// ${lineNumber} - current selected line number in the active file +// ${selectedText} - current selected text in the active file +// ${execPath} - path to the running VS Code executable +// ${defaultBuildTask} - name of the default build task +// ${pathSeparator} - character used by the operating system to separate components in file paths +{ + "version": "2.0.0", + "windows": { + "options": { + "shell": { + // "executable": "powershell.exe", + "executable": "pwsh.exe", + "args": [ + "-NoProfile", + "-ExecutionPolicy", + "Bypass", + "-Command" + ] + } + } + }, + "linux": { + "options": { + "shell": { + "executable": "/usr/bin/pwsh", + "args": [ + "-NoProfile", + "-Command" + ] + } + } + }, + "osx": { + "options": { + "shell": { + "executable": "/usr/local/bin/pwsh", + "args": [ + "-NoProfile", + "-Command" + ] + } + } + }, + "tasks": [ + { + "label": ".", + "type": "shell", + "command": "$PSVersionTable;Invoke-Build -Task . -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "TestLocal", + "type": "shell", + "command": "Invoke-Build -Task TestLocal -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "HelpLocal", + "type": "shell", + "command": "Invoke-Build -Task HelpLocal -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "Clean", + "type": "shell", + "command": "Invoke-Build -Task Clean -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "ValidateRequirements", + "type": "shell", + "command": "Invoke-Build -Task ValidateRequirements -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "Analyze", + "type": "shell", + "problemMatcher": "$msCompile", + "command": "Invoke-Build -Task Analyze -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "AnalyzeTests", + "type": "shell", + "command": "Invoke-Build -Task AnalyzeTests -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "FormattingCheck", + "type": "shell", + "command": "Invoke-Build -Task FormattingCheck -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "Test", + "type": "shell", + "command": "Invoke-Build -Task Test -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": { + "kind": "test", + "isDefault": true + } + }, + { + "label": "DevCC", + "type": "shell", + "command": "Invoke-Build -Task DevCC -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "Build", + "type": "shell", + "command": "Invoke-Build -Task Build -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "none" + }, + { + "label": "BuildNoIntegration", + "type": "shell", + "command": "Invoke-Build -Task BuildNoIntegration -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "build" + }, + { + "label": "IntegrationTest", + "type": "shell", + "command": "Invoke-Build -Task IntegrationTest -File '${workspaceFolder}/src/${workspaceFolderBasename}.build.ps1'", + "problemMatcher": "$msCompile", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "PesterTest", + "type": "shell", + "command": "Invoke-Pester '${workspaceFolder}/src/Tests/Unit' -Output Detailed", + "problemMatcher": "$pester", + "group": "test" + }, + { + "label": "Pester-Single-Coverage", + "type": "shell", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';$pesterConfig = New-PesterConfiguration;$pesterConfig.run.Path = '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1';$pesterConfig.CodeCoverage.Enabled = $true;$pesterConfig.CodeCoverage.Path = '${workspaceFolder}/src/${workspaceFolderBasename}/*/${input:functionName}.ps1';Invoke-Pester -Configuration $pesterConfig", + "problemMatcher": "$pester", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "Pester-Single-Detailed", + "type": "shell", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1' -Output Detailed", + "problemMatcher": "$pester", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "DevCC-Single", + "type": "shell", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';$pesterConfig = New-PesterConfiguration;$pesterConfig.run.Path = '${workspaceFolder}/src/Tests/Unit/*/${input:functionName}.Tests.ps1';$pesterConfig.CodeCoverage.Enabled = $true;$pesterConfig.CodeCoverage.Path = '${workspaceFolder}/src/${workspaceFolderBasename}/*/${input:functionName}.ps1';$pesterConfig.CodeCoverage.OutputPath = '${workspaceFolder}/cov.xml';$pesterConfig.CodeCoverage.OutputFormat = 'CoverageGutters';Invoke-Pester -Configuration $pesterConfig", + "problemMatcher": "$pester", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + }, + { + "label": "Integration-Single-Detailed", + "type": "shell", + "command": "Import-Module -Name '${workspaceFolder}/src/${workspaceFolderBasename}/${workspaceFolderBasename}.psm1';Invoke-Pester '${workspaceFolder}/src/Tests/Integration/*/${input:functionName}.Tests.ps1' -Output Detailed", + "problemMatcher": "$pester", + "presentation": { + "echo": false, + "showReuseMessage": false + }, + "group": "test" + } + ], + "inputs": [ + { + "type": "promptString", + "id": "functionName", + "description": "Name of PowerShell function you want to test" + } + ] +} diff --git a/Build/Build-Module.ps1 b/Build/Build-Module.ps1 deleted file mode 100644 index 06c8dfc..0000000 --- a/Build/Build-Module.ps1 +++ /dev/null @@ -1,90 +0,0 @@ -Build-Module -ModuleName 'PSPreWorkout' { - # Usual defaults as per standard module - $Manifest = [ordered] @{ - ModuleVersion = '0.0.3' - CompatiblePSEditions = @('Desktop', 'Core') - GUID = '3ea876cf-733d-4ac4-bd85-25503534c966' - Author = 'Sam Erde' - CompanyName = 'Sam Erde' - Copyright = "(c) $((Get-Date).Year) Sam Erde. All rights reserved." - Description = 'A special mix of tools (and experiments) to help jump start your PowerShell work session!' - PowerShellVersion = '5.1' - Tags = @('Windows','MacOS','Linux','PowerShell','Utility') - } - New-ConfigurationManifest @Manifest - - # Add standard module dependencies (directly, but can be used with loop as well) - foreach ($Module in @('Microsoft.PowerShell.Utility', 'Microsoft.PowerShell.Management', 'Microsoft.PowerShell.Security')) { - New-ConfigurationModule -Type RequiredModule -Name $Module -Guid 'Auto' -Version 'Latest' - } - - # Add external module dependencies, using loop for simplicity - foreach ($Module in @('PowerShellGet')) { - New-ConfigurationModule -Type ExternalModule -Name $Module - } - - # Add approved modules, that can be used as a dependency, but only when specific function from those modules - # is used, and on that time only that function and dependant functions will be copied over. Keep in mind it - # has its limits when "copying" functions such as, it should not depend on DLLs or other external files. - New-ConfigurationModule -Type ApprovedModule -Name @('AppX','Dism','powershell-yaml') - - # ExchangeOnlineManagement: Get-PSImplicitRemotingClientSideParameters and Get-PSImplicitRemotingSession - New-ConfigurationModuleSkip -IgnoreFunctionName 'brew','scoop','softwareupdate','sudo','ConvertFrom-yaml' -IgnoreModuleName 'ExchangeOnlineManagement','powershell-yaml' - - $ConfigurationFormat = [ordered] @{ - RemoveComments = $false - - PlaceOpenBraceEnable = $true - PlaceOpenBraceOnSameLine = $true - PlaceOpenBraceNewLineAfter = $true - PlaceOpenBraceIgnoreOneLineBlock = $false - - PlaceCloseBraceEnable = $true - PlaceCloseBraceNewLineAfter = $true - PlaceCloseBraceIgnoreOneLineBlock = $false - PlaceCloseBraceNoEmptyLineBefore = $true - - UseConsistentIndentationEnable = $true - UseConsistentIndentationKind = 'space' - UseConsistentIndentationPipelineIndentation = 'IncreaseIndentationAfterEveryPipeline' - UseConsistentIndentationIndentationSize = 4 - - UseConsistentWhitespaceEnable = $true - UseConsistentWhitespaceCheckInnerBrace = $true - UseConsistentWhitespaceCheckOpenBrace = $true - UseConsistentWhitespaceCheckOpenParen = $true - UseConsistentWhitespaceCheckOperator = $true - UseConsistentWhitespaceCheckPipe = $true - UseConsistentWhitespaceCheckSeparator = $true - - AlignAssignmentStatementEnable = $true - AlignAssignmentStatementCheckHashtable = $true - - UseCorrectCasingEnable = $true - } - - # Format PSD1 and PSM1 files when merging into a single file. - # Enable formatting is not required as Configuration is provided - New-ConfigurationFormat -ApplyTo 'OnMergePSM1', 'OnMergePSD1' -Sort None @ConfigurationFormat - - # Format PSD1 and PSM1 files within the module. - # Enable formatting is required to make sure that formatting is applied (with default settings). - New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'DefaultPSM1' -EnableFormatting -Sort None - - # When creating PSD1, use special style without comments, and with only required parameters. - New-ConfigurationFormat -ApplyTo 'DefaultPSD1', 'OnMergePSD1' -PSD1Style 'Minimal' - - # Configuration for documentation. Also enables documentation processing. - New-ConfigurationDocumentation -Enable:$false -StartClean -UpdateWhenNew -PathReadme 'Docs\Readme.md' -Path 'Docs' - - New-ConfigurationImportModule -ImportSelf -ImportRequiredModules - - New-ConfigurationBuild -Enable:$true -SignModule:$false -DeleteTargetModuleBeforeBuild -MergeModuleOnBuild -MergeFunctionsFromApprovedModules -DoNotAttemptToFixRelativePaths - - New-ConfigurationArtefact -Type Unpacked -Enable -Path "$PSScriptRoot\..\Artefacts\Unpacked" #-RequiredModulesPath "$PSScriptRoot\..\Artefacts\Modules" - New-ConfigurationArtefact -Type Packed -Enable -Path "$PSScriptRoot\..\Artefacts\Packed" -IncludeTagName - - # Global options for publishing to GitHub / PSGallery: - # New-ConfigurationPublish -Type PowerShellGallery -FilePath 'C:\Support\Important\PowerShellGalleryAPI.txt' -Enabled:$false - # New-ConfigurationPublish -Type GitHub -FilePath 'C:\Support\Important\GitHubAPI.txt' -UserName 'CompanyName' -Enabled:$false -} diff --git a/LICENSE b/LICENSE index 0f270b4..3465f4b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2024 Sam Erde - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +MIT License + +Copyright (c) 2024 Sam Erde + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/PSPreWorkout.psd1 b/PSPreWorkout.psd1 deleted file mode 100644 index d2f9d62..0000000 --- a/PSPreWorkout.psd1 +++ /dev/null @@ -1,33 +0,0 @@ -@{ - AliasesToExport = @('gev', 'sev', 'UATT') - Author = 'Sam Erde' - CmdletsToExport = @() - CompanyName = 'Sam Erde' - CompatiblePSEditions = @('Desktop', 'Core') - Copyright = '(c) 2024 Sam Erde. All rights reserved.' - Description = 'A special mix of tools (and experiments) to help jump start your PowerShell work session!' - FunctionsToExport = @('Get-EnvironmentVariable', 'Install-OhMyPosh', 'Install-PowerShellISE', 'New-ProfileWorkspace', 'Set-EnvironmentVariable', 'Update-AllTheThings') - GUID = '3ea876cf-733d-4ac4-bd85-25503534c966' - ModuleVersion = '0.0.3' - PowerShellVersion = '5.1' - PrivateData = @{ - PSData = @{ - ExternalModuleDependencies = @('PowerShellGet') - Tags = @('Windows', 'MacOS', 'Linux', 'PowerShell', 'Utility') - } - } - RequiredModules = @(@{ - Guid = '1da87e53-152b-403e-98dc-74d7b4d63d59' - ModuleName = 'Microsoft.PowerShell.Utility' - ModuleVersion = '3.1.0.0' - }, @{ - Guid = 'eefcb906-b326-4e99-9f54-8b4bb6ef3c6d' - ModuleName = 'Microsoft.PowerShell.Management' - ModuleVersion = '3.1.0.0' - }, @{ - Guid = 'a94c8c7e-9810-47c0-b8af-65089c13a35a' - ModuleName = 'Microsoft.PowerShell.Security' - ModuleVersion = '3.0.0.0' - }, 'PowerShellGet') - RootModule = 'PSPreWorkout.psm1' -} \ No newline at end of file diff --git a/PSPreWorkout.psm1 b/PSPreWorkout.psm1 deleted file mode 100644 index 39afab9..0000000 --- a/PSPreWorkout.psm1 +++ /dev/null @@ -1,96 +0,0 @@ -# Get public and private function definition files. -$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue -Recurse ) -$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue -Recurse ) -$Classes = @( Get-ChildItem -Path $PSScriptRoot\Classes\*.ps1 -ErrorAction SilentlyContinue -Recurse ) -$Enums = @( Get-ChildItem -Path $PSScriptRoot\Enums\*.ps1 -ErrorAction SilentlyContinue -Recurse ) -# Get all assemblies -$AssemblyFolders = Get-ChildItem -Path $PSScriptRoot\Lib -Directory -ErrorAction SilentlyContinue - -# Lets find which libraries we need to load -$Default = $false -$Core = $false -$Standard = $false -foreach ($A in $AssemblyFolders.Name) { - if ($A -eq 'Default') { - $Default = $true - } elseif ($A -eq 'Core') { - $Core = $true - } elseif ($A -eq 'Standard') { - $Standard = $true - } -} -if ($Standard -and $Core -and $Default) { - $FrameworkNet = 'Default' - $Framework = 'Standard' -} elseif ($Standard -and $Core) { - $Framework = 'Standard' - $FrameworkNet = 'Standard' -} elseif ($Core -and $Default) { - $Framework = 'Core' - $FrameworkNet = 'Default' -} elseif ($Standard -and $Default) { - $Framework = 'Standard' - $FrameworkNet = 'Default' -} elseif ($Standard) { - $Framework = 'Standard' - $FrameworkNet = 'Standard' -} elseif ($Core) { - $Framework = 'Core' - $FrameworkNet = '' -} elseif ($Default) { - $Framework = '' - $FrameworkNet = 'Default' -} else { - #Write-Error -Message 'No assemblies found' -} - -$Assembly = @( - if ($Framework -and $PSEdition -eq 'Core') { - Get-ChildItem -Path $PSScriptRoot\Lib\$Framework\*.dll -ErrorAction SilentlyContinue -Recurse - } - if ($FrameworkNet -and $PSEdition -ne 'Core') { - Get-ChildItem -Path $PSScriptRoot\Lib\$FrameworkNet\*.dll -ErrorAction SilentlyContinue -Recurse - } -) -$FoundErrors = @( - Foreach ($Import in @($Assembly)) { - try { - Write-Verbose -Message $Import.FullName - Add-Type -Path $Import.Fullname -ErrorAction Stop - # } - } catch [System.Reflection.ReflectionTypeLoadException] { - Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)" - $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique - foreach ($E in $LoaderExceptions) { - Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)" - } - $true - #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)" - } catch { - Write-Warning "Processing $($Import.Name) Exception: $($_.Exception.Message)" - $LoaderExceptions = $($_.Exception.LoaderExceptions) | Sort-Object -Unique - foreach ($E in $LoaderExceptions) { - Write-Warning "Processing $($Import.Name) LoaderExceptions: $($E.Message)" - } - $true - #Write-Error -Message "StackTrace: $($_.Exception.StackTrace)" - } - } - #Dot source the files - Foreach ($Import in @($Classes + $Enums + $Private + $Public)) { - Try { - . $Import.Fullname - } Catch { - Write-Error -Message "Failed to import functions from $($import.Fullname): $_" - $true - } - } -) - -if ($FoundErrors.Count -gt 0) { - $ModuleName = (Get-ChildItem $PSScriptRoot\*.psd1).BaseName - Write-Warning "Importing module $ModuleName failed. Fix errors before continuing." - break -} - -Export-ModuleMember -Function '*' -Alias '*' -Cmdlet '*' \ No newline at end of file diff --git a/Public/ProfileWorkspace.code-workspace b/Public/ProfileWorkspace.code-workspace deleted file mode 100644 index 5460d38..0000000 --- a/Public/ProfileWorkspace.code-workspace +++ /dev/null @@ -1,7 +0,0 @@ -{ - "folders": [ - { - "path": ".\\" - } - ] -} diff --git a/README Catesta.md b/README Catesta.md new file mode 100644 index 0000000..8a8d5f2 --- /dev/null +++ b/README Catesta.md @@ -0,0 +1,40 @@ +# PSPreworkout + +## Synopsis + + + +## Description + + + +## Why + + + +## Getting Started + +### Prerequisites + + + +### Installation + +```powershell +# how to install PSPreworkout + +``` + +### Quick start + +#### Example1 + +```powershell +# command showing how to use your project + +``` + +## Author + +Sam Erde + diff --git a/README.md b/README.md index 501f693..5f9520b 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@
-# PowerShell Pre-Workout +# PowerShell Pre-Workout (PSPreworkout) A special mix of tools (and experiments) to help jump start your PowerShell session! -An image generated by Bing Image Creator. Prompt: hooded robot hacker wearing a PowerShell shirt, drinking a powerful energy drink with energy swirling around the cup, surrounded by swirling energy, floating in the air, cinematic, hacker professional photography, studio lighting, studio background, advertising photography, intricate details, hyper-detailed, ultra realistic, 8K UHD, PowerShell +An image generated by Bing Image Creator. Prompt: hooded robot hacker wearing a PowerShell shirt, drinking a powerful energy drink with energy swirling around the cup, surrounded by swirling energy, floating in the air, cinematic, hacker professional photography, studio lighting, studio background, advertising photography, intricate details, hyper-detailed, ultra realistic, 8K UHD, PowerShell ## Functions diff --git a/actions_bootstrap.ps1 b/actions_bootstrap.ps1 new file mode 100644 index 0000000..4ea663c --- /dev/null +++ b/actions_bootstrap.ps1 @@ -0,0 +1,63 @@ +# Bootstrap dependencies + +# https://docs.microsoft.com/powershell/module/packagemanagement/get-packageprovider +Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null + +# https://docs.microsoft.com/powershell/module/powershellget/set-psrepository +Set-PSRepository -Name PSGallery -InstallationPolicy Trusted + +# List of PowerShell Modules required for the build +$modulesToInstall = New-Object System.Collections.Generic.List[object] +# https://github.com/pester/Pester +[void]$modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'Pester' + ModuleVersion = '5.6.1' + })) +# https://github.com/nightroman/Invoke-Build +[void]$modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'InvokeBuild' + ModuleVersion = '5.11.3' + })) +# https://github.com/PowerShell/PSScriptAnalyzer +[void]$modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'PSScriptAnalyzer' + ModuleVersion = '1.22.0' + })) +# https://github.com/PowerShell/platyPS +# older version used due to: https://github.com/PowerShell/platyPS/issues/457 +[void]$modulesToInstall.Add(([PSCustomObject]@{ + ModuleName = 'platyPS' + ModuleVersion = '0.12.0' + })) + + + +'Installing PowerShell Modules' +foreach ($module in $modulesToInstall) { + $installSplat = @{ + Name = $module.ModuleName + RequiredVersion = $module.ModuleVersion + Repository = 'PSGallery' + SkipPublisherCheck = $true + Force = $true + ErrorAction = 'Stop' + } + try { + if ($module.ModuleName -eq 'Pester' -and $IsWindows) { + # special case for Pester certificate mismatch with older Pester versions - https://github.com/pester/Pester/issues/2389 + # this only affects windows builds + Install-Module @installSplat -SkipPublisherCheck + } + else { + Install-Module @installSplat + } + Import-Module -Name $module.ModuleName -ErrorAction Stop + ' - Successfully installed {0}' -f $module.ModuleName + } + catch { + $message = 'Failed to install {0}' -f $module.ModuleName + " - $message" + throw + } +} + diff --git a/code_of_conduct.md b/code_of_conduct.md deleted file mode 100644 index 0eca0fc..0000000 --- a/code_of_conduct.md +++ /dev/null @@ -1,133 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official email address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement via their -profile's social links. All complaints will be reviewed and investigated -promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at -[https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[Mozilla CoC]: https://github.com/mozilla/diversity -[FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations diff --git a/docs/Get-EnvironmentVariable.md b/docs/Get-EnvironmentVariable.md new file mode 100644 index 0000000..fbd0050 --- /dev/null +++ b/docs/Get-EnvironmentVariable.md @@ -0,0 +1,109 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables +schema: 2.0.0 +--- + +# Get-EnvironmentVariable + +## SYNOPSIS +Retrieves the value of an environment variable. + +## SYNTAX + +``` +Get-EnvironmentVariable [[-Variable] ] [[-Target] ] [-All] + [] +``` + +## DESCRIPTION +The Get-EnvironmentVariable function retrieves the value of the specified environment variable +or displays all environment variables. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-EnvironmentVariable -Name "PATH" +Retrieves the value of the "PATH" environment variable. +``` + +## PARAMETERS + +### -Variable +The name of the environment variable to retrieve. +If not specified, all environment variables are returned. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Target +The target of the environment variable to retrieve. +Defaults to Machine. +(Process, User, or Machine) + +```yaml +Type: EnvironmentVariableTarget +Parameter Sets: (All) +Aliases: +Accepted values: Process, User, Machine + +Required: False +Position: 2 +Default value: Machine +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -All +Switch to show environment variables in all target scopes. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.String +## NOTES +Variable names are case-sensitive on Linux and macOS, but not on Windows. + +Why is 'Target' used by .NET instead of the familiar 'Scope' parameter name? +@IISResetMe (Mathias R. +Jessen) explains: +"Scope" would imply some sort of integrated hierarchy of env variables - that's not really the case. +Target=Process translates to kernel32!GetEnvironmentVariable (which then in turn reads the PEB from +the calling process), whereas Target={User,Machine} causes a registry lookup against environment +data in either HKCU or HKLM. + +The relevant sources for the User and Machine targets are in the registry at: +- HKEY_CURRENT_USER\Environment +- HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment + +## RELATED LINKS + +[https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables) diff --git a/docs/Install-OhMyPosh.md b/docs/Install-OhMyPosh.md new file mode 100644 index 0000000..ccf87d9 --- /dev/null +++ b/docs/Install-OhMyPosh.md @@ -0,0 +1,113 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables +schema: 2.0.0 +--- + +# Install-OhMyPosh + +## SYNOPSIS +Install Oh My Posh and add it to your profile. + +## SYNTAX + +``` +Install-OhMyPosh [-WingetSource ] [-Method ] [-InstallNerdFont] [-Font ] + [] +``` + +## DESCRIPTION +An over-engineered script to install Oh My Posh. + +## EXAMPLES + +### EXAMPLE 1 +``` +Install-OhMyPosh +``` + +## PARAMETERS + +### -WingetSource +Specify which source to install from. + + winget - Install from winget (default). + msstore - Install from the Microsoft Store. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Winget +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Method +Specify which tool to install Oh My Posh with. + + chocolatey + direct (default) + scoop + winget + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Direct +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InstallNerdFont +Use this switch if you want to install a nerd font for full glyph capabilities in your prompt. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Font +Choose a nerd font to install. + + Default - Installs "Meslo" as the default nerd font. + Select - Lets you choose a nerd font from the list. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: Default +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/docs/Install-PowerShellISE.md b/docs/Install-PowerShellISE.md new file mode 100644 index 0000000..984e081 --- /dev/null +++ b/docs/Install-PowerShellISE.md @@ -0,0 +1,46 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables +schema: 2.0.0 +--- + +# Install-PowerShellISE + +## SYNOPSIS +Install the Windows PowerShell ISE if you removed it after installing VS Code. + +## SYNTAX + +``` +Install-PowerShellISE +``` + +## DESCRIPTION +This script installs the Windows PowerShell ISE if it is not already. +It includes a step that resets the Windows +Automatic Update server source in the registry temporary, which may resolve errors that some people experience +while trying to add Windows Capabilities. +This was created because Out-GridView in Windows PowerShell 5.1 does not +work without the ISE installed. +However, Out-GridView was rewritten and included in PowerShell 7 for Windows. + +## EXAMPLES + +### EXAMPLE 1 +``` +Install-PowerShellISE +``` + +## PARAMETERS + +## INPUTS + +## OUTPUTS + +## NOTES +To Do: + - Check for Windows client vs Windows Server OS + - Add parameter to make the Windows Update registry change optional + +## RELATED LINKS diff --git a/docs/New-ProfileWorkspace.md b/docs/New-ProfileWorkspace.md new file mode 100644 index 0000000..dc87413 --- /dev/null +++ b/docs/New-ProfileWorkspace.md @@ -0,0 +1,169 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles +schema: 2.0.0 +--- + +# New-ProfileWorkspace + +## SYNOPSIS +Setup a folder and VS Code Workspace for maintaining your PowerShell profiles, VS Code settings, and Windows Terminal settings. + +## SYNTAX + +``` +New-ProfileWorkspace [[-WorkspacePath] ] [[-PowerShellPath] ] + [[-WindowsPowerShellPath] ] [-Launch] [-WhatIf] [-Confirm] + [] +``` + +## DESCRIPTION +I wanted an easy way to maintain all of my CurrentUser PowerShell profiles and settings for Visual Studio Code +and Windows Terminal. + +## EXAMPLES + +### EXAMPLE 1 +``` +New-ProfileWorkspace +``` + +## PARAMETERS + +### -WorkspacePath +The location to create your profile workspace in. +The default value is a "Repositories/ProfileWorkspace" folder in +the current user's home folder. +Example: "C:/Users/sam.erde/Repositories/ProfileWorkspace" + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: ~/Repositories/ProfileWorkspace +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -PowerShellPath +The location of the current user's PowerShell folder that should contain their profile. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 2 +Default value: ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/PowerShell' ) +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WindowsPowerShellPath +The location of the current user's WindowsPowerShell folder that should contain their profile. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 3 +Default value: ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/WindowsPowerShell' ) +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Launch +A switch that, if used, will launch the VS Code workspace upon completion of this script. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +Author: Sam Erde, https://www.twitter.com/SamErde +Created: 2023/11/28 + +This script creates a folder that contains: + + - Junction points to the locations of your CurrentUser PowerShell and Windows PowerShell folders + - Junction points to the locations of your settings for VS Code and Windows Terminal + - A Visual Studio Code workspace file that opens this new folder + - EditorConfig and Visual Studio Code settings files for consistent editing + - A .gitignore file in case you want to use this as a git repository (test?) + +Profile Locations on Windows: + ~/Documents/PowerShell/profile.ps1 + ~/Documents/PowerShell/Microsoft.PowerShell_profile.ps1 + + ~/Documents/WindowsPowerShell/profile.ps1 + ~/Documents/WindowsPowerShell/Microsoft.VSCode_profile.ps1 + ~/Documents/WindowsPowerShell/Microsoft.PowerShell_profile.ps1 + +Settings Locations on Windows: + ~/AppData/Local/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState/settings.json + ~/AppData/Roaming/Code/User/settings.json + +To Do: + - \[ \] Check for existence of junction points and target locations + - \[ \] Wrap New-Item in try/catch blocks + - \[ \] Take initial creation location for this setup as a parameter with a clear default value + - \[ \] Create function for a dot-sourced base profile that is stored in a git repo or synced user profile location + - \[ \] Add support for Linux and macOS? + +## RELATED LINKS + +[https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles) diff --git a/docs/New-ScriptFromTemplate.md b/docs/New-ScriptFromTemplate.md new file mode 100644 index 0000000..1374d16 --- /dev/null +++ b/docs/New-ScriptFromTemplate.md @@ -0,0 +1,174 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles +schema: 2.0.0 +--- + +# New-ScriptFromTemplate + +## SYNOPSIS +Create a new advanced function from a template. + +## SYNTAX + +### Named +``` +New-ScriptFromTemplate -Name [-SkipValidation] [-Synopsis ] [-Description ] + [-Alias ] [-Path ] [] +``` + +### VerbNoun +``` +New-ScriptFromTemplate -Verb -Noun [-SkipValidation] [-Synopsis ] + [-Description ] [-Alias ] [-Path ] + [] +``` + +## DESCRIPTION +This function creates a new function from a template and saves it to a file with the name of the function. +It takes values for the function's synopsis, description, and alias as parameters and populates comment- +based help for the new function automatically. + +## EXAMPLES + +### EXAMPLE 1 +``` +New-Function -Name "Get-Demo" -Synopsis "Get a demo." -Description "This function gets a demo." -Alias "Get-Sample" +``` + +## PARAMETERS + +### -Name +The name of the new function to create. +It is recommended to use ApprovedVerb-Noun for names. + +```yaml +Type: String +Parameter Sets: Named +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Verb +The verb to use for the function name. + +```yaml +Type: String +Parameter Sets: VerbNoun +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Noun +The noun to use for the function name. + +```yaml +Type: String +Parameter Sets: VerbNoun +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -SkipValidation +Optionally skip validation of the script name. +This will not check for use of approved verbs or restricted characters. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Synopsis +A synopsis of the new function. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Description +A description of the new function. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Alias +Optionally define an alias for the new function. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path +The path of the directory to save the new script in. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/docs/PSPreworkout.md b/docs/PSPreworkout.md new file mode 100644 index 0000000..c0352fe --- /dev/null +++ b/docs/PSPreworkout.md @@ -0,0 +1,35 @@ +--- +Module Name: PSPreworkout +Module Guid: 378339de-a0df-4d44-873b-4fd32c388e06 +Download Help Link: NA +Help Version: 0.0.5 +Locale: en-US +--- + +# PSPreworkout Module +## Description +A special mix of tools (and experiments) to help jump start your PowerShell session! + +## PSPreworkout Cmdlets +### [Get-EnvironmentVariable](Get-EnvironmentVariable.md) +Retrieves the value of an environment variable. + +### [Install-OhMyPosh](Install-OhMyPosh.md) +Install Oh My Posh and add it to your profile. + +### [Install-PowerShellISE](Install-PowerShellISE.md) +Install the Windows PowerShell ISE if you removed it after installing VS Code. + +### [New-ProfileWorkspace](New-ProfileWorkspace.md) +Setup a folder and VS Code Workspace for maintaining your PowerShell profiles, VS Code settings, and Windows Terminal settings. + +### [New-ScriptFromTemplate](New-ScriptFromTemplate.md) +Create a new advanced function from a template. + +### [Set-EnvironmentVariable](Set-EnvironmentVariable.md) +Set environment variables. + +### [Update-AllTheThings](Update-AllTheThings.md) +Update-AllTheThings: Update all the things! + + diff --git a/docs/Set-EnvironmentVariable.md b/docs/Set-EnvironmentVariable.md new file mode 100644 index 0000000..7cafc00 --- /dev/null +++ b/docs/Set-EnvironmentVariable.md @@ -0,0 +1,89 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles +schema: 2.0.0 +--- + +# Set-EnvironmentVariable + +## SYNOPSIS +Set environment variables. + +## SYNTAX + +``` +Set-EnvironmentVariable [-Name] [-Value] [[-Target] ] + [] +``` + +## DESCRIPTION +Set environment variables in any OS using .NET types. + +## EXAMPLES + +### EXAMPLE 1 +``` +An example +``` + +## PARAMETERS + +### -Name +Parameter description + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Value +Parameter description + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: True +Position: 2 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Target +Parameter description + +```yaml +Type: EnvironmentVariableTarget +Parameter Sets: (All) +Aliases: +Accepted values: Process, User, Machine + +Required: False +Position: 3 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +General notes + +## RELATED LINKS diff --git a/docs/Update-AllTheThings.md b/docs/Update-AllTheThings.md new file mode 100644 index 0000000..63911c1 --- /dev/null +++ b/docs/Update-AllTheThings.md @@ -0,0 +1,75 @@ +--- +external help file: PSPreworkout-help.xml +Module Name: PSPreworkout +online version: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles +schema: 2.0.0 +--- + +# Update-AllTheThings + +## SYNOPSIS +Update-AllTheThings: Update all the things! + +## SYNTAX + +``` +Update-AllTheThings [-WhatIf] [-Confirm] [] +``` + +## DESCRIPTION +A script to automatically update all PowerShell modules, PowerShell Help, and packages (apt, brew, chocolately, winget). + +## EXAMPLES + +### EXAMPLE 1 +``` +Update-AllTheThings +``` + +Updates all of the things it can! + +## PARAMETERS + +### -WhatIf +Shows what would happen if the cmdlet runs. +The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutBuffer, -OutVariable, -PipelineVariable, -Verbose, -WarningAction, -WarningVariable, and -ProgressAction. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### None. You can't pipe objects to Update-Everything. +## OUTPUTS + +## NOTES + +## RELATED LINKS diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..8a8d5f2 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,40 @@ +# PSPreworkout + +## Synopsis + + + +## Description + + + +## Why + + + +## Getting Started + +### Prerequisites + + + +### Installation + +```powershell +# how to install PSPreworkout + +``` + +### Quick start + +#### Example1 + +```powershell +# command showing how to use your project + +``` + +## Author + +Sam Erde + diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000..f9fb869 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,4 @@ +# https://github.com/readthedocs-examples/example-mkdocs-basic/blob/main/docs/requirements.txt +# requirements.txt +jinja2==3.1.4 #https://pypi.org/project/Jinja2/ +mkdocs>=1.6.0 #https://github.com/mkdocs/mkdocs diff --git a/media/PSPreWorkout-Droid-1.jpg b/media/PSPreWorkout-Droid-1.jpg new file mode 100644 index 0000000..ced12d9 Binary files /dev/null and b/media/PSPreWorkout-Droid-1.jpg differ diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..bd79849 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,39 @@ +# https://www.mkdocs.org/user-guide/configuration/ +# https://www.mkdocs.org/user-guide/writing-your-docs/ +# https://www.mkdocs.org/user-guide/writing-your-docs/#writing-with-markdown +# https://mkdocs.readthedocs.io/en/0.15.2/user-guide/writing-your-docs/ +# https://mkdocs.readthedocs.io/en/0.15.2/user-guide/styling-your-docs/ +# https://example-mkdocs-basic.readthedocs.io/en/latest/ +# https://github.com/mkdocs/mkdocs/blob/master/mkdocs.yml +# mkdocs.yml + +site_name: PowerShell Pre-Workout +site_url: https://day3bits.com/PSPreworkout +repo_url: https://github.com/SamErde/PowerShell-Pre-Workout +repo_name: PowerShell-Pre-Workout +# edit_uri: edit/main/docs/ +# edit_uri_template: +site_description: A special mix of tools (and experiments) to help jump start your PowerShell session! # meta tag to the generated HTML header +site_author: Sam Erde # meta tag to the generated HTML header +copyright: (c) 2024 Sam Erde. +# remote_branch: +# remote_name: +# docs_dir: docs +# site_dir: +# extra_css: +# extra_javascript: +# extra_templates: +# extra: +theme: readthedocs +# theme: +# name: readthedocs +# locale: en +# custom_dir: my_theme_customizations/ +# static_templates: +# - sitemap.html +# include_sidebar: true +nav: + - Home: index.md + - Change Log: CHANGELOG.md + # - Functions: + # - Function1: functions/function1.md diff --git a/src/MarkdownRepair.ps1 b/src/MarkdownRepair.ps1 new file mode 100644 index 0000000..731dc1d --- /dev/null +++ b/src/MarkdownRepair.ps1 @@ -0,0 +1,133 @@ +<# +.SYNOPSIS + Repair PlatyPS generated markdown files. +.NOTES + This file is temporarily required to handle platyPS help generation. + https://github.com/PowerShell/platyPS/issues/595 + This is a result of a breaking change introduced in PowerShell 7.4.0: + https://learn.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-74?view=powershell-7.4 + Breaking Changes: Added the ProgressAction parameter to the Common Parameters + modified from source: https://github.com/PowerShell/platyPS/issues/595#issuecomment-1820971702 +#> + +function Remove-CommonParameterFromMarkdown { + <# + .SYNOPSIS + Remove a PlatyPS generated parameter block. + .DESCRIPTION + Removes parameter block for the provided parameter name from the markdown file provided. + #> + param( + [Parameter(Mandatory)] + [string[]] + $Path, + + [Parameter(Mandatory = $false)] + [string[]] + $ParameterName = @('ProgressAction') + ) + $ErrorActionPreference = 'Stop' + foreach ($p in $Path) { + $content = (Get-Content -Path $p -Raw).TrimEnd() + $updateFile = $false + foreach ($param in $ParameterName) { + if (-not ($Param.StartsWith('-'))) { + $param = "-$($param)" + } + # Remove the parameter block + $pattern = "(?m)^### $param\r?\n[\S\s]*?(?=#{2,3}?)" + $newContent = $content -replace $pattern, '' + # Remove the parameter from the syntax block + $pattern = " \[$param\s?.*?]" + $newContent = $newContent -replace $pattern, '' + if ($null -ne (Compare-Object -ReferenceObject $content -DifferenceObject $newContent)) { + Write-Verbose "Added $param to $p" + # Update file content + $content = $newContent + $updateFile = $true + } + } + # Save file if content has changed + if ($updateFile) { + $newContent | Out-File -Encoding utf8 -FilePath $p + Write-Verbose "Updated file: $p" + } + } + return +} + +function Add-MissingCommonParameterToMarkdown { + param( + [Parameter(Mandatory)] + [string[]] + $Path, + + [Parameter(Mandatory = $false)] + [string[]] + $ParameterName = @('ProgressAction') + ) + $ErrorActionPreference = 'Stop' + foreach ($p in $Path) { + $content = (Get-Content -Path $p -Raw).TrimEnd() + $updateFile = $false + foreach ($NewParameter in $ParameterName) { + if (-not ($NewParameter.StartsWith('-'))) { + $NewParameter = "-$($NewParameter)" + } + $pattern = '(?m)^This cmdlet supports the common parameters:(.+?)\.' + $replacement = { + $Params = $_.Groups[1].Captures[0].ToString() -split ' ' + $CommonParameters = @() + foreach ($CommonParameter in $Params) { + if ($CommonParameter.StartsWith('-')) { + if ($CommonParameter.EndsWith(',')) { + $CleanParam = $CommonParameter.Substring(0, $CommonParameter.Length - 1) + } elseif ($p.EndsWith('.')) { + $CleanParam = $CommonParameter.Substring(0, $CommonParameter.Length - 1) + } else { + $CleanParam = $CommonParameter + } + $CommonParameters += $CleanParam + } + } + if ($NewParameter -notin $CommonParameters) { + $CommonParameters += $NewParameter + } + $CommonParameters[-1] = "and $($CommonParameters[-1]). " + return 'This cmdlet supports the common parameters: ' + (($CommonParameters | Sort-Object) -join ', ') + } + $newContent = $content -replace $pattern, $replacement + if ($null -ne (Compare-Object -ReferenceObject $content -DifferenceObject $newContent)) { + Write-Verbose "Added $NewParameter to $p" + $updateFile = $true + $content = $newContent + } + } + # Save file if content has changed + if ($updateFile) { + $newContent | Out-File -Encoding utf8 -FilePath $p + Write-Verbose "Updated file: $p" + } + } + return +} + +function Repair-PlatyPSMarkdown { + param( + [Parameter(Mandatory)] + [string[]] + $Path, + + [Parameter()] + [string[]] + $ParameterName = @('ProgressAction') + ) + $ErrorActionPreference = 'Stop' + $Parameters = @{ + Path = $Path + ParameterName = $ParameterName + } + $null = Remove-CommonParameterFromMarkdown @Parameters + $null = Add-MissingCommonParameterToMarkdown @Parameters + return +} diff --git a/src/PSPreworkout.Settings.ps1 b/src/PSPreworkout.Settings.ps1 new file mode 100644 index 0000000..a0e647a --- /dev/null +++ b/src/PSPreworkout.Settings.ps1 @@ -0,0 +1,2 @@ +# specify the minimum required major PowerShell version that the build script should validate +[version]$script:requiredPSVersion = '5.1.0' diff --git a/src/PSPreworkout.build.ps1 b/src/PSPreworkout.build.ps1 new file mode 100644 index 0000000..2ccf7e0 --- /dev/null +++ b/src/PSPreworkout.build.ps1 @@ -0,0 +1,553 @@ +<# +.SYNOPSIS + An Invoke-Build Build file. +.DESCRIPTION + Build steps can include: + - ValidateRequirements + - ImportModuleManifest + - Clean + - Analyze + - FormattingCheck + - Test + - DevCC + - CreateHelpStart + - Build + - IntegrationTest + - Archive +.EXAMPLE + Invoke-Build + + This will perform the default build Add-BuildTasks: see below for the default Add-BuildTask execution +.EXAMPLE + Invoke-Build -Add-BuildTask Analyze,Test + + This will perform only the Analyze and Test Add-BuildTasks. +.NOTES + This build file by Catesta will pull in configurations from the ".Settings.ps1" file as well, where users can more easily customize the build process if required. + https://github.com/nightroman/Invoke-Build + https://github.com/nightroman/Invoke-Build/wiki/Build-Scripts-Guidelines + If using VSCode you can use the generated tasks.json to execute the various tasks in this build file. + Ctrl + P | then type task (add space) - you will then be presented with a list of available tasks to run + The 'InstallDependencies' Add-BuildTask isn't present here. + Module dependencies are installed at a previous step in the pipeline. + If your manifest has module dependencies include all required modules in your CI/CD bootstrap file: + AWS - install_modules.ps1 + Azure - actions_bootstrap.ps1 + GitHub Actions - actions_bootstrap.ps1 + AppVeyor - actions_bootstrap.ps1 +#> + +#Include: Settings +$ModuleName = [regex]::Match((Get-Item $BuildFile).Name, '^(.*)\.build\.ps1$').Groups[1].Value +. "./$ModuleName.Settings.ps1" + +function Test-ManifestBool ($Path) { + Get-ChildItem $Path | Test-ModuleManifest -ErrorAction SilentlyContinue | Out-Null; $? +} + +#Default Build +$str = @() +$str = 'Clean', 'ValidateRequirements', 'ImportModuleManifest' +$str += 'FormattingCheck' +$str += 'Analyze', 'Test' +$str += 'CreateHelpStart' +$str2 = $str +$str2 += 'Build', 'Archive' +$str += 'Build', 'IntegrationTest', 'Archive' +Add-BuildTask -Name . -Jobs $str + +#Local testing build process +Add-BuildTask TestLocal Clean, ImportModuleManifest, Analyze, Test + +#Local help file creation process +Add-BuildTask HelpLocal Clean, ImportModuleManifest, CreateHelpStart + +#Full build sans integration tests +Add-BuildTask BuildNoIntegration -Jobs $str2 + +# Pre-build variables to be used by other portions of the script +Enter-Build { + $script:ModuleName = [regex]::Match((Get-Item $BuildFile).Name, '^(.*)\.build\.ps1$').Groups[1].Value + + # Identify other required paths + $script:ModuleSourcePath = Join-Path -Path $BuildRoot -ChildPath $script:ModuleName + $script:ModuleFiles = Join-Path -Path $script:ModuleSourcePath -ChildPath '*' + + $script:ModuleManifestFile = Join-Path -Path $script:ModuleSourcePath -ChildPath "$($script:ModuleName).psd1" + + $manifestInfo = Import-PowerShellDataFile -Path $script:ModuleManifestFile + $script:ModuleVersion = $manifestInfo.ModuleVersion + $script:ModuleDescription = $manifestInfo.Description + $script:FunctionsToExport = $manifestInfo.FunctionsToExport + + $script:TestsPath = Join-Path -Path $BuildRoot -ChildPath 'Tests' + $script:UnitTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Unit' + $script:IntegrationTestsPath = Join-Path -Path $script:TestsPath -ChildPath 'Integration' + + $script:ArtifactsPath = Join-Path -Path $BuildRoot -ChildPath 'Artifacts' + $script:ArchivePath = Join-Path -Path $BuildRoot -ChildPath 'Archive' + + $script:BuildModuleRootFile = Join-Path -Path $script:ArtifactsPath -ChildPath "$($script:ModuleName).psm1" + + # Ensure our builds fail until if below a minimum defined code test coverage threshold + $script:coverageThreshold = 2 # Default 30 + + [version]$script:MinPesterVersion = '5.2.2' + [version]$script:MaxPesterVersion = '5.99.99' + $script:testOutputFormat = 'NUnitXML' +} #Enter-Build + +# Define headers as separator, task path, synopsis, and location, e.g. for Ctrl+Click in VSCode. +# Also change the default color to Green. If you need task start times, use `$Task.Started`. +Set-BuildHeader { + param($Path) + # separator line + Write-Build DarkMagenta ('=' * 79) + # default header + synopsis + Write-Build DarkGray "Task $Path : $(Get-BuildSynopsis $Task)" + # task location in a script + Write-Build DarkGray "At $($Task.InvocationInfo.ScriptName):$($Task.InvocationInfo.ScriptLineNumber)" + Write-Build Yellow "Manifest File: $script:ModuleManifestFile" + Write-Build Yellow "Manifest Version: $($manifestInfo.ModuleVersion)" +} #Set-BuildHeader + +# Define footers similar to default but change the color to DarkGray. +Set-BuildFooter { + param($Path) + Write-Build DarkGray "Done $Path, $($Task.Elapsed)" + # # separator line + # Write-Build Gray ('=' * 79) +} #Set-BuildFooter + +#Synopsis: Validate system requirements are met +Add-BuildTask ValidateRequirements { + # this setting comes from the *.Settings.ps1 + Write-Build White " Verifying at least PowerShell $script:requiredPSVersion..." + Assert-Build ($PSVersionTable.PSVersion -ge $script:requiredPSVersion) "At least Powershell $script:requiredPSVersion is required for this build to function properly" + Write-Build Green ' ...Verification Complete!' +} #ValidateRequirements + +# Synopsis: Import the current module manifest file for processing +Add-BuildTask TestModuleManifest -Before ImportModuleManifest { + Write-Build White ' Running module manifest tests...' + Assert-Build (Test-Path $script:ModuleManifestFile) 'Unable to locate the module manifest file.' + Assert-Build (Test-ManifestBool -Path $script:ModuleManifestFile) 'Module Manifest test did not pass verification.' + Write-Build Green ' ...Module Manifest Verification Complete!' +} #f5b33218-bde4-4028-b2a1-9c206f089503 + +# Synopsis: Load the module project +Add-BuildTask ImportModuleManifest { + Write-Build White ' Attempting to load the project module.' + try { + Import-Module $script:ModuleManifestFile -Force -PassThru -ErrorAction Stop + } catch { + throw 'Unable to load the project module' + } + Write-Build Green " ...$script:ModuleName imported successfully" +} + +#Synopsis: Clean and reset Artifacts/Archive Directory +Add-BuildTask Clean { + Write-Build White ' Clean up our Artifacts/Archive directory...' + + $null = Remove-Item $script:ArtifactsPath -Force -Recurse -ErrorAction 0 + $null = New-Item $script:ArtifactsPath -ItemType:Directory + $null = Remove-Item $script:ArchivePath -Force -Recurse -ErrorAction 0 + $null = New-Item $script:ArchivePath -ItemType:Directory + + Write-Build Green ' ...Clean Complete!' +} #Clean + +#Synopsis: Invokes PSScriptAnalyzer against the Module source path +Add-BuildTask Analyze { + + $scriptAnalyzerParams = @{ + Path = $script:ModuleSourcePath + Setting = 'PSScriptAnalyzerSettings.psd1' + Recurse = $true + Verbose = $false + } + + Write-Build White ' Performing Module ScriptAnalyzer checks...' + $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' One or more PSScriptAnalyzer errors/warnings where found.' + } else { + Write-Build Green ' ...Module Analyze Complete!' + } +} #Analyze + +#Synopsis: Invokes Script Analyzer against the Tests path if it exists +Add-BuildTask AnalyzeTests -After Analyze { + if (Test-Path -Path $script:TestsPath) { + + $scriptAnalyzerParams = @{ + Path = $script:TestsPath + Setting = 'PSScriptAnalyzerSettings.psd1' + ExcludeRule = 'PSUseDeclaredVarsMoreThanAssignments' + Recurse = $true + Verbose = $false + } + + Write-Build White ' Performing Test ScriptAnalyzer checks...' + $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' One or more PSScriptAnalyzer errors/warnings where found.' + } else { + Write-Build Green ' ...Test Analyze Complete!' + } + } +} #AnalyzeTests + +#Synopsis: Analyze scripts to verify if they adhere to desired coding format (Stroustrup / OTBS / Allman) +Add-BuildTask FormattingCheck { + + + $scriptAnalyzerParams = @{ + Setting = 'CodeFormattingOTBS' + ExcludeRule = 'PSUseConsistentWhitespace' + Recurse = $true + Verbose = $false + } + + + Write-Build White ' Performing script formatting checks...' + $scriptAnalyzerResults = Get-ChildItem -Path $script:ModuleSourcePath -Exclude '*.psd1' | Invoke-ScriptAnalyzer @scriptAnalyzerParams + + if ($scriptAnalyzerResults) { + $scriptAnalyzerResults | Format-Table + throw ' PSScriptAnalyzer code formatting check did not adhere to {0} standards' -f $scriptAnalyzerParams.Setting + } else { + Write-Build Green ' ...Formatting Analyze Complete!' + } +} #FormattingCheck + +#Synopsis: Invokes all Pester Unit Tests in the Tests\Unit folder (if it exists) +Add-BuildTask Test { + + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + + $codeCovPath = "$script:ArtifactsPath\ccReport\" + $testOutPutPath = "$script:ArtifactsPath\testOutput\" + if (-not(Test-Path $codeCovPath)) { + New-Item -Path $codeCovPath -ItemType Directory | Out-Null + } + if (-not(Test-Path $testOutPutPath)) { + New-Item -Path $testOutPutPath -ItemType Directory | Out-Null + } + if (Test-Path -Path $script:UnitTestsPath) { + $pesterConfiguration = New-PesterConfiguration + $pesterConfiguration.run.Path = $script:UnitTestsPath + $pesterConfiguration.Run.PassThru = $true + $pesterConfiguration.Run.Exit = $false + $pesterConfiguration.CodeCoverage.Enabled = $true + $pesterConfiguration.CodeCoverage.Path = "..\..\..\$ModuleName\*\*.ps1" + $pesterConfiguration.CodeCoverage.CoveragePercentTarget = $script:coverageThreshold + $pesterConfiguration.CodeCoverage.OutputPath = "$codeCovPath\CodeCoverage.xml" + $pesterConfiguration.CodeCoverage.OutputFormat = 'JaCoCo' + $pesterConfiguration.TestResult.Enabled = $true + $pesterConfiguration.TestResult.OutputPath = "$testOutPutPath\PesterTests.xml" + $pesterConfiguration.TestResult.OutputFormat = $script:testOutputFormat + $pesterConfiguration.Output.Verbosity = 'Detailed' + + Write-Build White ' Performing Pester Unit Tests...' + # Publish Test Results + $testResults = Invoke-Pester -Configuration $pesterConfiguration + + # This will output a nice json for each failed test (if running in CodeBuild) + if ($env:CODEBUILD_BUILD_ARN) { + $testResults.TestResult | ForEach-Object { + if ($_.Result -ne 'Passed') { + ConvertTo-Json -InputObject $_ -Compress + } + } + } + + $numberFails = $testResults.FailedCount + Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) + + Write-Build Gray (' ...CODE COVERAGE - CommandsExecutedCount: {0}' -f $testResults.CodeCoverage.CommandsExecutedCount) + Write-Build Gray (' ...CODE COVERAGE - CommandsAnalyzedCount: {0}' -f $testResults.CodeCoverage.CommandsAnalyzedCount) + + if ($testResults.CodeCoverage.NumberOfCommandsExecuted -ne 0) { + $coveragePercent = '{0:N2}' -f ($testResults.CodeCoverage.CommandsExecutedCount / $testResults.CodeCoverage.CommandsAnalyzedCount * 100) + + <# + if ($testResults.CodeCoverage.NumberOfCommandsMissed -gt 0) { + 'Failed to analyze "{0}" commands' -f $testResults.CodeCoverage.NumberOfCommandsMissed + } + Write-Host "PowerShell Commands not tested:`n$(ConvertTo-Json -InputObject $testResults.CodeCoverage.MissedCommands)" + #> + if ([Int]$coveragePercent -lt $coverageThreshold) { + throw ('Failed to meet code coverage threshold of {0}% with only {1}% coverage' -f $coverageThreshold, $coveragePercent) + } else { + Write-Build Cyan " $('Covered {0}% of {1} analyzed commands in {2} files.' -f $coveragePercent,$testResults.CodeCoverage.CommandsAnalyzedCount,$testResults.CodeCoverage.FilesAnalyzedCount)" + Write-Build Green ' ...Pester Unit Tests Complete!' + } + } else { + # account for new module build condition + Write-Build Yellow ' Code coverage check skipped. No commands to execute...' + } + + } +} #Test + +#Synopsis: Used primarily during active development to generate xml file to graphically display code coverage in VSCode using Coverage Gutters +Add-BuildTask DevCC { + Write-Build White ' Generating code coverage report at root...' + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + $pesterConfiguration = New-PesterConfiguration + $pesterConfiguration.run.Path = $script:UnitTestsPath + $pesterConfiguration.CodeCoverage.Enabled = $true + $pesterConfiguration.CodeCoverage.Path = "$PSScriptRoot\$ModuleName\*\*.ps1" + $pesterConfiguration.CodeCoverage.CoveragePercentTarget = $script:coverageThreshold + $pesterConfiguration.CodeCoverage.OutputPath = '..\..\..\cov.xml' + $pesterConfiguration.CodeCoverage.OutputFormat = 'CoverageGutters' + + Invoke-Pester -Configuration $pesterConfiguration + Write-Build Green ' ...Code Coverage report generated!' +} #DevCC + +# Synopsis: Build help for module +Add-BuildTask CreateHelpStart { + Write-Build White ' Performing all help related actions.' + + Write-Build Gray ' Importing platyPS v0.12.0 ...' + Import-Module platyPS -RequiredVersion 0.12.0 -ErrorAction Stop + Write-Build Gray ' ...platyPS imported successfully.' +} #CreateHelpStart + +# Synopsis: Build markdown help files for module and fail if help information is missing +Add-BuildTask CreateMarkdownHelp -After CreateHelpStart { + $ModulePage = "$script:ArtifactsPath\docs\$($ModuleName).md" + + $markdownParams = @{ + Module = $ModuleName + OutputFolder = "$script:ArtifactsPath\docs\" + Force = $true + WithModulePage = $true + Locale = 'en-US' + FwLink = 'NA' + HelpVersion = $script:ModuleVersion + } + + Write-Build Gray ' Generating markdown files...' + $null = New-MarkdownHelp @markdownParams + Write-Build Gray ' ...Markdown generation completed.' + + Write-Build Gray ' Replacing markdown elements...' + # Replace multi-line EXAMPLES + $OutputDir = "$script:ArtifactsPath\docs\" + $OutputDir | Get-ChildItem -File | ForEach-Object { + # fix formatting in multiline examples + $content = Get-Content $_.FullName -Raw + $newContent = $content -replace '(## EXAMPLE [^`]+?```\r\n[^`\r\n]+?\r\n)(```\r\n\r\n)([^#]+?\r\n)(\r\n)([^#]+)(#)', '$1$3$2$4$5$6' + if ($newContent -ne $content) { + Set-Content -Path $_.FullName -Value $newContent -Force + } + } + # Replace each missing element we need for a proper generic module page .md file + $ModulePageFileContent = Get-Content -Raw $ModulePage + $ModulePageFileContent = $ModulePageFileContent -replace '{{Manually Enter Description Here}}', $script:ModuleDescription + $script:FunctionsToExport | ForEach-Object { + Write-Build DarkGray " Updating definition for the following function: $($_)" + $TextToReplace = "{{Manually Enter $($_) Description Here}}" + $ReplacementText = (Get-Help -Detailed $_).Synopsis + $ModulePageFileContent = $ModulePageFileContent -replace $TextToReplace, $ReplacementText + } + + $ModulePageFileContent | Out-File $ModulePage -Force -Encoding:utf8 + Write-Build Gray ' ...Markdown replacements complete.' + + Write-Build Gray ' Verifying GUID...' + $MissingGUID = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern '(00000000-0000-0000-0000-000000000000)' + if ($MissingGUID.Count -gt 0) { + Write-Build Yellow ' The documentation that got generated resulted in a generic GUID. Check the GUID entry of your module manifest.' + throw 'Missing GUID. Please review and rebuild.' + } + + Write-Build Gray ' Evaluating if running 7.4.0 or higher...' + # https://github.com/PowerShell/platyPS/issues/595 + if ($PSVersionTable.PSVersion -ge [version]'7.4.0') { + Write-Build Gray ' Performing Markdown repair' + # dot source markdown repair + . $BuildRoot\MarkdownRepair.ps1 + $OutputDir | Get-ChildItem -File | ForEach-Object { + Repair-PlatyPSMarkdown -Path $_.FullName + } + } + + Write-Build Gray ' Checking for missing documentation in md files...' + $MissingDocumentation = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern '({{.*}})' + if ($MissingDocumentation.Count -gt 0) { + Write-Build Yellow ' The documentation that got generated resulted in missing sections which should be filled out.' + Write-Build Yellow ' Please review the following sections in your comment based help, fill out missing information and rerun this build:' + Write-Build Yellow ' (Note: This can happen if the .EXTERNALHELP CBH is defined for a function before running this build.)' + Write-Build Yellow " Path of files with issues: $script:ArtifactsPath\docs\" + $MissingDocumentation | Select-Object FileName, LineNumber, Line | Format-Table -AutoSize + throw 'Missing documentation. Please review and rebuild.' + } + + Write-Build Gray ' Checking for missing SYNOPSIS in md files...' + $fSynopsisOutput = @() + $synopsisEval = Select-String -Path "$script:ArtifactsPath\docs\*.md" -Pattern '^## SYNOPSIS$' -Context 0, 1 + $synopsisEval | ForEach-Object { + $chAC = $_.Context.DisplayPostContext.ToCharArray() + if ($null -eq $chAC) { + $fSynopsisOutput += $_.FileName + } + } + if ($fSynopsisOutput) { + Write-Build Yellow ' The following files are missing SYNOPSIS:' + $fSynopsisOutput + throw 'SYNOPSIS information missing. Please review.' + } + + Write-Build Gray ' ...Markdown generation complete.' +} #CreateMarkdownHelp + +# Synopsis: Build the external xml help file from markdown help files with PlatyPS +Add-BuildTask CreateExternalHelp -After CreateMarkdownHelp { + Write-Build Gray ' Creating external xml help file...' + $null = New-ExternalHelp "$script:ArtifactsPath\docs" -OutputPath "$script:ArtifactsPath\en-US\" -Force + Write-Build Gray ' ...External xml help file created!' +} #CreateExternalHelp + +Add-BuildTask CreateHelpComplete -After CreateExternalHelp { + Write-Build Green ' ...CreateHelp Complete!' +} #CreateHelpStart + +# Synopsis: Replace comment based help (CBH) with external help in all public functions for this project +Add-BuildTask UpdateCBH -After AssetCopy { + $ExternalHelp = @" +<# +.EXTERNALHELP $($ModuleName)-help.xml +#> +"@ + + $CBHPattern = '(?ms)(\<#.*\.SYNOPSIS.*?#>)' + Get-ChildItem -Path "$script:ArtifactsPath\Public\*.ps1" -File | ForEach-Object { + $FormattedOutFile = $_.FullName + Write-Output " Replacing CBH in file: $($FormattedOutFile)" + $UpdatedFile = (Get-Content $FormattedOutFile -Raw) -replace $CBHPattern, $ExternalHelp + $UpdatedFile | Out-File -FilePath $FormattedOutFile -Force -Encoding:utf8 + } +} #UpdateCBH + +# Synopsis: Copies module assets to Artifacts folder +Add-BuildTask AssetCopy -Before Build { + Write-Build Gray ' Copying assets to Artifacts...' + Copy-Item -Path "$script:ModuleSourcePath\*" -Destination $script:ArtifactsPath -Exclude *.psd1, *.psm1 -Recurse -ErrorAction Stop + Write-Build Gray ' ...Assets copy complete.' +} #AssetCopy + +# Synopsis: Builds the Module to the Artifacts folder +Add-BuildTask Build { + Write-Build White ' Performing Module Build' + + Write-Build Gray ' Copying manifest file to Artifacts...' + Copy-Item -Path $script:ModuleManifestFile -Destination $script:ArtifactsPath -Recurse -ErrorAction Stop + #Copy-Item -Path $script:ModuleSourcePath\bin -Destination $script:ArtifactsPath -Recurse -ErrorAction Stop + Write-Build Gray ' ...manifest copy complete.' + + Write-Build Gray ' Merging Public and Private functions to one module file...' + #$private = "$script:ModuleSourcePath\Private" + $scriptContent = [System.Text.StringBuilder]::new() + #$powerShellScripts = Get-ChildItem -Path $script:ModuleSourcePath -Filter '*.ps1' -Recurse + $powerShellScripts = Get-ChildItem -Path $script:ArtifactsPath -Recurse | Where-Object { $_.Name -match '^*.ps1$' } + foreach ($script in $powerShellScripts) { + $null = $scriptContent.Append((Get-Content -Path $script.FullName -Raw)) + $null = $scriptContent.AppendLine('') + $null = $scriptContent.AppendLine('') + } + $scriptContent.ToString() | Out-File -FilePath $script:BuildModuleRootFile -Encoding utf8 -Force + Write-Build Gray ' ...Module creation complete.' + + Write-Build Gray ' Cleaning up leftover artifacts...' + #cleanup artifacts that are no longer required + if (Test-Path "$script:ArtifactsPath\Public") { + Remove-Item "$script:ArtifactsPath\Public" -Recurse -Force -ErrorAction Stop + } + if (Test-Path "$script:ArtifactsPath\Private") { + Remove-Item "$script:ArtifactsPath\Private" -Recurse -Force -ErrorAction Stop + } + if (Test-Path "$script:ArtifactsPath\Imports.ps1") { + Remove-Item "$script:ArtifactsPath\Imports.ps1" -Force -ErrorAction SilentlyContinue + } + + if (Test-Path "$script:ArtifactsPath\docs") { + #here we update the parent level docs. If you would prefer not to update them, comment out this section. + Write-Build Gray ' Overwriting docs output...' + if (-not (Test-Path '..\docs\')) { + New-Item -Path '..\docs\' -ItemType Directory -Force | Out-Null + } + Move-Item "$script:ArtifactsPath\docs\*.md" -Destination '..\docs\' -Force + Remove-Item "$script:ArtifactsPath\docs" -Recurse -Force -ErrorAction Stop + Write-Build Gray ' ...Docs output completed.' + } + + Write-Build Green ' ...Build Complete!' +} #Build + +#Synopsis: Invokes all Pester Integration Tests in the Tests\Integration folder (if it exists) +Add-BuildTask IntegrationTest { + if (Test-Path -Path $script:IntegrationTestsPath) { + Write-Build White " Importing desired Pester version. Min: $script:MinPesterVersion Max: $script:MaxPesterVersion" + Remove-Module -Name Pester -Force -ErrorAction SilentlyContinue # there are instances where some containers have Pester already in the session + Import-Module -Name Pester -MinimumVersion $script:MinPesterVersion -MaximumVersion $script:MaxPesterVersion -ErrorAction 'Stop' + + Write-Build White " Performing Pester Integration Tests in $($invokePesterParams.path)" + + $pesterConfiguration = New-PesterConfiguration + $pesterConfiguration.run.Path = $script:IntegrationTestsPath + $pesterConfiguration.Run.PassThru = $true + $pesterConfiguration.Run.Exit = $false + $pesterConfiguration.CodeCoverage.Enabled = $false + $pesterConfiguration.TestResult.Enabled = $false + $pesterConfiguration.Output.Verbosity = 'Detailed' + + $testResults = Invoke-Pester -Configuration $pesterConfiguration + # This will output a nice json for each failed test (if running in CodeBuild) + if ($env:CODEBUILD_BUILD_ARN) { + $testResults.TestResult | ForEach-Object { + if ($_.Result -ne 'Passed') { + ConvertTo-Json -InputObject $_ -Compress + } + } + } + + $numberFails = $testResults.FailedCount + Assert-Build($numberFails -eq 0) ('Failed "{0}" unit tests.' -f $numberFails) + Write-Build Green ' ...Pester Integration Tests Complete!' + } +} #IntegrationTest + +#Synopsis: Creates an archive of the built Module +Add-BuildTask Archive { + Write-Build White ' Performing Archive...' + + $archivePath = Join-Path -Path $BuildRoot -ChildPath 'Archive' + if (Test-Path -Path $archivePath) { + $null = Remove-Item -Path $archivePath -Recurse -Force + } + + $null = New-Item -Path $archivePath -ItemType Directory -Force + + $zipFileName = '{0}_{1}_{2}.{3}.zip' -f $script:ModuleName, $script:ModuleVersion, ([DateTime]::UtcNow.ToString('yyyyMMdd')), ([DateTime]::UtcNow.ToString('hhmmss')) + $zipFile = Join-Path -Path $archivePath -ChildPath $zipFileName + + if ($PSEdition -eq 'Desktop') { + Add-Type -AssemblyName 'System.IO.Compression.FileSystem' + } + [System.IO.Compression.ZipFile]::CreateFromDirectory($script:ArtifactsPath, $zipFile) + + Write-Build Green ' ...Archive Complete!' +} #Archive diff --git a/src/PSPreworkout/Imports.ps1 b/src/PSPreworkout/Imports.ps1 new file mode 100644 index 0000000..45056b1 --- /dev/null +++ b/src/PSPreworkout/Imports.ps1 @@ -0,0 +1,6 @@ +# This is a locally sourced Imports file for local development. +# It can be imported by the psm1 in local development to add script level variables. +# It will merged in the build process. This is for local development only. + +# region script variables +# $script:resourcePath = "$PSScriptRoot\Resources" diff --git a/src/PSPreworkout/PSPreworkout.psd1 b/src/PSPreworkout/PSPreworkout.psd1 new file mode 100644 index 0000000..9ab9e17 --- /dev/null +++ b/src/PSPreworkout/PSPreworkout.psd1 @@ -0,0 +1,138 @@ +# Module manifest for module 'PSPreworkout' +# Generated by: Sam Erde +# Generated on: 8/24/2024 + +@{ + # Script module or binary module file associated with this manifest. + RootModule = 'PSPreworkout.psm1' + + # Version number of this module. + ModuleVersion = '0.0.5' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = '378339de-a0df-4d44-873b-4fd32c388e06' + + # Author of this module + Author = 'Sam Erde' + + # Company or vendor of this module + CompanyName = 'Sam Erde' + + # Copyright statement for this module + Copyright = '(c) Sam Erde. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'A special mix of tools (and experiments) to help jump start your PowerShell session!' + + # Minimum version of the PowerShell engine required by this module + PowerShellVersion = '5.1' + + # Name of the PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # ClrVersion = '' + + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' + + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() + + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() + + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = @( + 'Get-EnvironmentVariable', + 'Install-OhMyPosh', + 'Install-PowerShellISE', + 'New-ScriptFromTemplate', + 'New-ProfileWorkspace', + 'Update-AllTheThings', + 'Set-EnvironmentVariable' + ) + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = '' + + # Variables to export from this module + VariablesToExport = '' + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = @( + 'UATT', + 'genv', + 'senv' + ) + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # List of all files packaged with this module + # FileList = @() + + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + +} diff --git a/src/PSPreworkout/PSPreworkout.psm1 b/src/PSPreworkout/PSPreworkout.psm1 new file mode 100644 index 0000000..d9013f8 --- /dev/null +++ b/src/PSPreworkout/PSPreworkout.psm1 @@ -0,0 +1,31 @@ +# this psm1 is for local testing and development use only + +# dot source the parent import for local development variables +. $PSScriptRoot\Imports.ps1 + +# discover all ps1 file(s) in Public and Private paths + +$itemSplat = @{ + Filter = '*.ps1' + Recurse = $true + ErrorAction = 'Stop' +} +try { + $public = @(Get-ChildItem -Path "$PSScriptRoot\Public" @itemSplat) + $private = @(Get-ChildItem -Path "$PSScriptRoot\Private" @itemSplat) +} catch { + Write-Error $_ + throw 'Unable to get get file information from Public & Private src.' +} + +# dot source all .ps1 file(s) found +foreach ($file in @($public + $private)) { + try { + . $file.FullName + } catch { + throw ('Unable to dot source {0}' -f $file.FullName) + } +} + +# export all public functions +Export-ModuleMember -Function $public.Basename diff --git a/Public/Get-EnvironmentVariable.ps1 b/src/PSPreworkout/Public/Get-EnvironmentVariable.ps1 similarity index 87% rename from Public/Get-EnvironmentVariable.ps1 rename to src/PSPreworkout/Public/Get-EnvironmentVariable.ps1 index 1e5a652..e1d891e 100644 --- a/Public/Get-EnvironmentVariable.ps1 +++ b/src/PSPreworkout/Public/Get-EnvironmentVariable.ps1 @@ -14,10 +14,6 @@ function Get-EnvironmentVariable { Get-EnvironmentVariable -Name "PATH" Retrieves the value of the "PATH" environment variable. - .OUTPUTS - System.String - The value of the environment variable. - .NOTES Variable names are case-sensitive on Linux and macOS, but not on Windows. @@ -33,10 +29,11 @@ function Get-EnvironmentVariable { .LINK https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables #> - [Alias("gev")] - [Outputs([System.String])] + [Alias('gev')] + #[Outputs([System.String])] [CmdletBinding()] - [OutputType([string],[System.Collections.IDictionary])] + #[OutputType([string],[System.Collections.IDictionary])] + [OutputType([string])] param ( # The name of the environment variable to retrieve. If not specified, all environment variables are returned. [Parameter()] @@ -65,11 +62,11 @@ function Get-EnvironmentVariable { } if ($All) { - Write-Output "Process Environment Variables:" + Write-Output 'Process Environment Variables:' [Environment]::GetEnvironmentVariables([System.EnvironmentVariableTarget]::Process) - Write-Output "User Environment Variables:" + Write-Output 'User Environment Variables:' [Environment]::GetEnvironmentVariables([System.EnvironmentVariableTarget]::User) - Write-Output "Machine Environment Variables:" + Write-Output 'Machine Environment Variables:' [Environment]::GetEnvironmentVariables([System.EnvironmentVariableTarget]::Machine) } } diff --git a/Public/Install-OhMyPosh.ps1 b/src/PSPreworkout/Public/Install-OhMyPosh.ps1 similarity index 77% rename from Public/Install-OhMyPosh.ps1 rename to src/PSPreworkout/Public/Install-OhMyPosh.ps1 index 8ca3418..a884f9e 100644 --- a/Public/Install-OhMyPosh.ps1 +++ b/src/PSPreworkout/Public/Install-OhMyPosh.ps1 @@ -1,9 +1,10 @@ function Install-OhMyPosh { -<# + <# .SYNOPSIS Install Oh My Posh and add it to your profile. .DESCRIPTION + An over-engineered script to install Oh My Posh. .PARAMETER Method Specify which tool to install Oh My Posh with. @@ -28,47 +29,44 @@ function Install-OhMyPosh { Default - Installs "Meslo" as the default nerd font. Select - Lets you choose a nerd font from the list. - .NOTES - Author: Sam Erde - Created: 12/01/2023 + .EXAMPLE + Install-OhMyPosh #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingInvokeExpression', '', Justification = 'Invoke-Expression is used for online OMP installer.')] param ( [Parameter()] - [ValidateSet("winget","msstore")] - [string]$WingetSource = "winget", + [ValidateSet('winget', 'msstore')] + [string]$WingetSource = 'winget', [Parameter()] - [ValidateSet("chocolatey","direct","scoop","winget")] - [string]$Method = "direct", + [ValidateSet('chocolatey', 'direct', 'scoop', 'winget')] + [string]$Method = 'direct', [Parameter(ParameterSetName = 'Font')] - [switch]$InstallNerdFont, + [switch]$InstallNerdFont, [Parameter (ParameterSetName = 'Font')] - [ValidateSet("Default","Select One","Meslo")] - [string]$Font = "Default" + [ValidateSet('Default', 'Select One', 'Meslo')] + [string]$Font = 'Default' ) switch ($Method) { chocolatey { if (choco.exe) { choco install oh-my-posh - } - else { - Write-Error -Message "Chocolatey was not found. Please install it or try another method." -ErrorAction Stop + } else { + Write-Error -Message 'Chocolatey was not found. Please install it or try another method.' -ErrorAction Stop } } winget { # Install Oh My Posh using Winget if (winget.exe) { winget install --id JanDeDobbeleer.OhMyPosh --source $WingetSource - } - else { - $Response = Read-Host -Prompt "Winget was not found. Would you like to try to install it?" - if ($Response -eq "y" -or $Response -eq "yes") { + } else { + $Response = Read-Host -Prompt 'Winget was not found. Would you like to try to install it?' + if ($Response -eq 'y' -or $Response -eq 'yes') { try { $progressPreference = 'silentlyContinue' - Write-Information "Downloading WinGet and its dependencies..." + Write-Information 'Downloading WinGet and its dependencies...' Invoke-WebRequest -Uri https://aka.ms/getwinget -OutFile Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -OutFile Microsoft.VCLibs.x64.14.00.Desktop.appx Invoke-WebRequest -Uri https://github.com/microsoft/microsoft-ui-xaml/releases/download/v2.7.3/Microsoft.UI.Xaml.2.7.x64.appx -OutFile Microsoft.UI.Xaml.2.7.x64.appx @@ -79,9 +77,8 @@ function Install-OhMyPosh { if (winget.exe) { winget install --id JanDeDobbeleer.OhMyPosh --source $WingetSource } - } - catch { - Write-Error -Message "Sorry, we failed to download and install winget. Please refer to https://learn.microsoft.com/en-us/windows/package-manager/winget/#install-winget." + } catch { + Write-Error -Message 'Sorry, we failed to download and install winget. Please refer to https://learn.microsoft.com/en-us/windows/package-manager/winget/#install-winget.' } } } @@ -99,20 +96,19 @@ function Install-OhMyPosh { switch ($InstallNerdFont) { False { - Write-Debug "Not installing a nerd fonts" + Write-Debug 'Not installing a nerd fonts' } True { - if ($Font -eq "Default" -or $Fond -eq "Meslo") { - $FontName = "Meslo" - } - else { + if ($Font -eq 'Default' -or $Fond -eq 'Meslo') { + $FontName = 'Meslo' + } else { $FontName = $null } Write-Information -MessageData "Installing as current user to avoid requiring local admin rights. Please see notes at https://ohmyposh.dev/docs/installation/fonts. `n" -InformationAction Continue oh-my-posh font install $FontName --user # To Do: Script the configuration of Windows Terminal, VS Code, and default shell font in Windows registry. - Write-Information -MessageData "Please be sure to configure your shell to use the new font. See https://ohmyposh.dev/docs/installation/fonts." + Write-Information -MessageData 'Please be sure to configure your shell to use the new font. See https://ohmyposh.dev/docs/installation/fonts.' } } diff --git a/Public/Install-PowerShellISE.ps1 b/src/PSPreworkout/Public/Install-PowerShellISE.ps1 similarity index 68% rename from Public/Install-PowerShellISE.ps1 rename to src/PSPreworkout/Public/Install-PowerShellISE.ps1 index 5c6bb29..85caa60 100644 --- a/Public/Install-PowerShellISE.ps1 +++ b/src/PSPreworkout/Public/Install-PowerShellISE.ps1 @@ -9,9 +9,10 @@ function Install-PowerShellISE { while trying to add Windows Capabilities. This was created because Out-GridView in Windows PowerShell 5.1 does not work without the ISE installed. However, Out-GridView was rewritten and included in PowerShell 7 for Windows. - .NOTES - Author: Sam Erde + .EXAMPLE + Install-PowerShellISE + .NOTES To Do: - Check for Windows client vs Windows Server OS - Add parameter to make the Windows Update registry change optional @@ -19,23 +20,21 @@ function Install-PowerShellISE { #Requires -RunAsAdministrator - if ((Get-WindowsCapability -Name 'Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0' -Online).State -eq "Installed") { - Write-Output "The Windows PowerShell ISE is already installed." - } - else { + if ((Get-WindowsCapability -Name 'Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0' -Online).State -eq 'Installed') { + Write-Output 'The Windows PowerShell ISE is already installed.' + } else { # Resetting the Windows Update source sometimes resolves errors when trying to add Windows capabilities - $CurrentWUServer = Get-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "UseWUServer" | Select-Object -ExpandProperty UseWUServer - Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "UseWUServer" -Value 0 + $CurrentWUServer = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -Name 'UseWUServer' | Select-Object -ExpandProperty UseWUServer + Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -Name 'UseWUServer' -Value 0 Restart-Service wuauserv try { Get-WindowsCapability -Name Microsoft.Windows.PowerShell.ISE~~~~0.0.1.0 -Online | Add-WindowsCapability -Online -Verbose - } - catch { + } catch { Write-Error "There was a problem adding the Windows PowerShell ISE: $error" } - Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "UseWUServer" -Value $CurrentWUServer + Set-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU' -Name 'UseWUServer' -Value $CurrentWUServer Restart-Service wuauserv } } diff --git a/Public/New-ProfileWorkspace.ps1 b/src/PSPreworkout/Public/New-ProfileWorkspace.ps1 similarity index 77% rename from Public/New-ProfileWorkspace.ps1 rename to src/PSPreworkout/Public/New-ProfileWorkspace.ps1 index 8b80c17..80fd137 100644 --- a/Public/New-ProfileWorkspace.ps1 +++ b/src/PSPreworkout/Public/New-ProfileWorkspace.ps1 @@ -5,13 +5,7 @@ function New-ProfileWorkspace { .DESCRIPTION I wanted an easy way to maintain all of my CurrentUser PowerShell profiles and settings for Visual Studio Code - and Windows Terminal. This script creates a folder that contains: - - - Junction points to the locations of your CurrentUser PowerShell and Windows PowerShell folders - - Junction points to the locations of your settings for VS Code and Windows Terminal - - A Visual Studio Code workspace file that opens this new folder - - EditorConfig and Visual Studio Code settings files for consistent editing - - A .gitignore file in case you want to use this as a git repository (test?) + and Windows Terminal. .PARAMETER WorkspacePath The location to create your profile workspace in. The default value is a "Repositories/ProfileWorkspace" folder in @@ -26,10 +20,21 @@ function New-ProfileWorkspace { .PARAMETER Launch A switch that, if used, will launch the VS Code workspace upon completion of this script. + .EXAMPLE + New-ProfileWorkspace + .NOTES Author: Sam Erde, https://www.twitter.com/SamErde Created: 2023/11/28 + This script creates a folder that contains: + + - Junction points to the locations of your CurrentUser PowerShell and Windows PowerShell folders + - Junction points to the locations of your settings for VS Code and Windows Terminal + - A Visual Studio Code workspace file that opens this new folder + - EditorConfig and Visual Studio Code settings files for consistent editing + - A .gitignore file in case you want to use this as a git repository (test?) + Profile Locations on Windows: ~/Documents/PowerShell/profile.ps1 ~/Documents/PowerShell/Microsoft.PowerShell_profile.ps1 @@ -52,20 +57,20 @@ function New-ProfileWorkspace { .LINK https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles #> - [CmdletBinding()] + [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()] - [string] - $WorkspacePath = "~/Repositories/ProfileWorkspace", + [string] + $WorkspacePath = '~/Repositories/ProfileWorkspace', [Parameter()] - [string] - $PowerShellPath = ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/PowerShell' ), + [string] + $PowerShellPath = ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/PowerShell' ), [Parameter()] - [string] - $WindowsPowerShellPath = ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/WindowsPowerShell' ), + [string] + $WindowsPowerShellPath = ( Join-Path ([System.Environment]::GetFolderPath('MyDocuments')) '/WindowsPowerShell' ), [Parameter()] - [switch] - $Launch + [switch] + $Launch ) $CurrentInformationPreference = $InformationPreference @@ -75,39 +80,37 @@ function New-ProfileWorkspace { # Check for the workspace path before creating it if (-not (Test-Path $WorkspacePath) ) { - Write-Information -MessageData "Creating directory `"$WorkspacePath`"." -Tags "WorkspacePath" + Write-Information -MessageData "Creating directory `"$WorkspacePath`"." -Tags 'WorkspacePath' New-Item -ItemType Directory -Path $WorkspacePath | Out-Null - } - else { - Write-Information -MessageData "Found `"$WorkspacePath`". Continuing..." -Tags "WorkspacePath" + } else { + Write-Information -MessageData "Found `"$WorkspacePath`". Continuing..." -Tags 'WorkspacePath' } $WorkspacePath = (Get-Item $WorkspacePath).FullName Set-Location -Path $WorkspacePath $JunctionPoints = @{ - "PowerShell" = ( Join-Path -Path $WorkspacePath -ChildPath 'PowerShell' ) - "WindowsPowerShell" = ( Join-Path -Path $WorkspacePath -ChildPath 'WindowsPowerShell' ) - "Code" = ( Join-Path -Path $env:AppData -ChildPath '/Code/User' ) - "WindowsTerminal" = ( Join-Path -Path $env:LocalAppData -ChildPath '/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState' ) + 'PowerShell' = ( Join-Path -Path $WorkspacePath -ChildPath 'PowerShell' ) + 'WindowsPowerShell' = ( Join-Path -Path $WorkspacePath -ChildPath 'WindowsPowerShell' ) + 'Code' = ( Join-Path -Path $env:AppData -ChildPath '/Code/User' ) + 'WindowsTerminal' = ( Join-Path -Path $env:LocalAppData -ChildPath '/Packages/Microsoft.WindowsTerminal_8wekyb3d8bbwe/LocalState' ) } foreach ( $item in $JunctionPoints.GetEnumerator() ) { - Write-Information -MessageData "Looking for $($item.Name) at $($item.Value)" -Tags "JunctionPoints" + Write-Information -MessageData "Looking for $($item.Name) at $($item.Value)" -Tags 'JunctionPoints' if (-not (Test-Path -Path $($item.Value) -Verbose) ) { New-Item -Type Junction -Path $($item.Value) -Name $($item.Name) -Value $PowerShellPath | Out-Null - Write-Information -MessageData "Created $($item.Name) junction point in $($item.Value). No action required.`n" -Tags "JunctionPoints" - } - else { - Write-Information -MessageData "Found a $($item.Name) junction point at $($item.Value). No action required.`n" -Tags "JunctionPoints" + Write-Information -MessageData "Created $($item.Name) junction point in $($item.Value). No action required.`n" -Tags 'JunctionPoints' + } else { + Write-Information -MessageData "Found a $($item.Name) junction point at $($item.Value). No action required.`n" -Tags 'JunctionPoints' } } $workspaceContent = @{ - folders = @( - @{ - path = $WorkspacePath - } - ) + folders = @( + @{ + path = $WorkspacePath + } + ) } $WorkspaceContent | ConvertTo-Json | Set-Content (Join-Path $WorkspacePath 'ProfileWorkspace.code-workspace') -Encoding utf8 -Force diff --git a/Public/New-ScriptFromTemplate.ps1 b/src/PSPreworkout/Public/New-ScriptFromTemplate.ps1 similarity index 94% rename from Public/New-ScriptFromTemplate.ps1 rename to src/PSPreworkout/Public/New-ScriptFromTemplate.ps1 index da749a0..69b959c 100644 --- a/Public/New-ScriptFromTemplate.ps1 +++ b/src/PSPreworkout/Public/New-ScriptFromTemplate.ps1 @@ -29,13 +29,11 @@ function New-ScriptFromTemplate { .EXAMPLE New-Function -Name "Get-Demo" -Synopsis "Get a demo." -Description "This function gets a demo." -Alias "Get-Sample" - .NOTES - Author: Sam Erde - Version: 0.0.1 - Modified: 2024-07-02 #> [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'OK')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Making it pretty.')] [Alias('New-Script')] param ( # The name of the new function. diff --git a/Public/Set-EnvironmentVariable.ps1 b/src/PSPreworkout/Public/Set-EnvironmentVariable.ps1 similarity index 54% rename from Public/Set-EnvironmentVariable.ps1 rename to src/PSPreworkout/Public/Set-EnvironmentVariable.ps1 index 076c5c4..e0a1b50 100644 --- a/Public/Set-EnvironmentVariable.ps1 +++ b/src/PSPreworkout/Public/Set-EnvironmentVariable.ps1 @@ -1,6 +1,29 @@ function Set-EnvironmentVariable { - [Alias("sev")] + <# + .SYNOPSIS + Set environment variables. + + .DESCRIPTION + Set environment variables in any OS using .NET types. + + .PARAMETER Name + Parameter description + + .PARAMETER Value + Parameter description + + .PARAMETER Target + Parameter description + + .EXAMPLE + An example + + .NOTES + General notes + #> + [Alias('sev')] [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'OK')] param ( # The name of the environment variable to set. [Parameter(Mandatory)] diff --git a/Public/Update-AllTheThings.ps1 b/src/PSPreworkout/Public/Update-AllTheThings.ps1 similarity index 97% rename from Public/Update-AllTheThings.ps1 rename to src/PSPreworkout/Public/Update-AllTheThings.ps1 index 859e2e6..6bccb0b 100644 --- a/Public/Update-AllTheThings.ps1 +++ b/src/PSPreworkout/Public/Update-AllTheThings.ps1 @@ -26,20 +26,17 @@ function Update-AllTheThings { .INPUTS None. You can't pipe objects to Update-Everything. - .OUTPUTS - None. Update-Everything does not return any objects. - #> - [CmdletBinding()] - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Update-AllTheThings', Justification = 'Riding the "{___} all the things train!"')] + [CmdletBinding(SupportsShouldProcess)] + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', 'Update-AllTheThings', Justification = 'This is what we do.')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Interactive Use')] [Alias('UATT')] param ( # Allow updates to pre-release PowerShell modules - [Parameter()] - [switch] - $AllowPrerelease + #[Parameter()] + #[switch] + #$AllowPrerelease ) begin { diff --git a/src/PSScriptAnalyzerSettings.psd1 b/src/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 0000000..398258d --- /dev/null +++ b/src/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,39 @@ +@{ + #________________________________________ + #IncludeDefaultRules + IncludeDefaultRules = $true + #________________________________________ + #Severity + #Specify Severity when you want to limit generated diagnostic records to a specific subset: [ Error | Warning | Information ] + Severity = @('Error', 'Warning') + #________________________________________ + #CustomRulePath + #Specify CustomRulePath when you have a large set of custom rules you'd like to reference + #CustomRulePath = "Module\InjectionHunter\1.0.0\InjectionHunter.psd1" + #________________________________________ + #IncludeRules + #Specify IncludeRules when you only want to run specific subset of rules instead of the default rule set. + #IncludeRules = @('PSShouldProcess', + # 'PSUseApprovedVerbs') + #________________________________________ + #ExcludeRules + #Specify ExcludeRules when you want to exclude a certain rule from the the default set of rules. + #ExcludeRules = @( + # 'PSUseDeclaredVarsMoreThanAssignments' + #) + #________________________________________ + #Rules + #Here you can specify customizations for particular rules. Several examples are included below: + #Rules = @{ + # PSUseCompatibleCmdlets = @{ + # compatibility = @('core-6.1.0-windows', 'desktop-4.0-windows') + # } + # PSUseCompatibleSyntax = @{ + # Enable = $true + # TargetVersions = @( + # '3.0', + # '5.1', + # '6.2' + # ) + # } +} diff --git a/src/Tests/Integration/SampleIntegrationTest.Tests.ps1 b/src/Tests/Integration/SampleIntegrationTest.Tests.ps1 new file mode 100644 index 0000000..16c70c8 --- /dev/null +++ b/src/Tests/Integration/SampleIntegrationTest.Tests.ps1 @@ -0,0 +1,17 @@ +# BeforeAll { +# Set-Location -Path $PSScriptRoot +# $ModuleName = 'PSPreworkout' +# $PathToManifest = [System.IO.Path]::Combine('..', '..', 'Artifacts', "$ModuleName.psd1") +# #if the module is already in memory, remove it +# Get-Module $ModuleName -ErrorAction SilentlyContinue | Remove-Module -Force +# Import-Module $PathToManifest -Force +# } + +# Describe 'Integration Tests' -Tag Integration { +# Context 'First Integration Tests' { +# It 'should pass the first integration test' { +# # test logic +# } #it +# } +# } + diff --git a/src/Tests/SkipUnit/ExportedFunctions.Tests.ps1 b/src/Tests/SkipUnit/ExportedFunctions.Tests.ps1 new file mode 100644 index 0000000..a5cbf8b --- /dev/null +++ b/src/Tests/SkipUnit/ExportedFunctions.Tests.ps1 @@ -0,0 +1,61 @@ +BeforeAll { + Set-Location -Path $PSScriptRoot + $ModuleName = 'PSPreworkout' + $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") + Get-Module $ModuleName -ErrorAction SilentlyContinue | Remove-Module -Force + Import-Module $PathToManifest -Force + $manifestContent = Test-ModuleManifest -Path $PathToManifest + $moduleExported = Get-Command -Module $ModuleName | Select-Object -ExpandProperty Name + $manifestExported = ($manifestContent.ExportedFunctions).Keys +} +BeforeDiscovery { + Set-Location -Path $PSScriptRoot + $ModuleName = 'PSPreworkout' + $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") + $manifestContent = Test-ModuleManifest -Path $PathToManifest + $moduleExported = Get-Command -Module $ModuleName | Select-Object -ExpandProperty Name + $manifestExported = ($manifestContent.ExportedFunctions).Keys +} +Describe $ModuleName { + + Context 'Exported Commands' -Fixture { + + Context 'Number of commands' -Fixture { + + It 'Exports the same number of public functions as what is listed in the Module Manifest' { + $manifestExported.Count | Should -BeExactly $moduleExported.Count + } + + } + + Context 'Explicitly exported commands' { + + It 'Includes <_> in the Module Manifest ExportedFunctions' -ForEach $moduleExported { + $manifestExported -contains $_ | Should -BeTrue + } + + } + } #context_ExportedCommands + + Context 'Command Help' -Fixture { + Context '<_>' -Foreach $moduleExported { + + BeforeEach { + $help = Get-Help -Name $_ -Full + } + + It -Name 'Includes a Synopsis' -Test { + $help.Synopsis | Should -Not -BeNullOrEmpty + } + + It -Name 'Includes a Description' -Test { + $help.description.Text | Should -Not -BeNullOrEmpty + } + + It -Name 'Includes an Example' -Test { + $help.examples.example | Should -Not -BeNullOrEmpty + } + } + } #context_CommandHelp +} + diff --git a/src/Tests/SkipUnit/PSPreworkout-Module.Tests.ps1 b/src/Tests/SkipUnit/PSPreworkout-Module.Tests.ps1 new file mode 100644 index 0000000..5b10062 --- /dev/null +++ b/src/Tests/SkipUnit/PSPreworkout-Module.Tests.ps1 @@ -0,0 +1,49 @@ +BeforeAll { + #------------------------------------------------------------------------- + Set-Location -Path $PSScriptRoot + #------------------------------------------------------------------------- + $ModuleName = 'PSPreworkout' + $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1") + $PathToModule = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psm1") + #------------------------------------------------------------------------- +} +Describe 'Module Tests' -Tag Unit { + Context "Module Tests" { + $script:manifestEval = $null + It 'Passes Test-ModuleManifest' { + { $script:manifestEval = Test-ModuleManifest -Path $PathToManifest } | Should -Not -Throw + $? | Should -BeTrue + } #manifestTest + It 'root module PSPreworkout.psm1 should exist' { + $PathToModule | Should -Exist + $? | Should -BeTrue + } #psm1Exists + It 'manifest should contain PSPreworkout.psm1' { + $PathToManifest | + Should -FileContentMatchExactly "PSPreworkout.psm1" + } #validPSM1 + It 'should have a matching module name in the manifest' { + $script:manifestEval.Name | Should -BeExactly $ModuleName + } #name + It 'should have a valid description in the manifest' { + $script:manifestEval.Description | Should -Not -BeNullOrEmpty + } #description + It 'should have a valid author in the manifest' { + $script:manifestEval.Author | Should -Not -BeNullOrEmpty + } #author + It 'should have a valid version in the manifest' { + $script:manifestEval.Version -as [Version] | Should -Not -BeNullOrEmpty + } #version + It 'should have a valid guid in the manifest' { + { [guid]::Parse($script:manifestEval.Guid) } | Should -Not -Throw + } #guid + It 'should not have any spaces in the tags' { + foreach ($tag in $script:manifestEval.Tags) { + $tag | Should -Not -Match '\s' + } + } #tagSpaces + It 'should have a valid project Uri' { + $script:manifestEval.ProjectUri | Should -Not -BeNullOrEmpty + } #uri + } #context_ModuleTests +} #describe_ModuleTests