├── .github
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ ├── bug-report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
└── SECURITY.md
├── .gitignore
├── .readthedocs.yaml
├── .vscode
├── extensions.json
├── settings.json
└── tasks.json
├── CloudFormation
├── Manual
│ ├── PSGELFunctions.yml
│ ├── PSGalleryPipeline.yml
│ └── PowerShellCodeBuildGit.yml
└── PSGalleryExplorer
│ ├── ChildTemplates
│ ├── PSGEAlarms.yml
│ ├── PSGES3Buckets.yml
│ └── PSGESSM.yml
│ ├── ControlPlane-Parameters
│ └── PSGalleryExplorer.json
│ └── PSGalleryExplorer-ControlPlane.yml
├── CodeBuild
├── IntegrationTest
│ ├── New-IntegrationInfrastructure.ps1
│ ├── Remove-IntegrationInfrastructure.ps1
│ ├── Tests
│ │ └── Integration.Tests.ps1
│ └── buildspec.yml
├── UnitTestAndBuild
│ ├── Publish-CFNTemplatesToS3.ps1
│ ├── Validate-CFNTemplates.Tests.ps1
│ ├── Validate-JSONConfigurations.Tests.ps1
│ ├── buildspec.yml
│ ├── dotnet-install.ps1
│ └── dotnet-install.sh
├── configure_aws_credential.ps1
└── install_modules.ps1
├── LICENSE
├── README.md
├── actions_bootstrap.ps1
├── appveyor.yml
├── buildspec_powershell_windows.yml
├── buildspec_pwsh_linux.yml
├── buildspec_pwsh_windows.yml
├── configure_aws_credential.ps1
├── docs
├── CHANGELOG.md
├── Find-ModuleByCommand.md
├── Find-PSGModule.md
├── PSGalleryExplorer-Data_Collection.md
├── PSGalleryExplorer-FAQ.md
├── PSGalleryExplorer-Metrics.md
├── PSGalleryExplorer.md
├── assets
│ ├── PSGalleryExplorer.png
│ ├── PSGalleryExplorerIcon.png
│ ├── PSGalleryExplorer_datapull.png
│ ├── PSGalleryExplorer_favicon-32x32.png
│ ├── Serverless_PowerShell_DataPull.png
│ ├── diagrams
│ │ └── PSGalleryExplorer_datapull.drawio
│ ├── favicon_io
│ │ ├── android-chrome-192x192.png
│ │ ├── android-chrome-512x512.png
│ │ ├── apple-touch-icon.png
│ │ ├── favicon-16x16.png
│ │ ├── favicon.ico
│ │ └── site.webmanifest
│ └── psgalleryexplorer.gif
├── index.md
└── requirements.txt
├── install_modules.ps1
├── lambdafunctions
└── PowerShell
│ └── PubXMLMonitor
│ ├── PubXMLMonitor.build.ps1
│ ├── PubXMLMonitor.ps1
│ └── PubXMLMonitor.settings.ps1
├── mkdocs.yml
└── src
├── PSGalleryExplorer.Settings.ps1
├── PSGalleryExplorer.build.ps1
├── PSGalleryExplorer
├── Imports.ps1
├── PSGalleryExplorer.Format.ps1xml
├── PSGalleryExplorer.psd1
├── PSGalleryExplorer.psm1
├── Private
│ ├── Confirm-DataLocation.ps1
│ ├── Confirm-MetadataUpdate.ps1
│ ├── Confirm-XMLDataSet.ps1
│ ├── Expand-XMLDataSet.ps1
│ ├── Get-RemoteFile.ps1
│ ├── Import-XMLDataSet.ps1
│ └── Invoke-XMLDataCheck.ps1
└── Public
│ ├── Find-ModuleByCommand.ps1
│ └── Find-PSGModule.ps1
├── PSScriptAnalyzerSettings.psd1
└── Tests
├── Integration
└── PSGalleryExplorer.Tests.ps1
└── Unit
├── ExportedFunctions.Tests.ps1
├── PSGalleryExplorer-Module.Tests.ps1
├── Private
├── Confirm-DataLocation.Tests.ps1
├── Confirm-MetadataUpdate.Tests.ps1
├── Confirm-XMLDataSet.Tests.ps1
├── Expand-XMLDataSet.Tests.ps1
├── Get-RemoteFile.Tests.ps1
├── Import-XMLDataSet.Tests.ps1
└── Invoke-XMLDataCheck.Tests.ps1
└── Public
├── Find-ModuleByCommand.Tests.ps1
└── Find-PSGModule.Tests.ps1
/.github/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at **[EMAIL REQUIRED]**. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | 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)
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq)
--------------------------------------------------------------------------------
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Thanks for your interest in contributing to the **PSGalleryExplorer Project**.
4 |
5 | Whether it's a bug report, new feature, correction, or additional documentation, your feedback and contributions are appreciated.
6 |
7 | 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.
8 |
9 | Please note there is a code of conduct, please follow it in all your interactions with the project.
10 |
11 | ## Reporting Bugs/Feature Requests
12 |
13 | When filing an issue, please check [existing open](https://github.com/techthoughts2/PSGalleryExplorer/issues), or [recently closed](https://github.com/techthoughts2/PSGalleryExplorer/issues?q=is%3Aissue+is%3Aclosed), issues to make sure somebody else hasn't already
14 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
15 |
16 | * A reproducible test case or series of steps
17 | * The version of the module being used
18 | * Any modifications you've made relevant to the bug
19 | * Anything unusual about your environment or deployment
20 |
21 | ## Contributing via Pull Requests
22 |
23 | Contributions via pull requests are much appreciated. Before sending a pull request, please ensure that:
24 |
25 | 1. You are working against the latest source on the *Enhancements* branch.
26 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
27 | 3. You open an issue to discuss any significant work - I'd hate for your time to be wasted.
28 |
29 | To send a pull request, please:
30 |
31 | 1. Fork the repository.
32 | 2. Checkout the *Enhancements* branch
33 | 3. Modify the source; please focus on the specific change you are contributing. Please refrain from code styling changes, it will be harder to focus on your change.
34 | 4. Ensure local tests pass.
35 | 5. Commit to your fork using clear commit messages.
36 | 6. Send a pull request, answering any default questions in the pull request interface.
37 |
38 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
39 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
40 |
41 | ## Finding contributions to work on
42 |
43 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (dev/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/techthoughts2/PSGalleryExplorer/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) issues is a great place to start.
44 |
45 | ## Code of Conduct
46 |
47 | This project has a [Code of Conduct](CODE_OF_CONDUCT.md).
48 |
49 | ## Licensing
50 |
51 | See the [LICENSE](../LICENSE) file for our project's licensing.
52 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug-report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Submit a new bug
4 | title: Bug report
5 | labels: 'bug'
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
12 | ### Expected Behavior
13 |
14 |
15 | ### Current Behavior
16 |
17 |
18 | ### Possible Solution
19 |
20 |
21 | ### Steps to Reproduce
22 |
23 |
24 |
25 | 1.
26 | 2.
27 | 3.
28 | 4.
29 |
30 | ### Context (Environment)
31 |
32 |
33 | * Operating System and version as reported by `$PSVersionTable.OS`:
34 | * PowerShell versions as reported by `$PSVersionTable.PSEdition`:
35 |
36 |
37 |
38 | ### Detailed Description
39 |
40 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: 'Feature request'
5 | labels: 'enhancement'
6 | assignees: ''
7 |
8 | ---
9 |
10 | ### Description
11 |
12 |
13 | ### Describe the solution you'd like
14 |
15 |
16 | ### Describe any alternatives you've considered
17 |
18 |
19 | ### Additional context
20 |
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | # Pull Request
2 |
3 | ## Issue
4 |
5 | Issue #, if available:
6 |
7 | ## Description
8 |
9 | Description of changes:
10 |
11 | ## License
12 |
13 | By submitting this pull request, I confirm that my contribution is made under the terms of the projects associated license.
14 |
--------------------------------------------------------------------------------
/.github/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 |
5 | If you discover a vulnerability in PSGalleryExplorer, please follow the _following process_:
6 |
7 | 1. Open a generic bug issue advising you have discovered a vulnerability.
8 | - Avoid sharing specifics or details of the vulnerability in an open GitHub issue.
9 | 2. A repo owner will reach out to you to establish a private form of communication.
10 | 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.
11 |
12 | Please **do not disclose the vulnerability publicly** until a fix is released!
13 |
14 | 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.
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Archive
2 | Artifacts
3 | cov.xml
4 | coverage.xml
5 | *.bkp
6 | *.dtmp
7 | # OS generated files #
8 | ######################
9 | .DS_Store
10 | .DS_Store?
11 | ._*
12 | .Spotlight-V100
13 | .Trashes
14 | ehthumbs.db
15 | Thumbs.db
16 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # https://docs.readthedocs.io/en/stable/config-file/index.html
2 |
3 | # .readthedocs.yaml
4 | # Read the Docs configuration file
5 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
6 |
7 | # Required
8 | version: 2
9 |
10 | build:
11 | os: ubuntu-22.04
12 | tools:
13 | python: "3.11"
14 |
15 | mkdocs:
16 | configuration: mkdocs.yml
17 |
18 | python:
19 | install:
20 | - requirements: docs/requirements.txt
21 |
22 | # # Build PDF & ePub
23 | formats: all
24 | # - epub
25 | # - pdf
26 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | "ms-vscode.PowerShell",
6 | "ryanluker.vscode-coverage-gutters",
7 | "DavidAnson.vscode-markdownlint",
8 | "aaron-bond.better-comments",
9 | "aws-scripting-guy.cform",
10 | "amazonwebservices.aws-toolkit-vscode",
11 | "kddejong.vscode-cfn-lint",
12 | "DanielThielking.aws-cloudformation-yaml",
13 | "redhat.vscode-yaml"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "markdownlint.config": {
3 | "default": true,
4 | "MD007": {
5 | "indent": 4
6 | },
7 | "no-hard-tabs": false
8 | },
9 | // When enabled, will trim trailing whitespace when you save a file.
10 | "files.trimTrailingWhitespace": true,
11 | // specifies the location of the explicity ScriptAnalyzer settings file
12 | "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
13 | // specifies the PowerShell coding style used in this project (https://github.com/PoshCode/PowerShellPracticeAndStyle/issues/81)
14 | "powershell.codeFormatting.preset": "Stroustrup",
15 | "cSpell.enableFiletypes": [
16 | "!yaml",
17 | "powershell"
18 | ],
19 | "cSpell.words": [
20 | "Allman",
21 | "allmodules",
22 | "amazonlinux",
23 | "APIURL",
24 | "buildspec",
25 | "Catesta",
26 | "Clixml",
27 | "datetime",
28 | "defaultparametersetname",
29 | "discoverability",
30 | "fanout",
31 | "gldata",
32 | "jakemorrison",
33 | "lambdafunctions",
34 | "notcontains",
35 | "notin",
36 | "OTBS",
37 | "Populator",
38 | "psgalleryexplorer",
39 | "PSGE",
40 | "PSGES",
41 | "pwsh",
42 | "ratelimit",
43 | "Ryver",
44 | "Sightview",
45 | "Stroustrup",
46 | "telegramchannel",
47 | "telegramtoken"
48 | ]
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/CloudFormation/Manual/PSGELFunctions.yml:
--------------------------------------------------------------------------------
1 | ---
2 | AWSTemplateFormatVersion: "2010-09-09"
3 |
4 | Description: PSGalleryExplorer S3 Code Bucket for Lambda Functions
5 |
6 | Parameters:
7 | ServiceName:
8 | Type: String
9 | Description: 'Name of the service that will be used to tag each resource.'
10 | Default: PSGalleryExplorer
11 | # The bucket name can be between 3 and 63 characters long, and can contain only lower-case characters, numbers, periods, and dashes.
12 | # Each label in the bucket name must start with a lowercase letter or number.
13 | # The bucket name cannot contain underscores, end with a dash, have consecutive periods, or use dashes adjacent to periods.
14 | # The bucket name cannot be formatted as an IP address (198.51.100.24).
15 | BucketName:
16 | Type: String
17 | Description: Hard coded S3 bucketname
18 | Default: psge
19 |
20 | Resources:
21 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket.html
22 | PSGELFunctions:
23 | Type: AWS::S3::Bucket
24 | DeletionPolicy: Delete
25 | Properties:
26 | # AccelerateConfiguration: AccelerateConfiguration
27 | # AccessControl: String
28 | # AnalyticsConfigurations:
29 | # - AnalyticsConfiguration
30 | BucketEncryption:
31 | ServerSideEncryptionConfiguration:
32 | - ServerSideEncryptionByDefault:
33 | SSEAlgorithm: AES256
34 | BucketName: !Sub ${BucketName}-psgelfunctions
35 | # CorsConfiguration:
36 | # CorsConfiguration
37 | # InventoryConfigurations:
38 | # - InventoryConfiguration
39 | # LifecycleConfiguration:
40 | # Rules:
41 | # -
42 | # AbortIncompleteMultipartUpload:
43 | # DaysAfterInitiation: 7
44 | # Status: Enabled
45 | # Transitions:
46 | # -
47 | # StorageClass: GLACIER
48 | # TransitionInDays: 30
49 | # LoggingConfiguration:
50 | # DestinationBucketName: !Ref S3BucketLogs
51 | # LogFilePrefix: '/logs/updateapcdata/'
52 | # MetricsConfigurations:
53 | # - MetricsConfiguration
54 | # NotificationConfiguration:
55 | # TopicConfigurations:
56 | # -
57 | # Event: s3:ObjectCreated:*
58 | # Topic: !Ref UpdateSNSTopic
59 | # ObjectLockConfiguration:
60 | # ObjectLockConfiguration
61 | # ObjectLockEnabled: Boolean
62 | PublicAccessBlockConfiguration:
63 | BlockPublicAcls: true
64 | BlockPublicPolicy: true
65 | IgnorePublicAcls: true
66 | RestrictPublicBuckets: true
67 | # ReplicationConfiguration:
68 | # ReplicationConfiguration
69 | # VersioningConfiguration:
70 | # VersioningConfiguration
71 | # WebsiteConfiguration:
72 | # WebsiteConfiguration
73 | Tags:
74 | - Key: Service
75 | Value: !Ref ServiceName
76 |
77 | Outputs:
78 | PSGELFunctionsBucketName:
79 | Value: !Ref PSGELFunctions
80 | Description: Name of the PSGalleryExplorer Amazon S3 bucket that holds Lambda functions
81 | Export:
82 | Name: PSGELFBN
83 | PSGELFunctionsArn:
84 | Description: Arn of the PSGalleryExplorer Amazon S3 bucket that holds Lambda functions
85 | Value: !GetAtt PSGELFunctions.Arn
86 | PSGELFunctionsDomainName:
87 | Description: Domain name of the PSGalleryExplorer Amazon S3 bucket that holds Lambda functions
88 | Value: !GetAtt PSGELFunctions.DomainName
89 |
--------------------------------------------------------------------------------
/CloudFormation/PSGalleryExplorer/ChildTemplates/PSGEAlarms.yml:
--------------------------------------------------------------------------------
1 | ---
2 | AWSTemplateFormatVersion: '2010-09-09'
3 |
4 | Description: 'AUTOMATED: PSGalleryExplorer - alarms deployment'
5 |
6 | Transform: 'AWS::Serverless-2016-10-31'
7 |
8 | Parameters:
9 | ServiceName:
10 | Type: String
11 | Description: The name of the service being deployed. Used for Developer AWS Account Resource Names.
12 |
13 | LambdaS3BucketName:
14 | Type: String
15 | Description: The S3 Bucket holding the Lambda code
16 |
17 | LMFunctionS3KeyPubXMLMonitor:
18 | Type: String
19 | Description: S3 Key for the PubXMLMonitor Lambda function(s) zip file
20 |
21 | LMFunctionHandlerPubXMLMonitor:
22 | Type: String
23 | Description: PubXMLMonitor Lambda HANDLER provided by New-AWSPowerShellLambdaPackage during build
24 |
25 | ResourceType:
26 | Type: String
27 | Description: Determine the type of resource that will be deployed
28 | AllowedValues:
29 | - core
30 | - dev
31 | - test
32 | - prod
33 |
34 | Resources:
35 | # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html
36 | # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html
37 | # https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-cloudwatchevent.html
38 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html#cfn-events-rule-eventpattern
39 | PubXMLMonitor:
40 | Type: 'AWS::Serverless::Function'
41 | Properties:
42 | # Architectures: x86_64
43 | # AssumeRolePolicyDocument: JSON
44 | # AutoPublishAlias: String
45 | # AutoPublishCodeSha256: String
46 | # CodeSigningConfigArn: String
47 | CodeUri:
48 | Bucket: !Ref LambdaS3BucketName
49 | Key: !Ref LMFunctionS3KeyPubXMLMonitor
50 | # DeadLetterQueue: Map | DeadLetterQueue
51 | # DeploymentPreference: DeploymentPreference
52 | Description: 'Determines age of PubXML and sends to CloudWatch Metric'
53 | Environment:
54 | Variables:
55 | S3_BUCKET_NAME: !ImportValue PubXMLDataBN
56 | SERVICE_NAME: !Ref ServiceName
57 | # EphemeralStorage: EphemeralStorage
58 | # EventInvokeConfig: EventInvokeConfiguration
59 | # Events: EventSource
60 | # FileSystemConfigs: List
61 | # FunctionName:
62 | # FunctionUrlConfig: FunctionUrlConfig
63 | Handler: !Ref LMFunctionHandlerPubXMLMonitor
64 | # ImageConfig: ImageConfig
65 | # ImageUri: String
66 | # InlineCode: String
67 | # KmsKeyArn: String
68 | # Layers: List
69 | MemorySize: 768
70 | # PackageType: String
71 | # PermissionsBoundary: String
72 | Policies:
73 | - AWSLambdaBasicExecutionRole
74 | - CloudWatchPutMetricPolicy: {}
75 | - S3CrudPolicy:
76 | BucketName: !ImportValue PubXMLDataBN
77 | - SSMParameterReadPolicy:
78 | ParameterName: telegramtoken
79 | - SSMParameterReadPolicy:
80 | ParameterName: telegramchannel
81 | # ProvisionedConcurrencyConfig: ProvisionedConcurrencyConfig
82 | # ReservedConcurrentExecutions: Integer
83 | # Role: String
84 | # RolePath: String
85 | Runtime: dotnet6
86 | # RuntimeManagementConfig: RuntimeManagementConfig
87 | # SnapStart: SnapStart
88 | Tags:
89 | ServiceName: !Ref ServiceName
90 | StackName: !Ref AWS::StackName
91 | ResourceType: !Ref ResourceType
92 | Events:
93 | RateSchedule:
94 | Type: Schedule
95 | Properties:
96 | Enabled: true
97 | Schedule: 'rate(1 day)'
98 | Timeout: 60
99 |
100 | #https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html
101 | PubXMLMonitorLogGroup:
102 | Type: AWS::Logs::LogGroup
103 | DependsOn: PubXMLMonitor
104 | DeletionPolicy: Delete
105 | UpdateReplacePolicy: Retain
106 | Properties:
107 | # KmsKeyId: String
108 | LogGroupName: !Sub '/aws/lambda/${PubXMLMonitor}'
109 | RetentionInDays: 14
110 | Tags:
111 | - Key: ServiceName
112 | Value: !Ref ServiceName
113 | - Key: StackName
114 | Value: !Ref AWS::StackName
115 | - Key: ResourceType
116 | Value: !Ref ResourceType
117 |
118 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cw-alarm.html
119 | PubXMLMonitorAlarm:
120 | Type: AWS::CloudWatch::Alarm
121 | Properties:
122 | ActionsEnabled: true
123 | AlarmActions:
124 | - !ImportValue AlertSNSTopic
125 | AlarmDescription: Alarms if the PubXML file is more than 8 days old.
126 | AlarmName: PubXMLMonitor
127 | ComparisonOperator: GreaterThanOrEqualToThreshold
128 | # DatapointsToAlarm: Integer
129 | # EvaluateLowSampleCountPercentile: String
130 | Dimensions:
131 | - Name: PubXML
132 | Value: DaysOld
133 | EvaluationPeriods: 1
134 | # ExtendedStatistic: String
135 | # InsufficientDataActions:
136 | # - String
137 | MetricName: PubXMLAge
138 | # Metrics:
139 | # - MetricDataQuery
140 | Namespace: !Ref ServiceName
141 | # OKActions:
142 | # - String
143 | Period: 3600
144 | Statistic: Maximum
145 | Threshold: 8
146 | # ThresholdMetricId: String
147 | TreatMissingData: notBreaching
148 | # Unit: String
149 |
150 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudwatch-dashboard.html
151 | PSGEPubXMLMonitorDashboard:
152 | Type: AWS::CloudWatch::Dashboard
153 | Properties:
154 | DashboardName: !Sub '${ServiceName}-PSGEPubXMLMonitorDashboard'
155 | DashboardBody: !Sub |
156 | {
157 | "widgets": [
158 | {
159 | "height": 10,
160 | "width": 20,
161 | "y": 12,
162 | "x": 0,
163 | "type": "metric",
164 | "properties": {
165 | "metrics": [
166 | [
167 | "PSGalleryExplorer",
168 | "PubXMLAge",
169 | "PubXML",
170 | "DaysOld",
171 | {
172 | "region": "us-west-2",
173 | "label": "Data Cache Age (Days)"
174 | }
175 | ]
176 | ],
177 | "view": "timeSeries",
178 | "stacked": false,
179 | "region": "us-west-2",
180 | "period": 86400,
181 | "stat": "Maximum",
182 | "start": "-P90D",
183 | "end": "P0D",
184 | "title": "PSGalleryExplorer Data Cache Age Metric",
185 | "yAxis": {
186 | "left": {
187 | "label": "Days Old",
188 | "min": 0
189 | }
190 | },
191 | "annotations": {
192 | "horizontal": [
193 | {
194 | "label": "Untitled annotation",
195 | "value": 8
196 | }
197 | ]
198 | }
199 | }
200 | },
201 | {
202 | "height": 10,
203 | "width": 20,
204 | "y": 0,
205 | "x": 0,
206 | "type": "metric",
207 | "properties": {
208 | "metrics": [
209 | [
210 | "AWS/CloudFront",
211 | "Requests",
212 | "Region",
213 | "Global",
214 | "DistributionId",
215 | "E253EO4S3ELURG",
216 | {
217 | "region": "us-east-1"
218 | }
219 | ]
220 | ],
221 | "view": "timeSeries",
222 | "stacked": false,
223 | "region": "us-west-2",
224 | "period": 86400,
225 | "stat": "Sum",
226 | "start": "-P90D",
227 | "end": "P0D",
228 | "title": "Data Cache Download Requests",
229 | "yAxis": {
230 | "left": {
231 | "label": "Download Count",
232 | "min": 0
233 | }
234 | },
235 | "setPeriodToTimeRange": true
236 | }
237 | },
238 | {
239 | "height": 2,
240 | "width": 20,
241 | "y": 10,
242 | "x": 0,
243 | "type": "alarm",
244 | "properties": {
245 | "title": "Over 8 Days Alarm Status",
246 | "alarms": [
247 | "arn:aws:cloudwatch:us-west-2:699483786831:alarm:PubXMLMonitor"
248 | ]
249 | }
250 | }
251 | ]
252 | }
253 |
254 | Outputs:
255 | PubXMLMonitorARN:
256 | Description: Arn for PubXMLMonitor Lambda
257 | Value: !GetAtt PubXMLMonitor.Arn
258 | Export:
259 | Name: !Sub ${ServiceName}-PubXMLMonitorARN
260 |
261 | PubXMLMonitorAlarmARN:
262 | Description: PubXMLMonitorAlarm Alarm ARN
263 | Value: !GetAtt PubXMLMonitorAlarm.Arn
264 | Export:
265 | Name: !Sub ${ServiceName}-PubXMLMonitorAlarmARN
266 |
--------------------------------------------------------------------------------
/CloudFormation/PSGalleryExplorer/ChildTemplates/PSGESSM.yml:
--------------------------------------------------------------------------------
1 | ---
2 | AWSTemplateFormatVersion: '2010-09-09'
3 |
4 | Description: 'AUTOMATED: PSGalleryExplorer - SSM deployment'
5 |
6 | Parameters:
7 | ServiceName:
8 | Type: String
9 | Description: The name of the service being deployed. Used for Developer AWS Account Resource Names.
10 |
11 | ResourceType:
12 | Type: String
13 | Description: Determine the type of resource that will be deployed
14 | AllowedValues:
15 | - core
16 | - dev
17 | - test
18 | - prod
19 |
20 | Resources:
21 |
22 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
23 | PSGEMaintenanceWindowTaskRole:
24 | Type: AWS::IAM::Role
25 | Properties:
26 | RoleName: !Sub '${ServiceName}-PSGEMaintenanceWindowTaskRole'
27 | Tags:
28 | - Key: ServiceName
29 | Value: !Ref ServiceName
30 | - Key: StackName
31 | Value: !Ref AWS::StackName
32 | - Key: ResourceType
33 | Value: !Ref ResourceType
34 | AssumeRolePolicyDocument:
35 | Version: '2012-10-17'
36 | Statement:
37 | - Effect: Allow
38 | Principal:
39 | Service: ssm.amazonaws.com
40 | Action:
41 | - sts:AssumeRole
42 | Path: /
43 | ManagedPolicyArns:
44 | - arn:aws:iam::aws:policy/service-role/AmazonSSMMaintenanceWindowRole
45 | Policies:
46 | - PolicyName: pass-role
47 | PolicyDocument:
48 | Version: '2012-10-17'
49 | Statement:
50 | - Effect: Allow
51 | Action:
52 | - iam:PassRole
53 | Resource:
54 | - !GetAtt PSGESSMMaintenanceWindowTaskCommandRole.Arn
55 |
56 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
57 | PSGESSMMaintenanceWindowTaskCommandRole:
58 | Type: AWS::IAM::Role
59 | Properties:
60 | RoleName: !Sub '${ServiceName}-PSGESSMMaintenanceWindowTaskCommandRole'
61 | Tags:
62 | - Key: ServiceName
63 | Value: !Ref ServiceName
64 | - Key: StackName
65 | Value: !Ref AWS::StackName
66 | - Key: ResourceType
67 | Value: !Ref ResourceType
68 | AssumeRolePolicyDocument:
69 | Version: '2012-10-17'
70 | Statement:
71 | - Effect: Allow
72 | Principal:
73 | Service: ssm.amazonaws.com
74 | Action:
75 | - sts:AssumeRole
76 | Path: /
77 | # ManagedPolicyArns:
78 | # - arn:${AWS::Partition}:iam::${AWS::Partition}:policy/service-role/AmazonSSMMaintenanceWindowRole
79 | # # - arn:${AWS::Partition}:iam::${AWS::Partition}:policy/service-role/AmazonSSMAutomationRole
80 | # - arn:${AWS::Partition}:iam::${AWS::Partition}:policy/CloudWatchFullAccess
81 | Policies:
82 | - PolicyName: SSMPublishAlertTopic
83 | PolicyDocument:
84 | Version: '2012-10-17'
85 | Statement:
86 | - Effect: Allow
87 | Action:
88 | - sns:Publish
89 | Resource:
90 | - !ImportValue AlertSNSTopic
91 |
92 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindow.html
93 | PSGEMaintWindow:
94 | Type: AWS::SSM::MaintenanceWindow
95 | Properties:
96 | AllowUnassociatedTargets: false
97 | Cutoff: 0
98 | Description: 'Maintenance window to fetch combined XML file'
99 | Duration: 1
100 | # EndDate: String
101 | Name: !Sub ${ServiceName}-PSGEMaintWindow
102 | Schedule: rate(7 days)
103 | # Schedule: rate(5 minutes)
104 | # ScheduleOffset: Integer
105 | ScheduleTimezone: 'US/Central'
106 | StartDate: '2023-04-20T21:30:00-06:00'
107 | Tags:
108 | - Key: ServiceName
109 | Value: !Ref ServiceName
110 | - Key: StackName
111 | Value: !Ref AWS::StackName
112 | - Key: ResourceType
113 | Value: !Ref ResourceType
114 |
115 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtarget.html
116 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtarget-targets.html
117 | PSGEMaintTarget:
118 | Type: AWS::SSM::MaintenanceWindowTarget
119 | Properties:
120 | Description: Hybrid Worker Target
121 | Name: !Sub ${ServiceName}-HybridWorkerTarget
122 | OwnerInformation: PSGE SSM XML Sourcing
123 | ResourceType: INSTANCE
124 | Targets:
125 | - Key: tag:type
126 | Values:
127 | - hybridworker
128 | WindowId: !Ref PSGEMaintWindow
129 |
130 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ssm-maintenancewindowtask.html
131 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtask-taskinvocationparameters.html
132 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtask-maintenancewindowruncommandparameters.html
133 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtask-cloudwatchoutputconfig.html
134 | # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ssm-maintenancewindowtask-notificationconfig.html
135 | # https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_SendCommand.html
136 | # https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-permissions.html#maintenance-window-tasks-service-role
137 | # https://docs.aws.amazon.com/systems-manager/latest/userguide/monitoring-sns-notifications.html
138 | # https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-maintenance-perm-console.html
139 | PSGEMaintWindowRunCommandTask:
140 | Type: 'AWS::SSM::MaintenanceWindowTask'
141 | Properties:
142 | CutoffBehavior: CANCEL_TASK
143 | Description: TBD
144 | # LoggingInfo:
145 | # LoggingInfo
146 | MaxConcurrency: 1
147 | MaxErrors: 1
148 | Name: !Sub ${ServiceName}-XMLSourcingTask
149 | Priority: 0
150 | ServiceRoleArn: !GetAtt PSGEMaintenanceWindowTaskRole.Arn
151 | Targets:
152 | - Key: WindowTargetIds
153 | Values:
154 | - !Ref PSGEMaintTarget
155 | TaskArn: AWS-RunPowerShellScript
156 | TaskInvocationParameters:
157 | MaintenanceWindowRunCommandParameters:
158 | CloudWatchOutputConfig:
159 | CloudWatchLogGroupName: !Ref PSGESSMRunCommandLogGroup
160 | CloudWatchOutputEnabled: true
161 | Comment: This is a comment
162 | # DocumentHash: String
163 | # DocumentHashType: String
164 | # DocumentVersion: String
165 | NotificationConfig:
166 | NotificationArn: !ImportValue AlertSNSTopic
167 | NotificationEvents:
168 | - TimedOut
169 | - Cancelled
170 | - Failed
171 | NotificationType: Command
172 | # OutputS3BucketName: !Ref PSGESSMLogBucket
173 | # OutputS3KeyPrefix: PSGE
174 | Parameters:
175 | executionTimeout:
176 | - '3600'
177 | commands:
178 | - !Sub if(-not(Test-Path 'C:\${ServiceName}\FinalZip\${ServiceName}.zip')){throw 'Cannot find zip file'}
179 | - !Sub $zipFilePath = 'C:\${ServiceName}\FinalZip\${ServiceName}.zip';$maxAge = New-TimeSpan -Days 4;$zipAge = New-TimeSpan -Start (Get-Item $zipFilePath).LastWriteTime -End (Get-Date);if ($zipAge -gt $maxAge) {throw 'stale zip file'}
180 | - !Sub
181 | - 'aws s3 cp "C:\${ServiceName}\FinalZip\${ServiceName}.zip" "s3://${bucketName}"'
182 | - bucketName:
183 | 'Fn::ImportValue': PubXMLDataBN
184 | - !Sub
185 | - 'aws s3 cp "C:\${ServiceName}\FinalZip\${ServiceName}.json" "s3://${bucketName}"'
186 | - bucketName:
187 | 'Fn::ImportValue': PubXMLDataBN
188 | workingDirectory:
189 | - ""
190 | ServiceRoleArn: !GetAtt PSGESSMMaintenanceWindowTaskCommandRole.Arn
191 | TimeoutSeconds: 300
192 | # TaskParameters: Json
193 | TaskType: RUN_COMMAND
194 | WindowId: !Ref PSGEMaintWindow
195 |
196 | # #https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html
197 | PSGESSMRunCommandLogGroup:
198 | Type: AWS::Logs::LogGroup
199 | DeletionPolicy: Delete
200 | UpdateReplacePolicy: Retain
201 | Properties:
202 | # DataProtectionPolicy: Json
203 | # KmsKeyId: String
204 | LogGroupName: '/aws/ssm/PSGESSMRunCommandLogGroup'
205 | RetentionInDays: 30
206 | Tags:
207 | - Key: ServiceName
208 | Value: !Ref ServiceName
209 | - Key: StackName
210 | Value: !Ref AWS::StackName
211 | - Key: ResourceType
212 | Value: !Ref ResourceType
213 |
214 | Outputs:
215 | PSGEMaintWindowID:
216 | Description: ID of PSGEMaintWindow
217 | Value: !Ref PSGEMaintWindow
218 | Export:
219 | Name: !Sub ${ServiceName}-PSGEMaintWindowID
220 |
221 | PSGEMaintTargetID:
222 | Description: ID of PSGEMaintTarget
223 | Value: !Ref PSGEMaintTarget
224 |
225 | PSGEMaintWindowRunCommandTaskID:
226 | Description: ID of PSGEMaintWindowRunCommandTask
227 | Value: !Ref PSGEMaintWindowRunCommandTask
228 |
--------------------------------------------------------------------------------
/CloudFormation/PSGalleryExplorer/ControlPlane-Parameters/PSGalleryExplorer.json:
--------------------------------------------------------------------------------
1 | {
2 | "Parameters": {
3 | "ServiceName": "PSGalleryExplorer",
4 | "LMFunctionS3KeyPubXMLMonitor": "< This value is replace by the UnitTestAndBuild CodeBuild step in the Lambda's build file >",
5 | "LMFunctionHandlerPubXMLMonitor": "< This value is replace by the UnitTestAndBuild CodeBuild step in the Lambda's build file >",
6 | "ArtifactS3Bucket": "will be replaced during CodeBuild process",
7 | "ArtifactS3KeyPrefix": "will be replaced during CodeBuild process"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/CloudFormation/PSGalleryExplorer/PSGalleryExplorer-ControlPlane.yml:
--------------------------------------------------------------------------------
1 | ---
2 | AWSTemplateFormatVersion: '2010-09-09'
3 |
4 | Description: 'AUTOMATED: PSGalleryExplorer: Control Plane'
5 |
6 | Parameters:
7 | ServiceName:
8 | Type: String
9 | Description: 'Name of the service that will be used to tag each resource.'
10 |
11 | LMFunctionS3KeyPubXMLMonitor:
12 | Type: String
13 | Description: S3 Key for the PubXMLMonitor Lambda function(s) zip file
14 |
15 | LMFunctionHandlerPubXMLMonitor:
16 | Type: String
17 | Description: PubXMLMonitor Lambda HANDLER provided by New-AWSPowerShellLambdaPackage during build
18 |
19 | ArtifactS3Bucket:
20 | Type: String
21 | Description: S3 Bucket for CodePipeline Artifacts
22 |
23 | ArtifactS3KeyPrefix:
24 | Type: String
25 | Description: S3 Key Prefix for CodePipeline Artifacts
26 |
27 | Resources:
28 | # Deploys the s3 buckets used for the PSGalleryExplorer project
29 | PSGES3Buckets:
30 | Type: AWS::CloudFormation::Stack
31 | DeletionPolicy: Delete
32 | UpdateReplacePolicy: Delete
33 | Properties:
34 | TemplateURL: !Sub
35 | - 'https://${ArtifactS3Bucket}.s3.amazonaws.com/${ArtifactS3KeyPrefix}/${FileName}'
36 | - #AWSRegion: !Ref "AWS::Region"
37 | ArtifactS3Bucket: !Ref ArtifactS3Bucket
38 | ArtifactS3KeyPrefix: !Ref ArtifactS3KeyPrefix
39 | FileName: CloudFormation/PSGalleryExplorer/ChildTemplates/PSGES3Buckets.yml
40 | TimeoutInMinutes: 5 #make sure it can actually complete in this time period
41 | Parameters: #much match the parameters of nested template
42 | ServiceName: !Ref ServiceName
43 | ResourceType: prod
44 | Tags:
45 | - Key: ServiceName
46 | Value: !Ref ServiceName
47 | - Key: StackName
48 | Value: !Ref AWS::StackName
49 |
50 | # Deploys the alarms used for the PSGalleryExplorer project
51 | PSGEAlarms:
52 | Type: AWS::CloudFormation::Stack
53 | DeletionPolicy: Delete
54 | UpdateReplacePolicy: Delete
55 | DependsOn: PSGES3Buckets
56 | Properties:
57 | TemplateURL: !Sub
58 | - 'https://${ArtifactS3Bucket}.s3.amazonaws.com/${ArtifactS3KeyPrefix}/${FileName}'
59 | - #AWSRegion: !Ref "AWS::Region"
60 | ArtifactS3Bucket: !Ref ArtifactS3Bucket
61 | ArtifactS3KeyPrefix: !Ref ArtifactS3KeyPrefix
62 | FileName: CloudFormation/PSGalleryExplorer/ChildTemplates/PSGEAlarms.yml
63 | TimeoutInMinutes: 5 #make sure it can actually complete in this time period
64 | Parameters: #much match the parameters of nested template
65 | ServiceName: !Ref ServiceName
66 | LambdaS3BucketName: !Ref ArtifactS3Bucket
67 | LMFunctionS3KeyPubXMLMonitor: !Ref LMFunctionS3KeyPubXMLMonitor
68 | LMFunctionHandlerPubXMLMonitor: !Ref LMFunctionHandlerPubXMLMonitor
69 | ResourceType: prod
70 | Tags:
71 | - Key: ServiceName
72 | Value: !Ref ServiceName
73 | - Key: StackName
74 | Value: !Ref AWS::StackName
75 |
76 | # Deploys the alarms used for the PSGalleryExplorer project
77 | PSGESSM:
78 | Type: AWS::CloudFormation::Stack
79 | DeletionPolicy: Delete
80 | UpdateReplacePolicy: Delete
81 | Properties:
82 | TemplateURL: !Sub
83 | - 'https://${ArtifactS3Bucket}.s3.amazonaws.com/${ArtifactS3KeyPrefix}/${FileName}'
84 | - #AWSRegion: !Ref "AWS::Region"
85 | ArtifactS3Bucket: !Ref ArtifactS3Bucket
86 | ArtifactS3KeyPrefix: !Ref ArtifactS3KeyPrefix
87 | FileName: CloudFormation/PSGalleryExplorer/ChildTemplates/PSGESSM.yml
88 | TimeoutInMinutes: 15 #make sure it can actually complete in this time period
89 | Parameters: #much match the parameters of nested template
90 | ServiceName: !Ref ServiceName
91 | ResourceType: prod
92 | Tags:
93 | - Key: ServiceName
94 | Value: !Ref ServiceName
95 | - Key: StackName
96 | Value: !Ref AWS::StackName
97 |
--------------------------------------------------------------------------------
/CodeBuild/IntegrationTest/New-IntegrationInfrastructure.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | This stands up any required infrastructure before the Pester integration tests run.
3 | It is invoked in the "pre_build" phase of CodeBuild.
4 | #>
5 |
6 | # $env:AWSAccountId = the AWS Account hosting the MOF Maker stack we're testing
7 | # $env:CODEBUILD_RESOLVED_SOURCE_VERSION = the CodeCommit Commit Id
8 |
9 | #$ErrorActionPreference = 'Stop'
10 | #Import-Module -Name 'AWSPowerShell.NetCore'
11 |
--------------------------------------------------------------------------------
/CodeBuild/IntegrationTest/Remove-IntegrationInfrastructure.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | This removes any required infrastructure after the Pester integration tests run.
3 | It is invoked whether the build succeeds or fails, and is invoked in the
4 | "post_build" phase of CodeBuild.
5 | #>
6 |
7 | # $env:AWSAccountId = the AWS Account hosting the MOF Maker stack we're testing
8 | # $env:CODEBUILD_RESOLVED_SOURCE_VERSION = the CodeCommit Commit Id
9 |
10 | #$ErrorActionPreference = 'Stop'
11 | #Import-Module -Name 'AWSPowerShell.NetCore'
12 |
--------------------------------------------------------------------------------
/CodeBuild/IntegrationTest/Tests/Integration.Tests.ps1:
--------------------------------------------------------------------------------
1 | # $env:ARTIFACT_S3_BUCKET = the artifact bucket used by CB
2 | # $env:AWSAccountId = the AWS Account hosting the service under test
3 | # $env:AWSRegion = the AWS Region hosting the service under test
4 | # $env:projectName = name of the project
5 |
6 | Describe -Name 'Infrastructure Tests' -Fixture {
7 | BeforeAll {
8 | try {
9 | $cfnExports = Get-CFNExport -ErrorAction Stop
10 | }
11 | catch {
12 | throw
13 | }
14 | $script:ServiceName = $env:projectName
15 | } #before_all
16 |
17 | Context -Name 'PSGES3Buckets.yml' {
18 |
19 | It 'Created the S3 buckets needed for the project' -Test {
20 | $assertion1 = ($cfnExports | Where-Object { $_.Name -eq 'StageTriggerBN' }).Value
21 | $expected = 'psge-*'
22 | $assertion1 | Should -BeLike $expected
23 | $assertion2 = ($cfnExports | Where-Object { $_.Name -eq 'GitXMLDataBN' }).Value
24 | $expected = 'psge-*'
25 | $assertion2 | Should -BeLike $expected
26 | $assertion4 = ($cfnExports | Where-Object { $_.Name -eq 'PubXMLDataBN' }).Value
27 | $expected = 'psge-*'
28 | $assertion4 | Should -BeLike $expected
29 | $logEval = ($cfnExports | Where-Object { $_.Name -eq 'PSGECloudFrontLogBucketBN' }).Value
30 | $logEval | Should -Not -BeNullOrEmpty
31 | } #it
32 |
33 | It 'Should create a SNS topic for S3 trigger updates' -Test {
34 | $assertion = ($cfnExports | Where-Object { $_.Name -eq 'UpdateSNSTopicArn' }).Value
35 | $expected = 'arn:aws:sns:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
36 | $assertion | Should -BeLike $expected
37 | } #it
38 |
39 | It -Name 'Should create a CloudFront distribution' -Test {
40 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-PSGECloudFrontDistributionDomain" }).Value
41 | $expected = '*.cloudfront.net'
42 | $assertion | Should -BeLike $expected
43 | } #it
44 |
45 | } #context_PSGES3Buckets
46 |
47 | Context -Name 'PSGE.yml' {
48 |
49 | It -Name 'Should create a GitHubDataDlqArn' -Test {
50 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubDataDlqARN" }).Value
51 | $expected = 'arn:aws:sqs:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
52 | $assertion | Should -BeLike $expected
53 | } #it
54 |
55 | It -Name 'Should create a GitHubDataQueueArn' -Test {
56 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubDataQueueARN" }).Value
57 | $expected = 'arn:aws:sqs:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
58 | $assertion | Should -BeLike $expected
59 | } #it
60 |
61 | It -Name 'Should create a GitLabDataDlqARN' -Test {
62 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabDataDlqARN" }).Value
63 | $expected = 'arn:aws:sqs:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
64 | $assertion | Should -BeLike $expected
65 | } #it
66 |
67 | It -Name 'Should create a GitLabDataQueueARN' -Test {
68 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabDataQueueARN" }).Value
69 | $expected = 'arn:aws:sqs:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
70 | $assertion | Should -BeLike $expected
71 | } #it
72 |
73 | It -Name 'Should create a UpdatePubXMLDataQueueARN' -Test {
74 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-UpdatePubXMLDataQueueARN" }).Value
75 | $expected = 'arn:aws:sqs:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
76 | $assertion | Should -BeLike $expected
77 | } #it
78 |
79 | It -Name 'Should create a GitHubScannerSMDelayStateMachineARN' -Test {
80 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubScannerSMDelayStateMachineARN" }).Value
81 | $expected = 'arn:aws:states:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
82 | $assertion | Should -BeLike $expected
83 | } #it
84 |
85 | It -Name 'Should create a GitLabScannerSMDelayStateMachineArn' -Test {
86 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabScannerSMDelayStateMachineArn" }).Value
87 | $expected = 'arn:aws:states:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
88 | $assertion | Should -BeLike $expected
89 | } #it
90 |
91 | It -Name 'Should create a GSScheduledRuleARN' -Test {
92 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GSScheduledRuleARN" }).Value
93 | $expected = 'arn:aws:events:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
94 | $assertion | Should -BeLike $expected
95 | } #it
96 |
97 | It -Name 'Should create a PubXMLPopulatorARN' -Test {
98 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-PubXMLPopulatorARN" }).Value
99 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
100 | $assertion | Should -BeLike $expected
101 | } #it
102 |
103 | It -Name 'Should create a GalleryScannerARN' -Test {
104 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GalleryScannerARN" }).Value
105 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
106 | $assertion | Should -BeLike $expected
107 | } #it
108 |
109 | It -Name 'Should create a GitHubScannerARN' -Test {
110 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubScannerARN" }).Value
111 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
112 | $assertion | Should -BeLike $expected
113 | } #it
114 |
115 | It -Name 'Should create a GitHubSMScannerARN' -Test {
116 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubSMScannerARN" }).Value
117 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
118 | $assertion | Should -BeLike $expected
119 | } #it
120 |
121 | It -Name 'Should create a GitLabScannerARN' -Test {
122 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabScannerARN" }).Value
123 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
124 | $assertion | Should -BeLike $expected
125 | } #it
126 |
127 | It -Name 'Should create a GitLabSMScannerARN' -Test {
128 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabSMScannerARN" }).Value
129 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
130 | $assertion | Should -BeLike $expected
131 | } #it
132 |
133 | It -Name 'Should create a GCombineArn' -Test {
134 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GCombineArn" }).Value
135 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
136 | $assertion | Should -BeLike $expected
137 | } #it
138 |
139 | } #context_PSGE
140 |
141 | Context -Name 'PSGEAlarms.yml' {
142 |
143 | It -Name 'Should create a GitHubSMFailureAlarmARN' -Test {
144 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubSMFailureAlarmARN" }).Value
145 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
146 | $assertion | Should -BeLike $expected
147 | } #it
148 |
149 | It -Name 'Should create a GitHubSMThrottleAlarmARN' -Test {
150 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubSMThrottleAlarmARN" }).Value
151 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
152 | $assertion | Should -BeLike $expected
153 | } #it
154 |
155 | It -Name 'Should create a GitHubSMTimedOutAlarmARN' -Test {
156 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitHubSMTimedOutAlarmARN" }).Value
157 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
158 | $assertion | Should -BeLike $expected
159 | } #it
160 |
161 | It -Name 'Should create a GitLabSMThrottleAlarmARN' -Test {
162 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabSMThrottleAlarmARN" }).Value
163 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
164 | $assertion | Should -BeLike $expected
165 | } #it
166 |
167 | It -Name 'Should create a GitLabSMTimedOutAlarmARN' -Test {
168 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-GitLabSMTimedOutAlarmARN" }).Value
169 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
170 | $assertion | Should -BeLike $expected
171 | } #it
172 |
173 | It -Name 'Should create a PubXMLMonitorAlarmARN' -Test {
174 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-PubXMLMonitorAlarmARN" }).Value
175 | $expected = 'arn:aws:cloudwatch:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
176 | $assertion | Should -BeLike $expected
177 | } #it
178 |
179 | It -Name 'Should create a PubXMLMonitorARN' -Test {
180 | $assertion = ($cfnExports | Where-Object { $_.Name -eq "$ServiceName-PubXMLMonitorARN" }).Value
181 | $expected = 'arn:aws:lambda:{0}:{1}:*' -f $env:AWSRegion, $env:AWSAccountId
182 | $assertion | Should -BeLike $expected
183 | } #it
184 |
185 | } #context_PSGEAlarms
186 |
187 | } #describe_infra_tests
188 |
--------------------------------------------------------------------------------
/CodeBuild/IntegrationTest/buildspec.yml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 |
3 | phases:
4 | install:
5 | runtime-versions:
6 | dotnet: 6.0
7 | commands:
8 | - echo Configure AWS defaults using the configuration script added to the Docker Image.
9 | - pwsh -command './CodeBuild/configure_aws_credential.ps1'
10 | - echo Installing PowerShell Modules from S3
11 | - pwsh -command './CodeBuild/install_modules.ps1'
12 | pre_build:
13 | commands:
14 | - pwsh -command '$PSVersionTable'
15 | - pwsh -command 'Get-ChildItem env:'
16 | - echo Pre-Build started on `date`
17 | - pwsh -command '& ./CodeBuild/IntegrationTest/New-IntegrationInfrastructure.ps1'
18 | build:
19 | commands:
20 | - pwsh -command '
21 | Import-Module Pester;
22 | $pesterConfiguration = [PesterConfiguration]::new();
23 | $pesterConfiguration.Run.Exit = $true;
24 | $pesterConfiguration.Run.Path = "./CodeBuild/IntegrationTest/Tests";
25 | $pesterConfiguration.Output.Verbosity = "Detailed";
26 | Invoke-Pester -Configuration $pesterConfiguration'
27 | finally:
28 | - pwsh -command '& ./CodeBuild/IntegrationTest/Remove-IntegrationInfrastructure.ps1'
29 |
--------------------------------------------------------------------------------
/CodeBuild/UnitTestAndBuild/Publish-CFNTemplatesToS3.ps1:
--------------------------------------------------------------------------------
1 | $ErrorActionPreference = 'Stop'
2 | $ProgressPreference = 'SilentlyContinue'
3 |
4 | if ([String]::IsNullOrWhiteSpace($env:ARTIFACT_S3_BUCKET)) {
5 | throw 'The environment variable ARTIFACT_S3_BUCKET must be configured.'
6 | }
7 |
8 | if ([String]::IsNullOrWhiteSpace($env:S3_KEY_PREFIX)) {
9 | throw 'The environment variable S3_KEY_PREFIX must be configured.'
10 | }
11 |
12 | # Paths are based from the root of the GIT repository
13 | $paths = @(
14 | './CloudFormation'
15 | )
16 |
17 | if ($env:REGIONAL_BUCKET) {
18 | $artifactBucket = $env:REGIONAL_BUCKET
19 | }
20 | else {
21 | $artifactBucket = $env:ARTIFACT_S3_BUCKET
22 | }
23 |
24 | foreach ($path in $paths) {
25 | Write-Host ('Processing CloudFormation Templates in {0}' -f $path)
26 | # All CloudFormation Templates to publish are located in or below the "./CloudFormation" folder
27 | foreach ($file in (Get-ChildItem -Path $path -Recurse -File -Filter "*.yml")) {
28 |
29 | '' # Blank line to separate CodeBuild Output
30 |
31 | # Calculate the S3 Key Prefix, keeping the correct Folder Structure
32 | if ($file.Name -like '*-ControlPlane.yml') {
33 | $s3KeyPrefix = '{0}/CloudFormation/{1}' -f $env:S3_KEY_PREFIX, $file.Directory.Name
34 | }
35 | elseif ($file.Directory.Name -eq 'ChildTemplates') {
36 | # Find the parent template path
37 | $parentPath = Split-Path -Path $file.Directory
38 | $templatePath = Split-Path -Path $parentPath -Leaf
39 | $s3KeyPrefix = '{0}/CloudFormation/{1}/{2}' -f $env:S3_KEY_PREFIX, $templatePath, $file.Directory.Name
40 | }
41 | elseif ($file.Directory.Name -eq 'Manual') {
42 | Write-Host 'Manually deployed CFN detected. Skipping.'
43 | continue
44 | }
45 | else {
46 | throw 'Unexpected directory encountered inside CloudFormation folder'
47 | }
48 |
49 | $s3Key = '{0}/{1}' -f $s3KeyPrefix, $file.Name
50 | [string]$endPoint = "https://s3.$env:AWSRegion" + ".amazonaws.com"
51 |
52 | Write-Host ('ENDPOINT: {0}' -f $endPoint)
53 | Write-Host ('BUCKET: {0}' -f $artifactBucket)
54 | Write-Host ('KEY: {0}' -f $s3Key)
55 | $writeS3ObjectSplat = @{
56 | BucketName = $artifactBucket
57 | Key = $s3Key
58 | File = $file.FullName
59 | Region = $env:AWSRegion
60 | EndpointUrl = $endPoint
61 | }
62 | Write-S3Object @writeS3ObjectSplat
63 |
64 | Remove-Variable -Name @('s3Key', 's3KeyPrefix') -ErrorAction SilentlyContinue
65 | }
66 | }
67 | # Update the ControlPlane Parameters JSON files with the target Artifact S3 Bucket.
68 | # All JSON files will be updated, however the deployment CodePipeline is hard coded
69 | # to a specific JSON file so other deployments will not be affected.
70 | foreach ($controlPlaneFolder in (Get-ChildItem -Path './CloudFormation' -Recurse -Filter '*ControlPlane-Parameters' -Directory)) {
71 | foreach ($file in (Get-ChildItem -Path $controlPlaneFolder.FullName -Filter '*.json' -Recurse)) {
72 | $fileContent = Get-Content -Path $file.FullName -Raw | ConvertFrom-Json
73 |
74 | $fileContent.Parameters.ArtifactS3Bucket = $artifactBucket
75 |
76 | $fileContent.Parameters.ArtifactS3KeyPrefix = $env:S3_KEY_PREFIX
77 |
78 | $fileContent | ConvertTo-Json -Compress -Depth 6 | Out-File -FilePath $file.FullName -Force
79 | }
80 | }
--------------------------------------------------------------------------------
/CodeBuild/UnitTestAndBuild/Validate-CFNTemplates.Tests.ps1:
--------------------------------------------------------------------------------
1 | $paths = @(
2 | 'CloudFormation'
3 | )
4 | $files = Get-ChildItem -Path $paths -Recurse -Filter '*.yml'
5 | $ErrorActionPreference = 'Stop'
6 |
7 | Describe 'CloudFormation Template Validation' {
8 |
9 | Context -Name 'CloudFormation Templates' {
10 | Context -Name '<_.Name>' -Foreach $files {
11 | It 'is valid CFN' {
12 | { Test-CFNTemplate -TemplateBody (Get-Content -Path $_.FullName -Raw) } | Should -Not -Throw
13 | } #it
14 | }
15 | } #context_cfn_templates
16 |
17 | } #describe_cfn_templates
18 |
--------------------------------------------------------------------------------
/CodeBuild/UnitTestAndBuild/Validate-JSONConfigurations.Tests.ps1:
--------------------------------------------------------------------------------
1 | $paths = @(
2 | 'CloudFormation'
3 | )
4 | $files = Get-ChildItem -Path $paths -File -Recurse -Filter '*.json'
5 | $ErrorActionPreference = 'Stop'
6 |
7 | Describe -Name 'JSON Configuration File Validation' {
8 |
9 | Context -Name 'JSON Parameter Files' {
10 | Context -Name '<_.Name>' -Foreach $files {
11 | It 'is valid JSON' {
12 | { $null = ConvertFrom-Json -InputObject (Get-Content -Path $_.FullName -Raw) } | Should -Not -Throw
13 | } #it
14 | }
15 | } #context_json_parameter_files
16 |
17 | } #describe_json_configuration_file_validation
18 |
--------------------------------------------------------------------------------
/CodeBuild/UnitTestAndBuild/buildspec.yml:
--------------------------------------------------------------------------------
1 | version: 0.2
2 |
3 | phases:
4 | install:
5 | runtime-versions:
6 | dotnet: 6.0
7 | # python: 3.8
8 | commands:
9 | # Check PowerShell Version
10 | - pwsh -command '$PSVersionTable'
11 |
12 | # Check available variables in the build
13 | # - pwsh -command 'Get-Variable'
14 |
15 | # Check available environment variables in the build
16 | # - pwsh -command 'Get-ChildItem env:'
17 |
18 | # Configure AWS defaults using the configuration script added to the Docker Image.
19 | - pwsh -command './CodeBuild/configure_aws_credential.ps1'
20 |
21 | # Installing PowerShell Modules from S3/Gallery
22 | - pwsh -command './CodeBuild/install_modules.ps1'
23 |
24 | # Install Python packages
25 | # - pip install pip -U
26 | # - pip install -r ./lambdafunctions/python/requirements.txt
27 |
28 | pre_build:
29 | commands:
30 | # https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script
31 | # - pwsh -command '& ./CodeBuild/UnitTestAndBuild/dotnet-install.ps1 -Channel LTS'
32 | # - ./CodeBuild/UnitTestAndBuild/dotnet-install.sh --channel LTS
33 |
34 | # Validate CloudFormation Templates
35 | - pwsh -command '
36 | Import-Module Pester;
37 | $pesterConfiguration = [PesterConfiguration]::new();
38 | $pesterConfiguration.Run.Exit = $true;
39 | $pesterConfiguration.Run.Path = "./CodeBuild/UnitTestAndBuild/Validate-CFNTemplates.Tests.ps1";
40 | $pesterConfiguration.Output.Verbosity = "Detailed";
41 | Invoke-Pester -Configuration $pesterConfiguration'
42 |
43 | # Validate Json files
44 | - pwsh -command '
45 | Import-Module Pester;
46 | $pesterConfiguration = [PesterConfiguration]::new();
47 | $pesterConfiguration.Run.Exit = $true;
48 | $pesterConfiguration.Run.Path = "./CodeBuild/UnitTestAndBuild/Validate-JSONConfigurations.Tests.ps1";
49 | $pesterConfiguration.Output.Verbosity = "Detailed";
50 | Invoke-Pester -Configuration $pesterConfiguration'
51 |
52 | build:
53 | commands:
54 |
55 | # Publish CloudFormation templates to S3
56 | - pwsh -command 'Import-Module -Name "AWS.Tools.Common";Import-Module -Name "AWS.Tools.S3"; & ./CodeBuild/UnitTestAndBuild/Publish-CFNTemplatesToS3.ps1'
57 |
58 | # Running Invoke-Build against each PowerShell AWS Lambda Function
59 | - pwsh -command 'Get-ChildItem -Path './lambdafunctions/PowerShell' -Filter '*.build.ps1' -File -Recurse | ForEach-Object {Invoke-Build -File $_.FullName}'
60 |
61 | artifacts:
62 | files:
63 | - CloudFormation/**/*
64 | - CodeBuild/**/*
65 |
--------------------------------------------------------------------------------
/CodeBuild/configure_aws_credential.ps1:
--------------------------------------------------------------------------------
1 | 'Configuring AWS credentials'
2 |
3 | ' - Retrieving temporary credentials from metadata'
4 | $uri = 'http://169.254.170.2{0}' -f $env:AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
5 | $sts = Invoke-RestMethod -UseBasicParsing -Uri $uri
6 |
7 | ' - Setting default AWS Credential'
8 | $credentialsFile = '~/.aws/credentials'
9 | $null = New-Item -Path $credentialsFile -Force
10 |
11 | '[default]' | Out-File -FilePath $credentialsFile -Append
12 | 'aws_access_key_id={0}' -f $sts.AccessKeyId | Out-File -FilePath $credentialsFile -Append
13 | 'aws_secret_access_key={0}' -f $sts.SecretAccessKey | Out-File -FilePath $credentialsFile -Append
14 | 'aws_session_token={0}' -f $sts.Token | Out-File -FilePath $credentialsFile -Append
15 |
16 | ' - Setting default AWS Region'
17 | $null = New-Item -Path $profile -Force
18 | '$StoredAWSRegion = "{0}"' -f $env:AWS_DEFAULT_REGION | Out-File -FilePath $profile -Force
19 |
20 | ' - AWS credentials configured'
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Jake Morrison
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # PSGalleryExplorer
2 |
3 | [](https://github.com/PowerShell/PowerShell) [![PowerShell Gallery][psgallery-img]][psgallery-site]  [![License][license-badge]](LICENSE) [](https://psgalleryexplorer.readthedocs.io/en/latest/?badge=latest)
4 |
5 | [psgallery-img]: https://img.shields.io/powershellgallery/dt/PSGalleryExplorer?label=Powershell%20Gallery&logo=powershell
6 | [psgallery-site]: https://www.powershellgallery.com/packages/PSGalleryExplorer
7 | [psgallery-v1]: https://www.powershellgallery.com/packages/PSGalleryExplorer/0.8.0
8 | [license-badge]: https://img.shields.io/github/license/techthoughts2/PSGalleryExplorer
9 |
10 |
11 |
12 |
13 |
14 | Branch | Windows | Windows pwsh | MacOS | Linux
15 | --- | --- | --- | --- | --- |
16 | main |  |  | [](https://ci.appveyor.com/project/techthoughts2/psgalleryexplorer/branch/main) |  |
17 | Enhancements |  |  | [](https://ci.appveyor.com/project/techthoughts2/psgalleryexplorer/branch/Enhancements)|  |
18 |
19 | ## Synopsis
20 |
21 | PSGalleryExplorer is a PowerShell module that extends the search functionality of the PowerShell Gallery by providing additional project information about modules. This enables you to search, explore, and discover PowerShell Gallery modules based on additional criteria.
22 |
23 | 
24 |
25 | ## Description
26 |
27 | PSGalleryExplorer is a PowerShell module that extends the search functionality of the PowerShell Gallery by providing additional project information about modules. It enables users to search, explore, and discover PowerShell Gallery modules based on additional criteria that are not available via `Find-Module`. The module provides various features such as filtering results based on download counts, stars, forks, and repository health metrics like open issues, license, and last updated date. With PSGalleryExplorer, users can easily identify trending and actively developed modules, and explore module repositories directly from the console.
28 |
29 | With `Find-ModuleByCommand`, PSGalleryExplorer now provides even more value to users by enabling them to quickly locate modules that contain specific commands. This enables you to search for modules by function name, even if you do not have the module locally installed.
30 |
31 | ### Features
32 |
33 | - Fully cross-platform and can be run on Windows, Linux, and macOS
34 | - Discover modules based on various criteria such as number of downloads, stars, forks, and more
35 | - Get insights into the community health of a module's repository, including information about open issues, license, and last updated date
36 | - Identify modules that are actively being developed by filtering based on their most recent repository update date.
37 | - Compliments existing tools like `Find-Module` to provide another way to explore modules on the PowerShell Gallery.
38 | - Identify up-and-coming or trending modules by comparing search results including and excluding popular and corporate modules
39 | - PSGalleryExplorer provides a detailed, informative output of module results to help you quickly identify prime candidates for further exploration.
40 | - `Find-ModuleByCommand` allows users to search for modules based on a specific command name, even if the module is not installed locally, providing a quick and easy way to locate modules containing the desired functionality.
41 |
42 | ## Getting Started
43 |
44 | ### Documentation
45 |
46 | Documentation for PSGalleryExplorer is available at: [https://psgalleryexplorer.readthedocs.io](https://psgalleryexplorer.readthedocs.io)
47 |
48 | ### Installation
49 |
50 | ```powershell
51 | # Install PSGalleryExplorer from the PowerShell Gallery
52 | Install-Module -Name "PSGalleryExplorer" -Repository PSGallery -Scope CurrentUser
53 | ```
54 |
55 | ### Quick start
56 |
57 | ```powershell
58 | #------------------------------------------------------------------------------------------------
59 | # import the PSGalleryExplorer module
60 | Import-Module -Name "PSGalleryExplorer"
61 | #------------------------------------------------------------------------------------------------
62 | # discover module info by tag
63 | Find-PSGModule -ByTag Telegram
64 | #------------------------------------------------------------------------------------------------
65 | # discover PowerShell modules by # of Gallery Downloads
66 | Find-PSGModule -ByDownloads
67 | #------------------------------------------------------------------------------------------------
68 | # discover the most recently updated modules on repo
69 | Find-PSGModule -ByRecentUpdate RepoUpdate
70 | #------------------------------------------------------------------------------------------------
71 | # discover the most recently updated modules on the PowerShell Gallery
72 | Find-PSGModule -ByRecentUpdate GalleryUpdate
73 | #------------------------------------------------------------------------------------------------
74 | # discover PowerShell modules by # of Gallery Downloads
75 | # include corporate modules and common/popular modules in results
76 | # return top 50
77 | Find-PSGModule -ByDownloads -IncludeCorps -IncludeRegulars -NumberToReturn 50
78 | #------------------------------------------------------------------------------------------------
79 | # discover PowerShell modules by # of repo project stars
80 | Find-PSGModule -ByRepoInfo StarCount
81 | #------------------------------------------------------------------------------------------------
82 | # discover PowerShell modules that could possibly use some help
83 | Find-PSGModule -ByRepoInfo Issues
84 | #------------------------------------------------------------------------------------------------
85 | # discover PowerShell modules by # of repo project subscribers
86 | Find-PSGModule -ByRepoInfo Subscribers
87 | #------------------------------------------------------------------------------------------------
88 | # discover a set of random modules
89 | Find-PSGModule -ByRandom
90 | #------------------------------------------------------------------------------------------------
91 | # discover module info by name
92 | Find-PSGModule -ByName 'PoshGram'
93 | #------------------------------------------------------------------------------------------------
94 | # Returns a list of modules that contain the command Send-TelegramTextMessage
95 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage'
96 | #------------------------------------------------------------------------------------------------
97 | ```
98 |
99 | ## Notes
100 |
101 | This PowerShell project was created with [Catesta](https://github.com/techthoughts2/Catesta).
102 |
103 | ## Contributing
104 |
105 | If you'd like to contribute to PSGalleryExplorer, please see the [contribution guidelines](.github/CONTRIBUTING.md).
106 |
107 | ## License
108 |
109 | This project is [licensed under the MIT License](LICENSE).
110 |
--------------------------------------------------------------------------------
/actions_bootstrap.ps1:
--------------------------------------------------------------------------------
1 | # Bootstrap dependencies
2 |
3 | # https://docs.microsoft.com/powershell/module/packagemanagement/get-packageprovider
4 | Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null
5 |
6 | # https://docs.microsoft.com/powershell/module/powershellget/set-psrepository
7 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
8 |
9 | # List of PowerShell Modules required for the build
10 | $modulesToInstall = [System.Collections.ArrayList]::new()
11 | # https://github.com/pester/Pester
12 | $null = $modulesToInstall.Add(([PSCustomObject]@{
13 | ModuleName = 'Pester'
14 | ModuleVersion = '5.4.0'
15 | }))
16 | # https://github.com/nightroman/Invoke-Build
17 | $null = $modulesToInstall.Add(([PSCustomObject]@{
18 | ModuleName = 'InvokeBuild'
19 | ModuleVersion = '5.10.3'
20 | }))
21 | # https://github.com/PowerShell/PSScriptAnalyzer
22 | $null = $modulesToInstall.Add(([PSCustomObject]@{
23 | ModuleName = 'PSScriptAnalyzer'
24 | ModuleVersion = '1.21.0'
25 | }))
26 | # https://github.com/PowerShell/platyPS
27 | # older version used due to: https://github.com/PowerShell/platyPS/issues/457
28 | $null = $modulesToInstall.Add(([PSCustomObject]@{
29 | ModuleName = 'platyPS'
30 | ModuleVersion = '0.12.0'
31 | }))
32 | $null = $modulesToInstall.Add(([PSCustomObject]@{
33 | ModuleName = 'Convert'
34 | ModuleVersion = '1.5.0'
35 | }))
36 |
37 | 'Installing PowerShell Modules'
38 | foreach ($module in $modulesToInstall) {
39 | $installSplat = @{
40 | Name = $module.ModuleName
41 | RequiredVersion = $module.ModuleVersion
42 | Repository = 'PSGallery'
43 | Force = $true
44 | ErrorAction = 'Stop'
45 | }
46 | try {
47 | Install-Module @installSplat
48 | Import-Module -Name $module.ModuleName -ErrorAction Stop
49 | ' - Successfully installed {0}' -f $module.ModuleName
50 | }
51 | catch {
52 | $message = 'Failed to install {0}' -f $module.ModuleName
53 | " - $message"
54 | throw $message
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.0.{build}
2 |
3 | # https://www.appveyor.com/docs/build-configuration/
4 | # https://www.appveyor.com/docs/build-configuration/#specializing-matrix-job-configuration
5 | # https://www.appveyor.com/docs/appveyor-yml/
6 |
7 | branches:
8 | only:
9 | - main
10 | - Enhancements
11 |
12 | # Do not build on tags (GitHub, Bitbucket, GitLab, Gitea)
13 | skip_tags: true
14 |
15 | skip_commits:
16 | files:
17 | - docs/*
18 | - media/*
19 | message: /updated readme.*|update readme.*s/
20 |
21 | image:
22 | - macOS
23 |
24 | init:
25 | - pwsh: $PSVersionTable
26 | # uncomment the line below to explore what modules/variables/env variables are available in the build image
27 | # - pwsh: Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String
28 | install:
29 | - pwsh: . .\actions_bootstrap.ps1
30 | build_script:
31 | - pwsh: Invoke-Build -File .\src\PSGalleryExplorer.build.ps1
32 |
33 | artifacts:
34 | - path: src/Artifacts/testOutput/PesterTests.xml
35 | name: PesterTestResults
36 | - path: src/Artifacts/ccReport/CodeCoverage.xml
37 | name: CodeCoverageResults
38 | - path: src/Archive/*.zip
39 | name: BuildArtifact
40 |
--------------------------------------------------------------------------------
/buildspec_powershell_windows.yml:
--------------------------------------------------------------------------------
1 | # This is a simple CodeBuild build file for PowerShell.
2 | # - pre_build step will ensure the Module Name / Version has not previously been built for production (plans to add this at a later time)
3 | # - build step will perform Clean, ValidateRequirements, Analyze, Test, CreateHelp, Build, Archive
4 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
5 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#runtime-versions-buildspec-file
6 | # https://docs.aws.amazon.com/codebuild/latest/userguide/test-reporting.html
7 |
8 | version: 0.2
9 |
10 | phases:
11 | install:
12 | commands:
13 | - powershell -command 'Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose'
14 | - powershell -command 'Install-Module -Name PowerShellGet -Repository PSGallery -Force'
15 | - powershell -command '.\configure_aws_credential.ps1'
16 | - powershell -command '.\install_modules.ps1'
17 | pre_build:
18 | commands:
19 | # - powershell -command 'New-Item -Path C:\Test -ItemType Directory | Out-Null'
20 | - powershell -command '$PSVersionTable'
21 | # uncomment the line below to explore what modules/variables/env variables are available in the build image
22 | # - powershell -command 'Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String'
23 | build:
24 | commands:
25 | - powershell -command 'Invoke-Build -File .\src\PSGalleryExplorer.build.ps1'
26 | artifacts:
27 | files:
28 | - '**/*'
29 | base-directory: 'src\Archive'
30 | reports:
31 | PesterTestReport:
32 | files:
33 | - '**/*'
34 | file-format: NunitXml
35 | base-directory: 'src\Artifacts\testOutput'
36 | CodeCoverageReport:
37 | files:
38 | - 'src\Artifacts\ccReport\CodeCoverage.xml'
39 | file-format: 'JaCoCoXml'
--------------------------------------------------------------------------------
/buildspec_pwsh_linux.yml:
--------------------------------------------------------------------------------
1 | # This is a simple CodeBuild build file for pwsh.
2 | # - pre_build step will ensure the Module Name / Version has not previously been built for production (plans to add this at a later time)
3 | # - build step will perform Clean, ValidateRequirements, Analyze, Test, CreateHelp, Build, Archive
4 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
5 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#runtime-versions-buildspec-file
6 | # https://docs.aws.amazon.com/codebuild/latest/userguide/test-reporting.html
7 |
8 | version: 0.2
9 |
10 | phases:
11 | install:
12 | runtime-versions:
13 | dotnet: 6.0
14 | commands:
15 | - pwsh -command './configure_aws_credential.ps1'
16 | - pwsh -command './install_modules.ps1'
17 | pre_build:
18 | commands:
19 | # - pwsh -command 'New-Item -Path /Test -ItemType Directory | Out-Null'
20 | - pwsh -command '$PSVersionTable'
21 | # uncomment the line below to explore what modules/variables/env variables are available in the build image
22 | # - pwsh -command 'Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String'
23 | build:
24 | commands:
25 | - pwsh -command 'Invoke-Build -File .\src\PSGalleryExplorer.build.ps1'
26 | artifacts:
27 | files:
28 | - '**/*'
29 | base-directory: 'src/Archive'
30 | reports:
31 | PesterTestReport:
32 | files:
33 | - '**/*'
34 | file-format: NunitXml
35 | base-directory: 'src/Artifacts/testOutput'
36 | CodeCoverageReport:
37 | files:
38 | - 'src/Artifacts/ccReport/CodeCoverage.xml'
39 | file-format: 'JaCoCoXml'
40 |
--------------------------------------------------------------------------------
/buildspec_pwsh_windows.yml:
--------------------------------------------------------------------------------
1 | # This is a simple CodeBuild build file for PowerShell.
2 | # - pre_build step will ensure the Module Name / Version has not previously been built for production (plans to add this at a later time)
3 | # - build step will perform Clean, ValidateRequirements, Analyze, Test, CreateHelp, Build, Archive
4 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
5 | # https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html#runtime-versions-buildspec-file
6 | # https://docs.aws.amazon.com/codebuild/latest/userguide/test-reporting.html
7 |
8 | version: 0.2
9 |
10 | phases:
11 | install:
12 | runtime-versions:
13 | dotnet: 6.0
14 | commands:
15 | - pwsh -command '.\configure_aws_credential.ps1'
16 | - pwsh -command '.\install_modules.ps1'
17 | pre_build:
18 | commands:
19 | - pwsh -command '$PSVersionTable'
20 | # uncomment the line below to explore what modules/variables/env variables are available in the build image
21 | # - pwsh -command 'Get-Module -ListAvailable; (Get-Variable).GetEnumerator() | Sort-Object Name | Out-String; (Get-ChildItem env:*).GetEnumerator() | Sort-Object Name | Out-String'
22 | build:
23 | commands:
24 | - pwsh -command 'Invoke-Build -File .\src\PSGalleryExplorer.build.ps1'
25 | artifacts:
26 | files:
27 | - '**/*'
28 | base-directory: 'src\Archive'
29 | reports:
30 | PesterTestReport:
31 | files:
32 | - '**/*'
33 | file-format: NunitXml
34 | base-directory: 'src\Artifacts\testOutput'
35 | CodeCoverageReport:
36 | files:
37 | - 'src\Artifacts\ccReport\CodeCoverage.xml'
38 | file-format: 'JaCoCoXml'
39 |
--------------------------------------------------------------------------------
/configure_aws_credential.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This script is used in AWS CodeBuild to configure the default AWS Credentials for use by the AWS CLI and the AWS Powershell module.
4 | .DESCRIPTION
5 | By default, the AWS PowerShell Module does not know about looking up an AWS Container's credentials path, so this works around that issue.
6 | .NOTES
7 | This script enables AWSPowerShell cmdlets in your CodeBuild to interact with and access other AWS resources in your account.
8 | #>
9 | 'Configuring AWS credentials'
10 |
11 | ' - Retrieving temporary credentials from metadata'
12 | $uri = 'http://169.254.170.2{0}' -f $env:AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
13 | $sts = Invoke-RestMethod -UseBasicParsing -Uri $uri
14 |
15 | ' - Setting default AWS Credential'
16 | $credentialsFile = "$env:HOME\.aws\credentials"
17 | $null = New-Item -Path $credentialsFile -Force
18 |
19 | '[default]' | Out-File -FilePath $credentialsFile -Append
20 | 'aws_access_key_id={0}' -f $sts.AccessKeyId | Out-File -FilePath $credentialsFile -Append
21 | 'aws_secret_access_key={0}' -f $sts.SecretAccessKey | Out-File -FilePath $credentialsFile -Append
22 | 'aws_session_token={0}' -f $sts.Token | Out-File -FilePath $credentialsFile -Append
23 |
24 | ' - Setting default AWS Region'
25 | 'region={0}' -f $env:AWS_DEFAULT_REGION | Out-File -FilePath $credentialsFile -Append
26 |
27 | ' - AWS credentials configured'
28 |
--------------------------------------------------------------------------------
/docs/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [2.5.4]
9 |
10 | - Module Changes
11 | - Updated links in `psd1` manifest
12 | - Added links to inline help for all functions
13 | - Build Updates
14 | - Adjusted metric dashboard arrangement and sizing + added alarm status
15 | - adjusted appveyor build
16 | - Misc
17 | - Updated CONTRIBUTING guidelines
18 | - Updated `extensions.json` with recommended extensions for working with this repo
19 | - Updated PSGalleryExplorer logo and icons
20 |
21 | ## [2.5.2]
22 |
23 | - Module Changes
24 | - `Confirm-XMLDataSet` now evaluates `LastWriteTime` instead of `CreationTime` to determine cache freshness requirements
25 | - Added additional corps to list
26 | - Build Updates
27 | - AWS Deployment Updates
28 | - Updated CodeBuild containers from `aws/codebuild/standard:6.0` to `aws/codebuild/standard:7.0`
29 | - Changed alarm for cache data to reference correct SNS topic for alerts
30 | - Added CloudWatch dashboard for data cache age metric
31 | - Misc
32 | - Added metric dashboards to docs section
33 |
34 | ## [2.5.0]
35 |
36 | - Module Updates
37 | - Added support for usage of a metadata file to better determine if data is current
38 | - Added `Confirm-MetadataUpdate` private function
39 | - Updated logic in `Confirm-XMLDataSet` and `Invoke-XMLDataCheck`
40 | - Removed private function `Get-XMLDataSet` for new private function `Get-RemoteFile`
41 | - Convert `1.5.0` or higher now required
42 | - Added the `InsightView` parameter to both `Find-ModuleByCommand` and `Find-PSGModule`
43 | - This provides a new results view that focuses on community insights
44 | - Build Updates
45 | - SSM Task now copies metadata file
46 | - InvokeBuild bumped from `5.10.2` to `5.10.3`
47 | - Convert bumped from `1.2.0` to `1.5.0`
48 | - Removed all test case uses of `Assert-MockCalled`
49 | - Improved test formatting
50 | - Updated test example references
51 | - Added additional integration tests for new properties
52 |
53 | ## [2.1.0]
54 |
55 | - Module Updates
56 | - New function: `Find-ModuleByCommand`
57 |
58 | ## [2.0.0] - *Breaking Changes Introduced*
59 |
60 | - Module Updates
61 | - **New CDN Endpoint** - ***Breaking Change***
62 | - PSGalleryExplorer has migrated to a new CDN endpoint for serving repository information. As a result, the old endpoint has been decommissioned.
63 | - *What does this mean?*
64 | - Older versions of PSGalleryExplorer (prior to `v2.0.0`) will no longer be able to fetch module project information due to the new CDN endpoint. If you're using an older version, please upgrade to v2.0.0 or later to continue using PSGalleryExplorer.
65 | - Convert `1.2.0` or higher now required
66 | - Added additional corps to list
67 | - Added additional regulars to list
68 | - Build Updates:
69 | - Moved from a fully serverless PowerShell lambda architecture to a hybrid SSM execution architecture.
70 | - Added integration for Read the Docs
71 | - Moved `CHANGELOG.md` from `.github` directory to `docs` directory
72 | - Updated VSCode `tasks.json`
73 | - Added a `SECURITY.md` file for the project
74 | - All Infra/Infrastructure references changed to Integration
75 | - CI/CD Changes:
76 | - Pester bumped from `5.3.1` to `5.4.0`
77 | - InvokeBuild bumped from `5.9.7` to `5.10.2`
78 | - PSScriptAnalyzer bumped from `1.20.0` to `1.21.0`
79 | - Convert bumped from `0.6.0` to `1.2.0`
80 | - Switched AWS module install to use PSGallery
81 | - Updated CodeBuild Linux image from `aws/codebuild/standard:5.0` to `aws/codebuild/standard:6.0`
82 | - Updated CodeBuild Windows image from `aws/codebuild/windows-base:2019-1.0` to `aws/codebuild/windows-base:2019-2.0`
83 | - Added log retention groups to all CodeBuild projects
84 |
85 | ## [1.0.2]
86 |
87 | - Added additional corps to list
88 | - Added additional regulars to list
89 | - Changed column output for module name from 15 to 20 characters
90 |
91 | ## [1.0.0]
92 |
93 | - Module Updates
94 | - Module manifest
95 | - Added additional tags
96 | - Bumped Convert requirement to `0.6.0`
97 | - Separated Pester unit tests into separate test folders
98 | - Added support for Pester 5
99 | - Minor formatting changes to most functions
100 | - Build Updates:
101 | - Refreshed CodeBuild module build process
102 | - Minor updates to AWS CodeBuild buildspec files
103 | - pwsh_windows updated to utilize native pwsh using dotnet 3.1
104 | - refreshed installed modules to latest available versions
105 | - Appveyor MacOS now produces artifacts
106 | - Updated PSGalleryExplorer.build file to align with latest bug fixes
107 | - Updated CodeBuild images to latest available
108 | - Added support for using new main branch instead of master
109 | - Updated CodeBuild image from `aws/codebuild/amazonlinux2-x86_64-standard:3.0` to `aws/codebuild/standard:5.0`
110 | - Added tagging to Lambda log groups
111 | - ***Updated all lambdas from `.NET 3.1` to `.NET 6`***
112 | - Bumped all PowerShell module versions to latest version
113 | - Added Pester 5 support
114 | - XML file generation is now sent to cloudfront
115 | - Added cloudfront logging
116 | - Added additional monitoring and alarms
117 | - Minor updates to VSCode settings/tasks/extension files
118 |
119 | ## [0.8.7]
120 |
121 | - Added support for including wildcards in ByName `Find-PSGModule -ByName Posh*`
122 | - Added support for returning all modules `Find-PSGModule`
123 |
124 | ## [0.8.5]
125 |
126 | - Module Updates:
127 | - **Support has been added to include information for projects hosted on GitLab**
128 | - Additional support for other repo locations is planned. As such several references in this module to GitHub have been replaced with Repo or repository.
129 | - **ByGitHubInfo parameter has been replaced with ByRepoInfo parameter**
130 | - **ByRecentUpdate parameter options have changed**
131 | - Previous: GalleryUpdate, GitUpdate
132 | - New: GalleryUpdate, RepoUpdate
133 | - **Repository issues is now a returned parameter in all queries**
134 | - **ByRepoInfo** now has a new parameter choice set:
135 | - StarCount, Forks, Issues, Subscribers
136 | - Added additional corps to corp list
137 | - Minor formatting changes to psd1 manifest
138 | - ByName selection now always includes all modules
139 | - The default output has been adjusted:
140 | - Previous: Name, Downloads, GitStar, GitFork, GitSub, GitWatch, Description
141 | - New: Name, Downloads, Star, Fork, Issues, Sub, Description
142 | - All data parameters are still available in the complete object return
143 | - Build Updates:
144 | - Added CodePipeline capability to deploy Serverless PSGallery solution through code
145 | - PSGallery lambda changes:
146 | - Updated to latest versions of used modules
147 | - A few bug fixes for not being able to properly craft URI
148 | - Added GitLab query capability
149 | - Added env variables to comments section
150 | - Refreshed CodeBuild module build process
151 | - Added test reporting capability
152 | - Updated linux CB to latest image and dotnet 3.1
153 | - Updated windows images to Server 2019
154 | - pwsh core build now uses PowerShell 7.0.3 instead of 7.0.0
155 | - refreshed installed modules to latest available versions
156 |
157 | ## [3/13/2020]
158 |
159 | No Version Change
160 |
161 | - Build/dev improvements
162 | - Bumped module versions to latest available
163 | - Switched Windows Build container to use PowerShell 7 instead of PowerShell 7 preview
164 | - Updated tasks.json to have better integration with InvokeBuild
165 |
166 | ## [0.8.0]
167 |
168 | ### Added
169 |
170 | - Initial release.
171 |
--------------------------------------------------------------------------------
/docs/Find-ModuleByCommand.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: PSGalleryExplorer-help.xml
3 | Module Name: PSGalleryExplorer
4 | online version: https://psgalleryexplorer.readthedocs.io/en/latest/Find-ModuleByCommand/
5 | schema: 2.0.0
6 | ---
7 |
8 | # Find-ModuleByCommand
9 |
10 | ## SYNOPSIS
11 | Searches for modules that contain a specific command or cmdlet name.
12 |
13 | ## SYNTAX
14 |
15 | ```
16 | Find-ModuleByCommand [-CommandName] [-InsightView] []
17 | ```
18 |
19 | ## DESCRIPTION
20 | The Find-ModuleByCommand cmdlet searches for modules on the PowerShell Gallery that contain a specified command or cmdlet name.
21 | The cmdlet returns a list of modules that include the command or cmdlet, along with key metrics and information about the module.
22 | This cmdlet is useful when you need to quickly find a module that includes a particular command or cmdlet, without having to install or download the module first.
23 |
24 | ## EXAMPLES
25 |
26 | ### EXAMPLE 1
27 | ```
28 | Find-ModuleByCommand -CommandName New-ModuleProject
29 | ```
30 |
31 | Returns a list of modules that contain the command New-ModuleProject
32 |
33 | ### EXAMPLE 2
34 | ```
35 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage'
36 | ```
37 |
38 | Returns a list of modules that contain the command Send-TelegramTextMessage
39 |
40 | ### EXAMPLE 3
41 | ```
42 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage' -InsightView
43 | ```
44 |
45 | Returns a list of modules that contain the command Send-TelegramTextMessage, with focused community insights about the module
46 |
47 | ## PARAMETERS
48 |
49 | ### -CommandName
50 | Specifies the command name to search for
51 |
52 | ```yaml
53 | Type: String
54 | Parameter Sets: (All)
55 | Aliases:
56 |
57 | Required: True
58 | Position: 1
59 | Default value: None
60 | Accept pipeline input: False
61 | Accept wildcard characters: False
62 | ```
63 |
64 | ### -InsightView
65 | Output focuses on additional insights available through PSGalleryExplorer.
66 | This includes the module's size and file count, as well as repository metrics like stars, forks, and last repo update date
67 |
68 | ```yaml
69 | Type: SwitchParameter
70 | Parameter Sets: (All)
71 | Aliases:
72 |
73 | Required: False
74 | Position: Named
75 | Default value: False
76 | Accept pipeline input: False
77 | Accept wildcard characters: False
78 | ```
79 |
80 | ### CommonParameters
81 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
82 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
83 |
84 | ## INPUTS
85 |
86 | ## OUTPUTS
87 |
88 | ### PSGEFormat
89 | ## NOTES
90 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
91 |
92 | ## RELATED LINKS
93 |
94 | [https://psgalleryexplorer.readthedocs.io/en/latest/Find-ModuleByCommand/](https://psgalleryexplorer.readthedocs.io/en/latest/Find-ModuleByCommand/)
95 |
96 |
--------------------------------------------------------------------------------
/docs/Find-PSGModule.md:
--------------------------------------------------------------------------------
1 | ---
2 | external help file: PSGalleryExplorer-help.xml
3 | Module Name: PSGalleryExplorer
4 | online version: https://psgalleryexplorer.readthedocs.io/en/latest/Find-PSGModule/
5 | schema: 2.0.0
6 | ---
7 |
8 | # Find-PSGModule
9 |
10 | ## SYNOPSIS
11 | Finds PowerShell Gallery module(s) that match specified criteria.
12 |
13 | ## SYNTAX
14 |
15 | ### none (Default)
16 | ```
17 | Find-PSGModule [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ] [-InsightView] []
18 | ```
19 |
20 | ### GalleryDownloads
21 | ```
22 | Find-PSGModule [-ByDownloads] [-ByRandom] [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ]
23 | [-InsightView] []
24 | ```
25 |
26 | ### Repo
27 | ```
28 | Find-PSGModule [-ByRepoInfo ] [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ]
29 | [-InsightView] []
30 | ```
31 |
32 | ### Update
33 | ```
34 | Find-PSGModule [-ByRecentUpdate ] [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ]
35 | [-InsightView] []
36 | ```
37 |
38 | ### Names
39 | ```
40 | Find-PSGModule [-ByName ] [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ] [-InsightView]
41 | []
42 | ```
43 |
44 | ### Tags
45 | ```
46 | Find-PSGModule [-ByTag ] [-IncludeCorps] [-IncludeRegulars] [-NumberToReturn ] [-InsightView]
47 | []
48 | ```
49 |
50 | ## DESCRIPTION
51 | Searches PowerShell Gallery for modules and their associated project repositories.
52 | Results are returned based on provided criteria.
53 | By default, more common/popular modules and modules made by corporations are excluded.
54 | This is to aid in discovery of other modules.
55 | Popular modules and corporation modules can be included in results by specifying the necessary parameter switches.
56 | 35 module results are returned by default unless the NumberToReturn parameter is used.
57 |
58 | ## EXAMPLES
59 |
60 | ### EXAMPLE 1
61 | ```
62 | Find-PSGModule -ByDownloads
63 | ```
64 |
65 | Returns up to 35 modules based on number of PowerShell Gallery downloads.
66 |
67 | ### EXAMPLE 2
68 | ```
69 | Find-PSGModule -ByDownloads -IncludeRegulars
70 | ```
71 |
72 | Returns up to 35 modules based on number of PowerShell Gallery downloads including more popular modules.
73 |
74 | ### EXAMPLE 3
75 | ```
76 | Find-PSGModule -ByDownloads -IncludeCorps -IncludeRegulars -NumberToReturn 50
77 | ```
78 |
79 | Returns up to 50 modules based on number of PowerShell Gallery downloads including more popular downloads, and modules made by corporations.
80 |
81 | ### EXAMPLE 4
82 | ```
83 | Find-PSGModule -ByRepoInfo StarCount
84 | ```
85 |
86 | Returns up to 35 modules based on number of stars the project's repository has.
87 |
88 | ### EXAMPLE 5
89 | ```
90 | Find-PSGModule -ByRepoInfo Forks
91 | ```
92 |
93 | Returns up to 35 modules based on number of forks the project's repository has.
94 |
95 | ### EXAMPLE 6
96 | ```
97 | Find-PSGModule -ByRepoInfo Issues
98 | ```
99 |
100 | Returns up to 35 modules based on number of issues the project's repository has.
101 |
102 | ### EXAMPLE 7
103 | ```
104 | Find-PSGModule -ByRepoInfo Subscribers
105 | ```
106 |
107 | Returns up to 35 modules based on number of subscribers the project's repository has.
108 |
109 | ### EXAMPLE 8
110 | ```
111 | Find-PSGModule -ByRecentUpdate GalleryUpdate
112 | ```
113 |
114 | Returns up to 35 modules based on their most recent PowerShell Gallery update.
115 |
116 | ### EXAMPLE 9
117 | ```
118 | Find-PSGModule -ByRecentUpdate RepoUpdate
119 | ```
120 |
121 | Returns up to 35 modules based on recent updates to their associated repository.
122 |
123 | ### EXAMPLE 10
124 | ```
125 | Find-PSGModule -ByRandom
126 | ```
127 |
128 | Returns up to 35 modules randomly
129 |
130 | ### EXAMPLE 11
131 | ```
132 | Find-PSGModule -ByName 'PoshGram'
133 | ```
134 |
135 | Returns module that equals the provided name, if found.
136 |
137 | ### EXAMPLE 12
138 | ```
139 | Find-PSGModule -ByName 'Posh*'
140 | ```
141 |
142 | Returns all modules that match the wild card provided name, if found.
143 |
144 | ### EXAMPLE 13
145 | ```
146 | Find-PSGModule -ByTag Telegram
147 | ```
148 |
149 | Returns up to 35 modules that contain the tag: Telegram.
150 |
151 | ### EXAMPLE 14
152 | ```
153 | Find-PSGModule -ByTag Telegram -IncludeCorps -IncludeRegulars -NumberToReturn 100
154 | ```
155 |
156 | Returns up to 100 modules that contains the tag: Telegram, including more popular modules and modules made by corporations.
157 |
158 | ### EXAMPLE 15
159 | ```
160 | $results = Find-PSGModule -ByRepoInfo Watchers -IncludeCorps -IncludeRegulars -NumberToReturn 40
161 | $results | Format-List
162 | ```
163 |
164 | Returns up to 40 modules based on number of module project repository watchers.
165 | It includes more popular modules as well as modules made by corporations.
166 | A list of results is displayed.
167 |
168 | ### EXAMPLE 16
169 | ```
170 | Find-PSGModule
171 | ```
172 |
173 | Returns all non-corp/non-regular modules
174 |
175 | ### EXAMPLE 17
176 | ```
177 | Find-PSGModule -IncludeCorps -IncludeRegulars
178 | ```
179 |
180 | Returns all modules
181 |
182 | ### EXAMPLE 18
183 | ```
184 | Find-PSGModule -ByTag module -InsightView
185 | ```
186 |
187 | Returns up to 35 modules that contain the tag: module.
188 | The output focuses on additional insights available through PSGalleryExplorer.
189 | This includes the module's size and file count, as well as repository metrics like stars, forks, and last repo update date.
190 |
191 | ## PARAMETERS
192 |
193 | ### -ByDownloads
194 | Find modules by number of PowerShell Gallery Downloads
195 |
196 | ```yaml
197 | Type: SwitchParameter
198 | Parameter Sets: GalleryDownloads
199 | Aliases:
200 |
201 | Required: False
202 | Position: Named
203 | Default value: False
204 | Accept pipeline input: False
205 | Accept wildcard characters: False
206 | ```
207 |
208 | ### -ByRepoInfo
209 | Find modules based on various project repository metrics
210 |
211 | ```yaml
212 | Type: String
213 | Parameter Sets: Repo
214 | Aliases:
215 |
216 | Required: False
217 | Position: Named
218 | Default value: None
219 | Accept pipeline input: False
220 | Accept wildcard characters: False
221 | ```
222 |
223 | ### -ByRecentUpdate
224 | Find modules based on recent updated to PowerShell Gallery or associated repository
225 |
226 | ```yaml
227 | Type: String
228 | Parameter Sets: Update
229 | Aliases:
230 |
231 | Required: False
232 | Position: Named
233 | Default value: None
234 | Accept pipeline input: False
235 | Accept wildcard characters: False
236 | ```
237 |
238 | ### -ByRandom
239 | Find modules randomly from the PowerShell Gallery
240 |
241 | ```yaml
242 | Type: SwitchParameter
243 | Parameter Sets: GalleryDownloads
244 | Aliases:
245 |
246 | Required: False
247 | Position: Named
248 | Default value: False
249 | Accept pipeline input: False
250 | Accept wildcard characters: False
251 | ```
252 |
253 | ### -ByName
254 | Find module by module name
255 |
256 | ```yaml
257 | Type: String
258 | Parameter Sets: Names
259 | Aliases:
260 |
261 | Required: False
262 | Position: Named
263 | Default value: None
264 | Accept pipeline input: False
265 | Accept wildcard characters: False
266 | ```
267 |
268 | ### -ByTag
269 | Find modules by tag
270 |
271 | ```yaml
272 | Type: String
273 | Parameter Sets: Tags
274 | Aliases:
275 |
276 | Required: False
277 | Position: Named
278 | Default value: None
279 | Accept pipeline input: False
280 | Accept wildcard characters: False
281 | ```
282 |
283 | ### -IncludeCorps
284 | Include modules written by corporations in results
285 |
286 | ```yaml
287 | Type: SwitchParameter
288 | Parameter Sets: (All)
289 | Aliases:
290 |
291 | Required: False
292 | Position: Named
293 | Default value: False
294 | Accept pipeline input: False
295 | Accept wildcard characters: False
296 | ```
297 |
298 | ### -IncludeRegulars
299 | Include modules that are well known in results
300 |
301 | ```yaml
302 | Type: SwitchParameter
303 | Parameter Sets: (All)
304 | Aliases:
305 |
306 | Required: False
307 | Position: Named
308 | Default value: False
309 | Accept pipeline input: False
310 | Accept wildcard characters: False
311 | ```
312 |
313 | ### -NumberToReturn
314 | Max number of modules to return
315 |
316 | ```yaml
317 | Type: Int32
318 | Parameter Sets: (All)
319 | Aliases:
320 |
321 | Required: False
322 | Position: Named
323 | Default value: 35
324 | Accept pipeline input: False
325 | Accept wildcard characters: False
326 | ```
327 |
328 | ### -InsightView
329 | Output focuses on additional insights available through PSGalleryExplorer.
330 | This includes the module's size and file count, as well as repository metrics like stars, forks, and last repo update date
331 |
332 | ```yaml
333 | Type: SwitchParameter
334 | Parameter Sets: (All)
335 | Aliases:
336 |
337 | Required: False
338 | Position: Named
339 | Default value: False
340 | Accept pipeline input: False
341 | Accept wildcard characters: False
342 | ```
343 |
344 | ### CommonParameters
345 | This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable.
346 | For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216).
347 |
348 | ## INPUTS
349 |
350 | ## OUTPUTS
351 |
352 | ### PSGEFormat
353 | ## NOTES
354 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
355 |
356 | ## RELATED LINKS
357 |
358 | [https://psgalleryexplorer.readthedocs.io/en/latest/Find-PSGModule/](https://psgalleryexplorer.readthedocs.io/en/latest/Find-PSGModule/)
359 |
360 |
--------------------------------------------------------------------------------
/docs/PSGalleryExplorer-Data_Collection.md:
--------------------------------------------------------------------------------
1 | # PSGalleryExplorer - Data Component
2 |
3 | ## Overview
4 |
5 | One key feature of PSGalleryExplorer is the inclusion of associated repository information for each module.
6 |
7 | For several years PSGalleryExplorer leveraged a [PowerShell serverless model](assets/Serverless_PowerShell_DataPull.png) for data collection. However, as the number of modules continued to grow, this was unable to process the data set in a time efficient manner.
8 |
9 | Today, a fully PowerShell hybrid solution is deployed to continually collect and update repository information for PSGalleryExplorer's use.
10 |
11 | ## Deployment Stack
12 |
13 | - [Cloudformation for Serverless deployment](../CloudFormation/PSGalleryExplorer/)
14 |
15 | ## Design Diagram
16 |
17 | 
18 |
19 | ## Outline
20 |
21 | 1. A Hybrid worker configured via [AWS Systems Manager](https://aws.amazon.com/systems-manager/) is configured with a weekly scheduled task.
22 | - This task:
23 | - Downloads all current modules from the PSGallery
24 | - Identifies modules that have public repositories
25 | - Queries [GitHub](https://github.com/), [GitLab](https://gitlab.com), and [Bitbucket](https://bitbucket.org) to retrieve project information
26 | - Combines data sets together to one final data set.
27 | 1. An [AWS Systems Manager Maintenance Window](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-maintenance.html) task is set up to retrieve the data set and publish it to [Amazon CloudFront](https://aws.amazon.com/cloudfront/)
28 | 1. Users of PSGalleryExplorer can quickly download the refreshed data set worldwide when running searches
29 |
30 | You can see additional metric data of data cache age, and cache downloads on the [PSGalleryExplorer Metrics](PSGalleryExplorer-Metrics.md) page.
31 |
--------------------------------------------------------------------------------
/docs/PSGalleryExplorer-FAQ.md:
--------------------------------------------------------------------------------
1 | # PSGalleryExplorer - FAQ
2 |
3 | ## FAQs
4 |
5 | ### How current is the GitHub info that is included with PSGallery Explorer?
6 |
7 | There can be up to a 1 week delay in corresponding PowerShell GitHub project data. This is solely due to cost. The [Serverless PowerShell solution](PowerShell_Serverless.md) in place cost compute time. As such, it's currently set to refresh approximately once per week.
8 |
9 | ### Why are common modules and corporate modules excluded by default?
10 |
11 | By default, PSGalleryExplorer excludes common modules and corporate modules from search results. These modules tend to dominate the metrics by a wide margin, making it challenging to discover new or trending modules. However, it is easy to include these modules in your search results by using the appropriate parameters.
12 |
13 | If you feel like a module should be added/excluded please open an issue for discussion.
14 |
--------------------------------------------------------------------------------
/docs/PSGalleryExplorer-Metrics.md:
--------------------------------------------------------------------------------
1 | # PSGalleryExplorer Metrics
2 |
3 | ## Metric Dashboards
4 |
5 | Up-to-date visualizations representing the age of the data cache and the frequency of download requests.
6 |
7 |
11 |
--------------------------------------------------------------------------------
/docs/PSGalleryExplorer.md:
--------------------------------------------------------------------------------
1 | ---
2 | Module Name: PSGalleryExplorer
3 | Module Guid: e9252e8e-2073-4084-9562-cf60ad84603d
4 | Download Help Link: NA
5 | Help Version: 2.5.4
6 | Locale: en-US
7 | ---
8 |
9 | # PSGalleryExplorer Module
10 | ## Description
11 | Search, explore, and discover PowerShell Gallery modules based on various criteria.
12 |
13 | ## PSGalleryExplorer Cmdlets
14 | ### [Find-ModuleByCommand](Find-ModuleByCommand.md)
15 | Searches for modules that contain a specific command or cmdlet name.
16 |
17 | ### [Find-PSGModule](Find-PSGModule.md)
18 | Finds PowerShell Gallery module(s) that match specified criteria.
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/assets/PSGalleryExplorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/PSGalleryExplorer.png
--------------------------------------------------------------------------------
/docs/assets/PSGalleryExplorerIcon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/PSGalleryExplorerIcon.png
--------------------------------------------------------------------------------
/docs/assets/PSGalleryExplorer_datapull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/PSGalleryExplorer_datapull.png
--------------------------------------------------------------------------------
/docs/assets/PSGalleryExplorer_favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/PSGalleryExplorer_favicon-32x32.png
--------------------------------------------------------------------------------
/docs/assets/Serverless_PowerShell_DataPull.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/Serverless_PowerShell_DataPull.png
--------------------------------------------------------------------------------
/docs/assets/favicon_io/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/favicon_io/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/assets/favicon_io/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/favicon_io/android-chrome-512x512.png
--------------------------------------------------------------------------------
/docs/assets/favicon_io/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/favicon_io/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/assets/favicon_io/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/favicon_io/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/assets/favicon_io/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/favicon_io/favicon.ico
--------------------------------------------------------------------------------
/docs/assets/favicon_io/site.webmanifest:
--------------------------------------------------------------------------------
1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
--------------------------------------------------------------------------------
/docs/assets/psgalleryexplorer.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/docs/assets/psgalleryexplorer.gif
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # PSGalleryExplorer
2 |
3 | [](https://github.com/PowerShell/PowerShell) [![PowerShell Gallery][psgallery-img]][psgallery-site]  [![License][license-badge]](LICENSE) [](https://psgalleryexplorer.readthedocs.io/en/latest/?badge=latest)
4 |
5 | [psgallery-img]: https://img.shields.io/powershellgallery/dt/PSGalleryExplorer?label=Powershell%20Gallery&logo=powershell
6 | [psgallery-site]: https://www.powershellgallery.com/packages/PSGalleryExplorer
7 | [psgallery-v1]: https://www.powershellgallery.com/packages/PSGalleryExplorer/0.8.0
8 | [license-badge]: https://img.shields.io/github/license/techthoughts2/PSGalleryExplorer
9 |
10 |
11 |
12 |
13 |
14 | ## What is PSGalleryExplorer?
15 |
16 | PSGalleryExplorer is a PowerShell module that extends the search functionality of the PowerShell Gallery by providing additional project information about modules. This enables you to search, explore, and discover PowerShell Gallery modules based on additional criteria.
17 |
18 | PSGalleryExplorer is not intended to replace `Find-Module`. Rather, it complements it by providing a means to discover modules and gain insights into their associated project repositories. PSGalleryExplorer enables you to expand your exploration of the PowerShell Gallery, identifying new, trending, and modules with heavy community involvement.
19 |
20 | ## Why PSGalleryExplorer?
21 |
22 | To aid in the discoverability of modules in the PowerShell Gallery.
23 |
24 | The current PowerShell Gallery search options are primarily limited to module name, and tags. CI/CD processes also inflate the download numbers of many modules on the gallery. This makes it challenging to get a sense of new or trending modules, or modules that the community is engaging with.
25 |
26 | This project aims to increase the discoverability of modules on the PowerShell Gallery and encourage module exploration.
27 |
28 | For example, when exploring what is available for adding message functionality, PSGalleryExplorer provides repo statistics on the associated projects (when available), such as star count and issues, giving you a better understanding of the module's community involvement and overall health.
29 |
30 | To further enhance the discoverability of modules, PSGalleryExplorer now includes the `Find-ModuleByCommand` function, which allows users to search for modules based on a specific command, even if the module is not installed locally. This feature provides an additional means to explore modules in the PowerShell Gallery and identify modules that contain specific commands that you may be interested in.
31 |
32 | `Find-Module` Example:
33 |
34 | ```powershell
35 | Find-Module -Tag message
36 |
37 | Version Name Repository Description
38 | ------- ---- ---------- -----------
39 | 1.0.6 PSSlack PSGallery PowerShell module for the Slack API
40 | 2.3.0 PoshGram PSGallery PoshGram provides functionality to send various message t…
41 | 0.3.5 PSRabbitMq PSGallery Send and receive messages using a RabbitMQ server
42 | 1.1.0 Environment PSGallery Provides Trace-Message, and functions for working with En…
43 | 0.6.0 GitUtils PSGallery A set of functions for git tasks
44 | 0.0.1 Send-Message PSGallery Show popup message box on local or remote computers
45 | 0.0.8 PSRyver PSGallery Community PowerShell module for the Ryver API
46 | 1.0.0.0 MessageBox PSGallery Easy to use to create a popup message box
47 | ```
48 |
49 | PSGalleryExplorer Example:
50 |
51 | ```powershell
52 | Find-PSGModule -ByTag message -IncludeCorps -IncludeRegulars
53 |
54 | Name Downloads Star Fork Issues Sub Description
55 | ---- --------- ---- ---- ------ --- -----------
56 | PSSlack 10390604 255 72 41 29 PowerShell module for the Slack API
57 | PoshGram 81268 115 11 4 10 PoshGram provides functionality to send various message types to a specif…
58 | PSRabbitMq 21769 42 28 2 9 Send and receive messages using a RabbitMQ server
59 | Environment 2091 24 2 0 3 Provides Trace-Message, and functions for working with Environment and Pa…
60 | GitUtils 783 A set of functions for git tasks
61 | PSRyver 449 0 0 0 2 Community PowerShell module for the Ryver API
62 | MessageBox 439 Easy to use to create a popup message box
63 | Send-Message 411 Show popup message box on local or remote computers
64 | ```
65 |
66 | ## Getting Started
67 |
68 | ### Installation
69 |
70 | ```powershell
71 | # Install PSGalleryExplorer from the PowerShell Gallery
72 | Install-Module -Name PSGalleryExplorer -Repository PSGallery -Scope CurrentUser
73 | ```
74 |
75 | ### Quick start
76 |
77 | ```powershell
78 | #------------------------------------------------------------------------------------------------
79 | # import the PSGalleryExplorer module
80 | Import-Module -Name "PSGalleryExplorer"
81 | #------------------------------------------------------------------------------------------------
82 | # discover module info by tag
83 | Find-PSGModule -ByTag Telegram
84 | #------------------------------------------------------------------------------------------------
85 | # discover PowerShell modules by # of Gallery Downloads
86 | Find-PSGModule -ByDownloads
87 | #------------------------------------------------------------------------------------------------
88 | # discover the most recently updated modules on repo
89 | Find-PSGModule -ByRecentUpdate RepoUpdate
90 | #------------------------------------------------------------------------------------------------
91 | # discover the most recently updated modules on the PowerShell Gallery
92 | Find-PSGModule -ByRecentUpdate GalleryUpdate
93 | #------------------------------------------------------------------------------------------------
94 | # discover PowerShell modules by # of Gallery Downloads
95 | # include corporate modules and common/popular modules in results
96 | # return top 50
97 | Find-PSGModule -ByDownloads -IncludeCorps -IncludeRegulars -NumberToReturn 50
98 | #------------------------------------------------------------------------------------------------
99 | # discover PowerShell modules by # of repo project stars
100 | Find-PSGModule -ByRepoInfo StarCount
101 | #------------------------------------------------------------------------------------------------
102 | # discover PowerShell modules that could possibly use some help
103 | Find-PSGModule -ByRepoInfo Issues
104 | #------------------------------------------------------------------------------------------------
105 | # discover PowerShell modules by # of repo project subscribers
106 | Find-PSGModule -ByRepoInfo Subscribers
107 | #------------------------------------------------------------------------------------------------
108 | # discover a set of random modules
109 | Find-PSGModule -ByRandom
110 | #------------------------------------------------------------------------------------------------
111 | # discover module info by name
112 | Find-PSGModule -ByName 'PoshGram'
113 | #------------------------------------------------------------------------------------------------
114 | # Returns a list of modules that contain the command Send-TelegramTextMessage
115 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage'
116 | #------------------------------------------------------------------------------------------------
117 | ```
118 |
119 | ## How PSGalleryExplorer Works
120 |
121 | PSGalleryExplorer uses a workflow to collect and serve information about module repositories. It scrapes repository data for modules that have public repositories, then aggregates and includes that data in an easy-to-read format.
122 |
123 | ## Features
124 |
125 | - Fully cross-platform and can be run on Windows, Linux, and macOS
126 | - Discover modules based on various criteria such as number of downloads, stars, forks, and more
127 | - Get insights into the community health of a module's repository, including information about open issues, license, and last updated date
128 | - Identify modules that are actively being developed by filtering based on their most recent repository update date.
129 | - Compliments existing tools like `Find-Module` to provide another way to explore modules on the PowerShell Gallery.
130 | - Identify up-and-coming or trending modules by comparing search results including and excluding popular and corporate modules
131 | - PSGalleryExplorer provides a detailed, informative output of module results to help you quickly identify prime candidates for further exploration.
132 | - `Find-ModuleByCommand` allows users to search for modules based on a specific command name, even if the module is not installed locally, providing a quick and easy way to locate modules containing the desired functionality.
133 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | # https://github.com/readthedocs-examples/example-mkdocs-basic/blob/main/docs/requirements.txt
2 | # requirements.txt
3 | jinja2==3.0.3
4 | mkdocs>=1.4.2
5 | mkdocs-material>=9.0.12 #https://github.com/squidfunk/mkdocs-material
6 | pygments>=2.14.0
7 | # mdx_truly_sane_lists
8 |
--------------------------------------------------------------------------------
/install_modules.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This script is used in AWS CodeBuild to install the required PowerShell Modules for the build process.
4 | .DESCRIPTION
5 | The version of PowerShell being run will be identified. This may vary depending on what type of build
6 | container you are running and if your buildspec is installing various versions of PowerShell. You will
7 | need to specify each module and version that is required for installation. You also need to specify
8 | which version of that module should be installed. Additionally, you will need to specify the S3 bucket
9 | location where that module currently resides, so that it can be downloaded and installed into the build
10 | container at runtime. This necessitates that you download and upload your required modules to S3 prior to
11 | the build being executed.
12 | .EXAMPLE
13 | Save-Module -Name Pester -RequiredVersion 4.4.5 -Path C:\RequiredModules
14 | Create an S3 bucket in your AWS account
15 | Zip the contents of the Pester Module up (when done properly the .psd1 of the module should be at the root of the zip)
16 | Name the ZIP file Pester_4.4.4 (adjust version as needed) unless you want to modify the logic below
17 | Upload the Pester Zip file up to S3 bucket you just created
18 | .NOTES
19 | AWSPowerShell / AWSPowerShell.NetCore module should be included in all CodeBuild projects and is included below
20 | Pester, InvokeBuild, PSScriptAnalyzer, platyPS will typically be required by all module builds
21 | which is why they are included in this build script. Adjust versions as needed.
22 | #>
23 |
24 |
25 | $galleryDownload = $true
26 |
27 | $ErrorActionPreference = 'Stop'
28 | $ProgressPreference = 'SilentlyContinue'
29 | $VerbosePreference = 'SilentlyContinue'
30 |
31 | # List of PowerShell Modules required for the build
32 | # The AWS PowerShell Modules are added below, based on the $PSEdition
33 | $modulesToInstall = [System.Collections.ArrayList]::new()
34 | $null = $modulesToInstall.Add(([PSCustomObject]@{
35 | ModuleName = 'Pester'
36 | ModuleVersion = '5.5.0'
37 | BucketName = 'PSGallery'
38 | KeyPrefix = ''
39 | }))
40 | $null = $modulesToInstall.Add(([PSCustomObject]@{
41 | ModuleName = 'InvokeBuild'
42 | ModuleVersion = '5.10.4'
43 | BucketName = 'PSGallery'
44 | KeyPrefix = ''
45 | }))
46 | $null = $modulesToInstall.Add(([PSCustomObject]@{
47 | ModuleName = 'PSScriptAnalyzer'
48 | ModuleVersion = '1.21.0'
49 | BucketName = 'PSGallery'
50 | KeyPrefix = ''
51 | }))
52 | $null = $modulesToInstall.Add(([PSCustomObject]@{
53 | ModuleName = 'platyPS'
54 | ModuleVersion = '0.12.0'
55 | BucketName = 'PSGallery'
56 | KeyPrefix = ''
57 | }))
58 | $null = $modulesToInstall.Add(([PSCustomObject]@{
59 | ModuleName = 'Convert'
60 | ModuleVersion = '1.5.0'
61 | BucketName = 'PSGallery'
62 | KeyPrefix = ''
63 | }))
64 |
65 | if ($galleryDownload -eq $false) {
66 |
67 | $tempPath = [System.IO.Path]::GetTempPath()
68 |
69 | if ($PSVersionTable.Platform -eq 'Win32NT') {
70 | $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules')
71 | if ($PSEdition -eq 'Core') {
72 | $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'PowerShell', 'Modules')
73 | # Add the AWSPowerShell.NetCore Module
74 | # $null = $modulesToInstall.Add(([PSCustomObject]@{
75 | # ModuleName = 'AWSPowerShell.NetCore'
76 | # ModuleVersion = '3.3.604.0'
77 | # BucketName = 'ps-invoke-modules'
78 | # KeyPrefix = ''
79 | # }))
80 | }
81 | else {
82 | $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules')
83 | # Add the AWSPowerShell Module
84 | # $null = $modulesToInstall.Add(([PSCustomObject]@{
85 | # ModuleName = 'AWSPowerShell'
86 | # ModuleVersion = '3.3.604.0'
87 | # BucketName = 'ps-invoke-modules'
88 | # KeyPrefix = ''
89 | # }))
90 | }
91 | }
92 | elseif ($PSVersionTable.Platform -eq 'Unix') {
93 | $moduleInstallPath = [System.IO.Path]::Combine('/', 'usr', 'local', 'share', 'powershell', 'Modules')
94 |
95 | # Add the AWSPowerShell.NetCore Module
96 | # $null = $modulesToInstall.Add(([PSCustomObject]@{
97 | # ModuleName = 'AWSPowerShell.NetCore'
98 | # ModuleVersion = '3.3.604.0'
99 | # BucketName = 'ps-invoke-modules'
100 | # KeyPrefix = ''
101 | # }))
102 | }
103 | elseif ($PSEdition -eq 'Desktop') {
104 | $moduleInstallPath = [System.IO.Path]::Combine($env:ProgramFiles, 'WindowsPowerShell', 'Modules')
105 | # Add the AWSPowerShell Module
106 | # $null = $modulesToInstall.Add(([PSCustomObject]@{
107 | # ModuleName = 'AWSPowerShell'
108 | # ModuleVersion = '3.3.604.0'
109 | # BucketName = 'ps-invoke-modules'
110 | # KeyPrefix = ''
111 | # }))
112 | }
113 | else {
114 | throw 'Unrecognized OS platform'
115 | }
116 |
117 | 'Installing PowerShell Modules'
118 | foreach ($module in $modulesToInstall) {
119 | ' - {0} {1}' -f $module.ModuleName, $module.ModuleVersion
120 |
121 | # Download file from S3
122 | $key = '{0}_{1}.zip' -f $module.ModuleName, $module.ModuleVersion
123 | $localFile = Join-Path -Path $tempPath -ChildPath $key
124 |
125 | # Download modules from S3 to using the AWS CLI
126 | #note: remove --quiet for more verbose output or if S3 download troubleshooting is needed
127 | $s3Uri = 's3://{0}/{1}{2}' -f $module.BucketName, $module.KeyPrefix, $key
128 | & aws s3 cp $s3Uri $localFile --quiet
129 |
130 | # Ensure the download worked
131 | if (-not(Test-Path -Path $localFile)) {
132 | $message = 'Failed to download {0}' -f $module.ModuleName
133 | " - $message"
134 | throw $message
135 | }
136 |
137 | # Create module path
138 | $modulePath = Join-Path -Path $moduleInstallPath -ChildPath $module.ModuleName
139 | $moduleVersionPath = Join-Path -Path $modulePath -ChildPath $module.ModuleVersion
140 | $null = New-Item -Path $modulePath -ItemType 'Directory' -Force
141 | $null = New-Item -Path $moduleVersionPath -ItemType 'Directory' -Force
142 |
143 | # Expand downloaded file
144 | Expand-Archive -Path $localFile -DestinationPath $moduleVersionPath -Force
145 | }
146 | } #if_GalleryDownload
147 | else {
148 | Get-PackageProvider -Name Nuget -ForceBootstrap | Out-Null
149 | 'Installing PowerShell Modules'
150 | Set-PSRepository -Name 'PSGallery' -InstallationPolicy Trusted
151 | # $NuGetProvider = Get-PackageProvider -Name "NuGet" -ErrorAction SilentlyContinue
152 | # if ( -not $NugetProvider ) {
153 | # Install-PackageProvider -Name "NuGet" -Confirm:$false -Force -Verbose
154 | # }
155 | foreach ($module in $modulesToInstall) {
156 | $installSplat = @{
157 | Name = $module.ModuleName
158 | RequiredVersion = $module.ModuleVersion
159 | Repository = 'PSGallery'
160 | SkipPublisherCheck = $true
161 | Force = $true
162 | ErrorAction = 'Stop'
163 | }
164 | try {
165 | Install-Module @installSplat
166 | Import-Module -Name $module.ModuleName -ErrorAction Stop
167 | ' - Successfully installed {0}' -f $module.ModuleName
168 | }
169 | catch {
170 | $message = 'Failed to install {0}' -f $module.ModuleName
171 | " - $message"
172 | throw
173 | }
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/lambdafunctions/PowerShell/PubXMLMonitor/PubXMLMonitor.build.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | An Invoke-Build Build file for an AWS PowerShell Lambda Function
4 |
5 | .DESCRIPTION
6 | This build file is configured for AWS CodeBuild builds, but will work locally as well.
7 |
8 | Build steps can include:
9 | - InstallDependencies
10 | - Clean
11 | - Analyze
12 | - Test
13 | - Build
14 | - Archive
15 |
16 | The default build will not call the 'InstallDependencies' task, but can be used if you want PSDepend
17 | to install pre-requisite modules. "Invoke-Build -Task InstallDependencies"
18 |
19 | This build will pull in configurations from the ".Settings.ps1" file as well, where users can
20 | more easily customize the build process if required.
21 |
22 | .EXAMPLE
23 | Invoke-Build
24 |
25 | This will perform the default build tasks: Clean, Analyze, Test, Build, Archive
26 |
27 | .EXAMPLE
28 | Invoke-Build -Task Analyze,Test
29 |
30 | This will perform only the Analyze and Test tasks.
31 | #>
32 |
33 | # Include: Settings
34 | $ScriptName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0]
35 | . "./$ScriptName.settings.ps1"
36 |
37 | # Default Build
38 | task . Clean, ImportModules, Analyze, Build, Publish
39 |
40 | # Pre-build variables to configure
41 | Enter-Build {
42 | $script:LambdaName = (Split-Path -Path $BuildFile -Leaf).Split('.')[0]
43 |
44 | # Identify other required paths
45 | $script:LambdaSourcePath = $BuildRoot
46 | $script:LambdaScriptPath = Join-Path -Path $script:LambdaSourcePath -ChildPath "$ScriptName.ps1"
47 | $script:ArtifactsPath = Join-Path -Path $BuildRoot -ChildPath 'Artifacts'
48 | $script:ArtifactPackage = Join-Path -Path $script:ArtifactsPath -ChildPath "$ScriptName.zip"
49 | $script:PowerShellLambdaPath = Split-Path -Path $script:LambdaSourcePath
50 | $script:StagingPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'LambdaStaging'
51 |
52 | if ([String]::IsNullOrWhiteSpace($env:CODEBUILD_SRC_DIR)) {
53 | $script:LambdaFunctionsPath = Split-Path -Path $script:PowerShellLambdaPath
54 | $script:CodeBuildRoot = Split-Path -Path $script:LambdaFunctionsPath
55 | }
56 | else {
57 | $script:CodeBuildRoot = $env:CODEBUILD_SRC_DIR
58 | }
59 | $script:ModulesRoot = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath 'Modules'
60 | $script:CFNParameterFilePath = Join-Path -Path $script:CodeBuildRoot -ChildPath 'CloudFormation'
61 |
62 | if (-not(Test-Path -Path $script:CFNParameterFilePath)) {
63 | throw ('Unable to find the cloudformation Path: {0}' -f $script:CFNParameterFilePath)
64 | }
65 | }
66 |
67 | # Synopsis: Imports PowerShell Modules
68 | task ImportModules {
69 | Write-Host 'Importing PowerShell Modules'
70 |
71 | $manifests = Get-ChildItem -Path $script:ModulesRoot -Recurse -Filter "*.psd1"
72 | foreach ($manifest in $manifests) {
73 | if (Get-Module -Name $manifest.BaseName) {
74 | Remove-Module -Name $manifest.BaseName
75 | }
76 |
77 | Write-Host ' -' $manifest.BaseName
78 | Import-Module $manifest.FullName -Force -Verbose:$false
79 | }
80 | }
81 |
82 | # Synopsis: Clean Artifacts Directory
83 | task Clean {
84 | foreach ($path in $script:ArtifactsPath, $script:StagingPath) {
85 | if (Test-Path -Path $path) {
86 | $null = Remove-Item -Path $path -Recurse -Force
87 | }
88 |
89 | $null = New-Item -ItemType Directory -Path $path -Force
90 | }
91 | }
92 |
93 | # Synopsis: Invokes Script Analyzer against the Module source path
94 | task Analyze {
95 | $scriptAnalyzerParams = @{
96 | Path = $script:LambdaScriptPath
97 | Severity = @('Error', 'Warning')
98 | Recurse = $true
99 | ExcludeRule = @('PSAvoidUsingWriteHost', 'PSUseShouldProcessForStateChangingFunctions')
100 | Verbose = $false
101 | }
102 |
103 | $scriptAnalyzerResults = Invoke-ScriptAnalyzer @scriptAnalyzerParams
104 |
105 | if ($scriptAnalyzerResults) {
106 | $scriptAnalyzerResults | Format-Table
107 | throw 'One or more PSScriptAnalyzer errors/warnings where found.'
108 | }
109 | }
110 |
111 | # Synopsis: Builds the Module to the Artifacts folder
112 | task Build {
113 | Write-Verbose -Message 'Compiling the AWS Lambda Package'
114 | $script:LambdaPackage = New-AWSPowerShellLambdaPackage -ScriptPath $script:LambdaScriptPath -StagingDirectory $script:StagingPath -OutputPackage $script:ArtifactPackage -Verbose
115 | Write-Host 'AWS Lambda Function Handler:' $script:LambdaPackage.LambdaHandler
116 | Write-Host 'PowerShell Function Handler Environment Variable Name:' $script:LambdaPackage.PowerShellFunctionHandlerEnvVar
117 | }
118 |
119 | task Publish {
120 | if ([String]::IsNullOrWhiteSpace($env:CODEBUILD_SRC_DIR) -and [String]::IsNullOrWhiteSpace($env:CODEBUILD_RESOLVED_SOURCE_VERSION)) {
121 | Write-Warning -Message 'Not publishing the artifact because the code is not running inside a CodeBuild Project'
122 | }
123 | else {
124 | 'Publishing Lambda Function to S3'
125 |
126 | $s3Key = '{0}/{1}/lambdafunctions/PowerShell/{2}.zip' -f $env:S3_KEY_PREFIX, $env:CODEBUILD_RESOLVED_SOURCE_VERSION, $ScriptName
127 | ' - S3Key:/{0}/{1}' -f $env:ARTIFACT_S3_BUCKET, $s3Key
128 |
129 | Write-S3Object -BucketName $env:ARTIFACT_S3_BUCKET -Key $s3Key -File $script:ArtifactPackage
130 |
131 | # Update json parameter files
132 | $cfnLambdaS3KeyParameterName = 'LMFunctionS3Key{0}' -f $ScriptName
133 | Write-Verbose -Message "JSON Parameter Name for cloudformation S3 Key: $cfnLambdaS3KeyParameterName" -Verbose
134 |
135 | $cfnLambdaHandlerParameterName = 'LMFunctionHandler{0}' -f $ScriptName
136 | Write-Verbose -Message "JSON Parameter Name for Lambda Function Handler: $cfnLambdaHandlerParameterName" -Verbose
137 |
138 | $jsonFiles = Get-ChildItem -Path $script:CFNParameterFilePath -Recurse -Filter "*.json"
139 | foreach ($jsonFile in $jsonFiles) {
140 | 'Processing {0}' -f $jsonFile.Name
141 | $jsonData = Get-Content -Path $jsonFile.FullName -Raw | ConvertFrom-Json
142 |
143 | # Update cfnLambdaS3KeyParameterName in json parameters
144 | try {
145 | $jsonData.Parameters.$cfnLambdaS3KeyParameterName = $s3Key
146 | ' - Updated the json parameter "{0}" with "{1}".' -f $cfnLambdaS3KeyParameterName, $s3Key
147 | }
148 | catch {
149 | ' - Unable to find the json parameter "{0}". No modifications being made.' -f $cfnLambdaS3KeyParameterName
150 | }
151 |
152 | # Update cfnLambdaHandlerParameterName in json parameters
153 | try {
154 | $jsonData.Parameters.$cfnLambdaHandlerParameterName = $script:LambdaPackage.LambdaHandler
155 | ' - Updated the json parameter "{0}" with "{1}".' -f $cfnLambdaHandlerParameterName, $script:LambdaPackage.LambdaHandler
156 | }
157 | catch {
158 | ' - Unable to find the json parameter "{0}". No modifications being made.' -f $cfnLambdaHandlerParameterName
159 | }
160 |
161 | # Export the json back to disk
162 | $jsonData | ConvertTo-Json | Out-File -FilePath $jsonFile.FullName -Force -Encoding utf8
163 | }
164 | }
165 | }
--------------------------------------------------------------------------------
/lambdafunctions/PowerShell/PubXMLMonitor/PubXMLMonitor.ps1:
--------------------------------------------------------------------------------
1 | # PowerShell script file to be executed as an AWS Lambda function.
2 | #
3 | # When executing in Lambda the following variables will be predefined.
4 | # $LambdaInput - A PSObject that contains the Lambda function input data.
5 | # $LambdaContext - An Amazon.Lambda.Core.ILambdaContext object that contains information about the currently running Lambda environment.
6 | #
7 | # The last item in the PowerShell pipeline will be returned as the result of the Lambda function.
8 | #
9 | # To include PowerShell modules with your Lambda function, like the AWS.Tools.Common module, add a "#Requires" statement
10 | # indicating the module and version.
11 |
12 | # Env variables that are set by the AWS Lambda environment:
13 | # $env:S3_BUCKET_NAME
14 | # $env:TELEGRAM_SECRET
15 | # $env:SERVICE_NAME
16 |
17 | #Requires -Modules @{ModuleName='AWS.Tools.Common';ModuleVersion='4.1.472'}
18 | #Requires -Modules @{ModuleName='AWS.Tools.CloudWatch';ModuleVersion='4.1.472'}
19 | #Requires -Modules @{ModuleName='AWS.Tools.SimpleSystemsManagement';ModuleVersion='4.1.472'}
20 | #Requires -Modules @{ModuleName='AWS.Tools.S3';ModuleVersion='4.1.472'}
21 | #Requires -Modules @{ModuleName='PoshGram';ModuleVersion='2.3.0'}
22 |
23 | # Uncomment to send the input event to CloudWatch Logs
24 | Write-Host (ConvertTo-Json -InputObject $LambdaInput -Compress -Depth 5)
25 |
26 | # CW Event Scheduled -> Lambda -> CW Metric
27 |
28 | #region supportingFunctions
29 |
30 | function Send-TelegramMessage {
31 | <#
32 | .SYNOPSIS
33 | Sends message to Telegram for notification.
34 | #>
35 | param (
36 | [Parameter(Mandatory = $true,
37 | HelpMessage = 'Message to send to telegram')]
38 | [string]
39 | $Message
40 | )
41 |
42 | if ($null -eq $script:telegramToken -or $null -eq $script:telegramChannel) {
43 | try {
44 | $getSSMParameterValueSplatToken = @{
45 | Name = 'telegramtoken'
46 | WithDecryption = $true
47 | ErrorAction = 'Stop'
48 | }
49 | $getSSMParameterValueSplatChannel = @{
50 | Name = 'telegramchannel'
51 | WithDecryption = $true
52 | ErrorAction = 'Stop'
53 | }
54 | $script:telegramToken = Get-SSMParameterValue @getSSMParameterValueSplatToken
55 | $script:telegramChannel = Get-SSMParameterValue @getSSMParameterValueSplatChannel
56 | }
57 | catch {
58 | throw $_
59 | }
60 | } #if_token_channel_null
61 |
62 | if ([string]::IsNullOrWhiteSpace($script:telegramToken) -or [string]::IsNullOrWhiteSpace($script:telegramChannel)) {
63 | throw 'Parameters not successfully retrieved'
64 | }
65 | else {
66 | Write-Host 'Parameters retrieved.'
67 | $token = $script:telegramToken.Parameters.Value
68 | $channel = $script:telegramChannel.Parameters.Value
69 | $out = Send-TelegramTextMessage -BotToken $token -ChatID $channel -Message $Message
70 | Write-Host ($out | Out-String)
71 | }
72 | } #Send-TelegramMessage
73 |
74 | #endregion
75 |
76 | $key = '{0}.zip' -f $env:SERVICE_NAME
77 | Write-Host ('Retrieving {0} from {1}..' -f $key, $env:S3_BUCKET_NAME)
78 | try {
79 | $getS3ObjectSplat = @{
80 | BucketName = $env:S3_BUCKET_NAME
81 | Key = $key
82 | ErrorAction = 'Stop'
83 | }
84 | $objInfo = Get-S3Object @getS3ObjectSplat
85 | }
86 | catch {
87 | Write-Warning -Message 'Error retrieving object from S3'
88 | Write-Error $_
89 | Send-TelegramMessage -Message '\\\ Project PSGalleryExplorer - PubXMLMonitor Error retrieving object from S3'
90 | return
91 | }
92 |
93 | if ($null -eq $objInfo) {
94 | Write-Warning -Message 'No object returned from S3'
95 | Send-TelegramMessage -Message '\\\ Project PSGalleryExplorer - PubXMLMonitor The S3 object was not found'
96 | }
97 |
98 | Write-Host 'Getting current date'
99 | $now = Get-Date
100 |
101 | Write-Host 'Determining how old the object is'
102 | $diff = $now - $objInfo.LastModified
103 | $diffDays = $diff.Days
104 | Write-Host ('Object is {0} days old' -f $diffDays)
105 |
106 | # Create a MetricDatum .NET object
107 | $MetricDatum = [Amazon.CloudWatch.Model.MetricDatum]::new()
108 | $MetricDatum.MetricName = 'PubXMLAge'
109 | $MetricDatum.Value = $diffDays
110 |
111 | # Create a Dimension .NET object
112 | $Dimension = [Amazon.CloudWatch.Model.Dimension]::new()
113 | $Dimension.Name = 'PubXML'
114 | $Dimension.Value = 'DaysOld'
115 |
116 | # Assign the Dimension object to the MetricDatum's Dimensions property
117 | $MetricDatum.Dimensions = $Dimension
118 |
119 | $Namespace = 'PSGalleryExplorer'
120 |
121 | try {
122 |
123 | # Write the metric data to the CloudWatch service
124 | $writeCWMetricDataSplat = @{
125 | Namespace = $Namespace
126 | MetricData = $MetricDatum
127 | ErrorAction = 'Stop'
128 | }
129 | Write-CWMetricData @writeCWMetricDataSplat
130 | }
131 | catch {
132 | $errorMessage = $_.Exception.Message
133 | Write-Error -Message ('Something went wrong: {0}' -f $errorMessage)
134 | Send-TelegramMessage -Message '\\\ Project PSGalleryExplorer - PubXMLMonitor Error sending metric data to CloudWatch'
135 | }
136 |
137 | return $true
138 |
--------------------------------------------------------------------------------
/lambdafunctions/PowerShell/PubXMLMonitor/PubXMLMonitor.settings.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Use this for custom modifications to the build process if needed.
4 | #>
5 |
6 | ###############################################################################
7 | # Before/After Hooks for the Core Task: Clean
8 | ###############################################################################
9 |
10 | # Synopsis: Executes before the Clean task.
11 | #task BeforeClean -Before Clean {}
12 |
13 | # Synopsis: Executes after the Clean task.
14 | #task AfterClean -After Clean {}
15 |
16 | ###############################################################################
17 | # Before/After Hooks for the Core Task: Analyze
18 | ###############################################################################
19 |
20 | # Synopsis: Executes before the Analyze task.
21 | #task BeforeAnalyze -Before Analyze {}
22 |
23 | # Synopsis: Executes after the Analyze task.
24 | #task AfterAnalyze -After Analyze {}
25 |
26 | ###############################################################################
27 | # Before/After Hooks for the Core Task: Archive
28 | ###############################################################################
29 |
30 | # Synopsis: Executes before the Archive task.
31 | #task BeforeArchive -Before Archive {}
32 |
33 | # Synopsis: Executes after the Archive task.
34 | #task AfterArchive -After Archive {}
35 |
36 | ###############################################################################
37 | # Before/After Hooks for the Core Task: Build
38 | ###############################################################################
39 |
40 | # Synopsis: Executes before the Build task.
41 | #task BeforeBuild -Before Build {}
42 |
43 | # Synopsis: Executes after the Build task.
44 | #task AfterBuild -After Build {}
45 |
46 | ###############################################################################
47 | # Before/After Hooks for the Core Task: Test
48 | ###############################################################################
49 |
50 | # Synopsis: Executes before the Test Task.
51 | #task BeforeTest -Before Test {}
52 |
53 | # Synopsis: Executes after the Test Task.
54 | #task AfterTest -After Test {}
55 |
--------------------------------------------------------------------------------
/mkdocs.yml:
--------------------------------------------------------------------------------
1 | # https://www.mkdocs.org/user-guide/configuration/
2 | # https://www.mkdocs.org/user-guide/writing-your-docs/
3 | # https://www.mkdocs.org/user-guide/writing-your-docs/#writing-with-markdown
4 | # https://mkdocs.readthedocs.io/en/0.15.2/user-guide/writing-your-docs/
5 | # https://mkdocs.readthedocs.io/en/0.15.2/user-guide/styling-your-docs/
6 | # https://example-mkdocs-basic.readthedocs.io/en/latest/
7 | # https://github.com/mkdocs/mkdocs/blob/master/mkdocs.yml
8 | # https://squidfunk.github.io/mkdocs-material/creating-your-site/
9 | # mkdocs.yml
10 |
11 | site_name: PSGalleryExplorer - search, explore, and discover PowerShell Gallery modules
12 | # site_url:
13 | repo_url: https://github.com/techthoughts2/PSGalleryExplorer
14 | # repo_name:
15 | # edit_uri: edit/main/docs/
16 | # edit_uri_template:
17 | site_description: PSGalleryExplorer is a PowerShell module that lets you search, explore, and discover PowerShell Gallery modules based on additional criteria. # meta tag to the generated HTML header
18 | site_author: Jake Morrison # meta tag to the generated HTML header
19 | copyright: "PSGalleryExplorer is licensed under the MIT license"
20 | # remote_branch:
21 | # remote_name:
22 | # docs_dir: docs
23 | # site_dir:
24 | # extra_css:
25 | # extra_javascript:
26 | markdown_extensions:
27 | # Python Markdown
28 | - admonition
29 | - toc:
30 | permalink: true
31 | # code highlighting
32 | - pymdownx.highlight:
33 | use_pygments: true
34 | - pymdownx.highlight:
35 | anchor_linenums: true
36 | - pymdownx.inlinehilite
37 | - pymdownx.snippets
38 | - pymdownx.superfences
39 |
40 | # extra_templates:
41 | # extra:
42 | theme:
43 | name: material
44 | # language: en
45 | # custom_dir: overrides
46 | features:
47 | # - navigation.tabs
48 | # - navigation.tabs.sticky
49 | # - navigation.path
50 | favicon: assets/PSGalleryExplorer_favicon-32x32.png
51 | icon:
52 | repo: fontawesome/brands/github
53 | # font:
54 | # text: Work Sans
55 | logo: assets/PSGalleryExplorerIcon.png
56 | # palette:
57 | # primary: teal
58 | palette:
59 | # Palette toggle for light mode
60 | - media: "(prefers-color-scheme: light)"
61 | scheme: default
62 | primary: light blue
63 | accent: deep purple
64 | toggle:
65 | icon: material/brightness-7
66 | name: Switch to dark mode
67 |
68 | # Palette toggle for dark mode
69 | - media: "(prefers-color-scheme: dark)"
70 | scheme: slate
71 | primary: indigo
72 | accent: light blue
73 | toggle:
74 | icon: material/brightness-4
75 | name: Switch to light mode
76 | nav:
77 | - Overview: index.md
78 | - Functions:
79 | - Find-ModuleByCommand.md: Find-ModuleByCommand.md
80 | - Find-PSGModule.md: Find-PSGModule.md
81 | - Data Collection: PSGalleryExplorer-Data_Collection.md
82 | - Metrics: PSGalleryExplorer-Metrics.md
83 | - FAQ: PSGalleryExplorer-FAQ.md
84 | - Change Log: CHANGELOG.md
85 | # - Functions:
86 | # - Function1: functions/function1.md
87 |
88 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer.Settings.ps1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/techthoughts2/PSGalleryExplorer/adbf98fe62f59219f97aeeb2c9271b556cf41535/src/PSGalleryExplorer.Settings.ps1
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Imports.ps1:
--------------------------------------------------------------------------------
1 | # This is a locally sourced Imports file for local development.
2 | # It can be imported by the psm1 in local development to add script level variables.
3 | # It will merged in the build process. This is for local development only.
4 |
5 | #region script variables
6 |
7 | function Get-DataLocation {
8 | $folderName = "PSGalleryExplorer"
9 | if ($PROFILE) {
10 | $script:dataPath = (Join-Path (Split-Path -Parent $PROFILE) $folderName)
11 | }
12 | else {
13 | $script:dataPath = "~\${$folderName}"
14 | }
15 | }
16 |
17 | $script:corps = @(
18 | '2AT B.V.'
19 | '3Shape A/S'
20 | 'AWS'
21 | 'Amazon'
22 | 'Amazon.com, Inc'
23 | 'Amazon Web Services'
24 | 'AtlassianPS'
25 | 'BAMCIS'
26 | 'Bentley Systems, Incorporated'
27 | 'BitTitan'
28 | 'BitTitan, Inc.'
29 | '(c) 2014 Microsoft Corporation. All rights reserved.'
30 | 'CData Software, Inc.'
31 | 'Chocolatey Software'
32 | 'Cisco Systems'
33 | 'Cisco'
34 | 'Cisco Systems, Inc.'
35 | 'Cybersecurity Engineering'
36 | 'DSC Community'
37 | 'Dell Inc.'
38 | 'Dell Technologies'
39 | 'Dell'
40 | 'DELL|EMC'
41 | 'DELL||EMC'
42 | 'Dell EMC'
43 | 'DevScope'
44 | 'Docker Inc.'
45 | 'Docker'
46 | 'Evotec'
47 | 'Google'
48 | 'Google Inc'
49 | 'Google Inc.'
50 | 'Hewlett Packard Enterprise Co.'
51 | 'Hewlett Packard Enterprise'
52 | 'Hewlett-Packard Enterprise'
53 | 'Hewlett Packard Enterprise Development LP'
54 | 'HP Development Company L.P.'
55 | 'HP Inc'
56 | 'HPE Storage, A Hewlett Packard Enterprise Company'
57 | 'https://github.com/ebekker/ACMESharp'
58 | 'Ironman Software, LLC'
59 | 'Ironman Software'
60 | 'JDH Information Technology Solutions, Inc.'
61 | 'JumpCloud'
62 | 'Kelverion'
63 | 'Kelverion Automation Limited'
64 | 'Lockstep Technology Group'
65 | 'Microsoft 365 Patterns and Practices'
66 | 'Microsoft (Xbox)'
67 | 'Microsoft Corp'
68 | 'Microsoft Inc.'
69 | 'Microsoft Corporation'
70 | 'Microsoft Corportation'
71 | 'Microsoft Corpration'
72 | 'Microsoft'
73 | 'Microsoft | Services'
74 | 'Microsoft CSS'
75 | 'MicrosoftCorporation'
76 | 'Microsoft Corp.'
77 | 'Microsoft Germany GmbH'
78 | 'Microsoft Support'
79 | 'MosaicMK Software LLC'
80 | 'MosaicMKSoftwareLLC'
81 | 'Mozilla Corporation'
82 | 'Nimble Storage, A Hewlett Packard Enterprise Company'
83 | 'Noveris Pty Ltd'
84 | 'Octopus Deploy Pty. Ltd'
85 | 'Octopus Deploy'
86 | 'Oracle Cloud Infrastructure'
87 | 'Oracle Corporation'
88 | 'Pentia A/S'
89 | 'Pentia'
90 | 'PowerShell.org'
91 | 'Pure Storage, Inc.'
92 | 'Red Gate Software Ltd.'
93 | 'SecureMFA'
94 | 'SecureMFA.com'
95 | 'SolarNet'
96 | 'SolarWinds Worldwide, LLC.'
97 | 'SolarWinds'
98 | 'SynEdgy Limited'
99 | 'Synergex International Corporation'
100 | 'Transitional Data Services, Inc.'
101 | 'VMware'
102 | 'VMware, Inc.'
103 | 'VMware Inc.'
104 | 'Virtual Engine'
105 | 'waldo.be'
106 | 'WebMD Health Services'
107 | 'Worxspace'
108 | 'XtremIO Dell EMC'
109 | 'Yevrag35, LLC.'
110 | 'Zerto Ltd.'
111 | )
112 | $script:regulars = @(
113 | 'BuildHelpers'
114 | 'BurntToast'
115 | 'Carbon'
116 | 'ChocolateyGet'
117 | 'CredentialManager'
118 | 'dbatools'
119 | 'Foil'
120 | 'ImportExcel'
121 | 'Invokebuild'
122 | 'Invoke-CommandAs'
123 | 'oh-my-posh'
124 | 'PendingReboot'
125 | 'PSDepend'
126 | 'PSDeploy'
127 | 'PSKoans'
128 | 'PSLogging'
129 | 'PSSlack'
130 | 'PSWindowsUpdate'
131 | 'Pester'
132 | 'PoshBot'
133 | 'posh-git'
134 | 'Posh-SSH'
135 | 'powershell-yaml'
136 | 'psake'
137 | 'RunAsUser'
138 | 'Selenium'
139 | 'SnipeitPS'
140 | 'SNMP'
141 | 'TeamViewerPS'
142 | 'Write-ObjectToSQL'
143 | )
144 |
145 | $domain = 'cloudfront.net'
146 | $target = 'dfuu1myynofuh'
147 | Get-DataLocation
148 | $script:dataFileZip = 'PSGalleryExplorer.zip'
149 | $script:metadataFile = 'PSGalleryExplorer.json'
150 | $script:dataFile = 'PSGalleryExplorer.xml'
151 | $script:dlURI = '{0}.{1}' -f $target, $domain
152 | $script:glData = $null
153 |
154 | #endregion
155 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/PSGalleryExplorer.Format.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PSGETable
6 |
7 | PSGEFormat
8 |
9 |
10 |
11 |
12 | 20
13 |
14 |
15 | 9
16 | right
17 |
18 |
19 | 7
20 | right
21 |
22 |
23 | 7
24 | right
25 |
26 |
27 | 7
28 | right
29 |
30 |
31 | 6
32 | right
33 |
34 |
35 | left
36 |
37 |
38 |
39 |
40 |
41 |
42 | Name
43 |
44 |
45 | Downloads
46 |
47 |
48 | Star
49 |
50 |
51 | Fork
52 |
53 |
54 | Issues
55 |
56 |
57 | Sub
58 |
59 |
60 | Description
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | PSGEList
69 |
70 | PSGEFormat
71 |
72 |
73 |
74 |
75 |
76 |
77 | Name
78 |
79 |
80 | Downloads
81 |
82 |
83 | LastUpdate
84 |
85 |
86 | Star
87 |
88 |
89 | Issues
90 |
91 |
92 | Sub
93 |
94 |
95 | Watch
96 |
97 |
98 | Fork
99 |
100 |
101 | RepoUpdate
102 |
103 |
104 | Description
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | PSGEInsightTable
114 |
115 | PSGEInsight
116 |
117 |
118 |
119 |
120 | 20
121 |
122 |
123 | 9
124 | right
125 |
126 |
127 | 7
128 | right
129 |
130 |
131 | 7
132 | right
133 |
134 |
135 | 6
136 | right
137 |
138 |
139 | 10
140 | right
141 |
142 |
143 | 6
144 | right
145 |
146 |
147 | left
148 |
149 |
150 |
151 |
152 |
153 |
154 | Name
155 |
156 |
157 | Downloads
158 |
159 |
160 | Star
161 |
162 |
163 | Fork
164 |
165 |
166 | Watch
167 |
168 |
169 | ModuleSize
170 |
171 |
172 | ModuleFileCount
173 |
174 |
175 | RepoUpdate
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 | PSGEInsightList
184 |
185 | PSGEInsight
186 |
187 |
188 |
189 |
190 |
191 |
192 | Name
193 |
194 |
195 | Downloads
196 |
197 |
198 | Star
199 |
200 |
201 | Fork
202 |
203 |
204 | Watch
205 |
206 |
207 | ModuleSize
208 |
209 |
210 | ModuleFileCount
211 |
212 |
213 | RepoUpdate
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/PSGalleryExplorer.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'PSGalleryExplorer'
3 | #
4 | # Generated by: Jake Morrison
5 | #
6 | # Generated on: 12/21/19
7 | #
8 |
9 | @{
10 |
11 | # Script module or binary module file associated with this manifest.
12 | RootModule = 'PSGalleryExplorer.psm1'
13 |
14 | # Version number of this module.
15 | ModuleVersion = '2.5.4'
16 |
17 | # Supported PSEditions
18 | # CompatiblePSEditions = @()
19 |
20 | # ID used to uniquely identify this module
21 | GUID = 'e9252e8e-2073-4084-9562-cf60ad84603d'
22 |
23 | # Author of this module
24 | Author = 'Jake Morrison'
25 |
26 | # Company or vendor of this module
27 | CompanyName = 'TechThoughts'
28 |
29 | # Copyright statement for this module
30 | Copyright = '(c) Jake Morrison. All rights reserved.'
31 |
32 | # Description of the functionality provided by this module
33 | Description = 'Search, explore, and discover PowerShell Gallery modules based on various criteria.'
34 |
35 | # Minimum version of the PowerShell engine required by this module
36 | PowerShellVersion = '5.1'
37 |
38 | # Name of the PowerShell host required by this module
39 | # PowerShellHostName = ''
40 |
41 | # Minimum version of the PowerShell host required by this module
42 | # PowerShellHostVersion = ''
43 |
44 | # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
45 | # DotNetFrameworkVersion = ''
46 |
47 | # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only.
48 | # CLRVersion = ''
49 |
50 | # Processor architecture (None, X86, Amd64) required by this module
51 | # ProcessorArchitecture = ''
52 |
53 | # Modules that must be imported into the global environment prior to importing this module
54 | RequiredModules = @(
55 | @{
56 | ModuleName = 'Convert'
57 | ModuleVersion = '1.5.0'
58 | }
59 | )
60 |
61 | # Assemblies that must be loaded prior to importing this module
62 | # RequiredAssemblies = @()
63 |
64 | # Script files (.ps1) that are run in the caller's environment prior to importing this module.
65 | # ScriptsToProcess = @()
66 |
67 | # Type files (.ps1xml) to be loaded when importing this module
68 | # TypesToProcess = @()
69 |
70 | # Format files (.ps1xml) to be loaded when importing this module
71 | FormatsToProcess = @(
72 | 'PSGalleryExplorer.Format.ps1xml'
73 | )
74 |
75 | # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
76 | # NestedModules = @()
77 |
78 | # 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.
79 | FunctionsToExport = @(
80 | 'Find-ModuleByCommand'
81 | 'Find-PSGModule'
82 | )
83 |
84 | # 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.
85 | # CmdletsToExport = '*'
86 |
87 | # Variables to export from this module
88 | # VariablesToExport = '*'
89 |
90 | # 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.
91 | # AliasesToExport = '*'
92 |
93 | # DSC resources to export from this module
94 | # DscResourcesToExport = @()
95 |
96 | # List of all modules packaged with this module
97 | # ModuleList = @()
98 |
99 | # List of all files packaged with this module
100 | # FileList = @()
101 |
102 | # 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.
103 | PrivateData = @{
104 |
105 | PSData = @{
106 |
107 | # Tags applied to this module. These help with module discovery in online galleries.
108 | Tags = @(
109 | 'discover',
110 | 'find',
111 | 'gallery',
112 | 'github',
113 | 'gitlab',
114 | 'bitbucket',
115 | 'module',
116 | 'modules',
117 | 'powershell',
118 | 'powershellmodule',
119 | 'psgallery',
120 | 'search'
121 | )
122 |
123 | # A URL to the license for this module.
124 | LicenseUri = 'https://github.com/techthoughts2/PSGalleryExplorer/blob/main/LICENSE'
125 |
126 | # A URL to the main website for this project.
127 | ProjectUri = 'https://github.com/techthoughts2/PSGalleryExplorer'
128 |
129 | # A URL to an icon representing this module.
130 | IconUri = 'https://github.com/techthoughts2/PSGalleryExplorer/raw/main/docs/assets/PSGalleryExplorerIcon.png'
131 |
132 | # ReleaseNotes of this module
133 | ReleaseNotes = 'https://github.com/techthoughts2/PSGalleryExplorer/blob/main/docs/CHANGELOG.md'
134 |
135 | # Prerelease string of this module
136 | # Prerelease = ''
137 |
138 | # Flag to indicate whether the module requires explicit user acceptance for install/update/save
139 | RequireLicenseAcceptance = $false
140 |
141 | # External dependent modules of this module
142 | # ExternalModuleDependencies = @()
143 |
144 | } # End of PSData hashtable
145 |
146 | } # End of PrivateData hashtable
147 |
148 | # HelpInfo URI of this module
149 | # HelpInfoURI = ''
150 |
151 | # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
152 | # DefaultCommandPrefix = ''
153 |
154 | }
155 |
156 |
157 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/PSGalleryExplorer.psm1:
--------------------------------------------------------------------------------
1 | # this psm1 is for local testing and development use only
2 |
3 | # dot source the parent import for local development variables
4 | . $PSScriptRoot\Imports.ps1
5 |
6 | # discover all ps1 file(s) in Public and Private paths
7 |
8 | $itemSplat = @{
9 | Filter = '*.ps1'
10 | Recurse = $true
11 | ErrorAction = 'Stop'
12 | }
13 | try {
14 | $public = @(Get-ChildItem -Path "$PSScriptRoot\Public" @itemSplat)
15 | $private = @(Get-ChildItem -Path "$PSScriptRoot\Private" @itemSplat)
16 | }
17 | catch {
18 | Write-Error $_
19 | throw "Unable to get get file information from Public & Private src."
20 | }
21 |
22 | # dot source all .ps1 file(s) found
23 | foreach ($file in @($public + $private)) {
24 | try {
25 | . $file.FullName
26 | }
27 | catch {
28 | throw "Unable to dot source [$($file.FullName)]"
29 |
30 | }
31 | }
32 |
33 | # export all public functions
34 | Export-ModuleMember -Function $public.Basename
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Confirm-DataLocation.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Confirm data output location. Creates output dir if not present.
4 | .DESCRIPTION
5 | Evaluates presence of data output location for xml dataset. If the directory is not found, it will be created.
6 | .EXAMPLE
7 | Confirm-DataLocation
8 |
9 | Confirms presence of data output location. Creates if not found.
10 | .OUTPUTS
11 | System.Boolean
12 | .NOTES
13 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
14 | .COMPONENT
15 | PSGalleryExplorer
16 | #>
17 | function Confirm-DataLocation {
18 | [CmdletBinding()]
19 | param (
20 | )
21 | $result = $true #assume the best
22 | Write-Verbose -Message 'Verifying data set output location...'
23 | try {
24 | $pathEval = Test-Path -Path $script:dataPath -ErrorAction Stop
25 | }
26 | catch {
27 | $result = $false
28 | Write-Error $_
29 | return $result
30 | }
31 |
32 | if (-not ($pathEval)) {
33 | Write-Verbose -Message 'Creating output directory...'
34 | try {
35 | $newItemSplat = @{
36 | ItemType = 'Directory'
37 | Path = $script:dataPath
38 | ErrorAction = 'Stop'
39 | }
40 | $null = New-Item @newItemSplat
41 | Write-Verbose -Message 'Created.'
42 | }
43 | catch {
44 | $result = $false
45 | Write-Error $_
46 | return $result
47 | }
48 | } #if_TestPath
49 | else {
50 | Write-Verbose 'Data path confirmed.'
51 | } #else_TestPath
52 |
53 | return $result
54 | } #Confirm-DataLocation
55 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Confirm-MetadataUpdate.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Compares the local metadata file to the remote metadata file.
4 | .DESCRIPTION
5 | Evaluates the local metadata file and compares it to the remote metadata file. If the files are the same, returns true. If the files are different, returns false.
6 | .EXAMPLE
7 | Confirm-MetadataUpdate
8 |
9 | Compares the local metadata file to the remote metadata file.
10 | .OUTPUTS
11 | System.Boolean
12 | .NOTES
13 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
14 | .COMPONENT
15 | PSGalleryExplorer
16 | #>
17 | function Confirm-MetadataUpdate {
18 | [CmdletBinding()]
19 | param (
20 | )
21 | $result = $true #assume the best
22 |
23 | Write-Verbose -Message 'Checking for metadata file...'
24 | $localMetaDataFilePath = [System.IO.Path]::Combine($script:dataPath, $script:metadataFile)
25 | try {
26 | $pathEval = Test-Path -Path $localMetaDataFilePath -ErrorAction Stop
27 | }
28 | catch {
29 | $result = $false
30 | Write-Error $_
31 | return $result
32 | }
33 |
34 | if (-not ($pathEval)) {
35 | $result = $false
36 | } #if_pathEval
37 | else {
38 | Write-Verbose 'Metadata file found. Performing metadata comparison...'
39 | try {
40 | $localMetadata = Get-Content $localMetaDataFilePath -ErrorAction 'Stop' | ConvertFrom-Json
41 | }
42 | catch {
43 | $result = $false
44 | Write-Error $_
45 | return $result
46 | }
47 |
48 | $tempMetadataFile = '{0}_temp' -f $script:metadataFile
49 | $tempMetadataFilePath = [System.IO.Path]::Combine($script:dataPath, $tempMetadataFile)
50 | # if the temp metadata file exists, delete it
51 | if (Test-Path -Path $tempMetadataFile) {
52 | Remove-Item -Path $tempMetadataFilePath -Force
53 | }
54 |
55 | # download metadata file for comparison
56 | $fileFetchStatus = Get-RemoteFile -File $script:metadataFile -OutFile $tempMetadataFile
57 | if ($fileFetchStatus -eq $false) {
58 | Write-Error 'Unable to download metadata file.'
59 | $result = $false
60 | return $result
61 | }
62 |
63 | try {
64 | $remoteMetadata = Get-Content $tempMetadataFilePath -ErrorAction 'Stop' | ConvertFrom-Json
65 | }
66 | catch {
67 | $result = $false
68 | Write-Error $_
69 | return $result
70 | }
71 |
72 | Write-Verbose -Message ('{0} vs {1}' -f $localMetadata.zipCreated, $remoteMetadata.zipCreated)
73 | if ($localMetadata.zipCreated -eq $remoteMetadata.zipCreated) {
74 | Write-Verbose 'Metadata file is current.'
75 | }
76 | else {
77 | Write-Verbose 'Metadata file requires refresh.'
78 | $result = $false
79 | }
80 | }
81 |
82 | return $result
83 | } #Confirm-MetadataUpdate
84 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Confirm-XMLDataSet.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Confirms the XML dataset file is available and not beyond the expiration time.
4 | .DESCRIPTION
5 | Determines if the XML dataset file is stale or not available.
6 | If the file is not available, false will be returned so it can be downloaded.
7 | If the file is available, but over 9 days old, the metadata file will be checked to see if an update is available.
8 | If an update is available after the metadata file is checked, false will be returned so the data file can be refreshed.
9 | .EXAMPLE
10 | Confirm-XMLDataSet
11 |
12 | Checks for XML dataset and determines if it is 9 days older or more.
13 | .OUTPUTS
14 | System.Boolean
15 | .NOTES
16 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
17 | .COMPONENT
18 | PSGalleryExplorer
19 | #>
20 | function Confirm-XMLDataSet {
21 | [CmdletBinding()]
22 | param (
23 | )
24 | $result = $true #assume the best
25 | $dataFile = '{0}/{1}' -f $script:dataPath, $script:dataFile
26 |
27 | Write-Verbose -Message 'Confirming valid and current data set...'
28 |
29 | # if the file doesn't exist, we need to download it
30 | Write-Verbose -Message 'Checking for data file...'
31 | try {
32 | $pathEval = Test-Path -Path $dataFile -ErrorAction Stop
33 | }
34 | catch {
35 | $result = $false
36 | Write-Error $_
37 | return $result
38 | }
39 |
40 | if (-not ($pathEval)) {
41 | $result = $false
42 | } #if_pathEval
43 | else {
44 | Write-Verbose 'Data file found. Checking date of file...'
45 | try {
46 | $fileData = Get-Item -Path $dataFile -ErrorAction Stop
47 | }
48 | catch {
49 | $result = $false
50 | Write-Error $_
51 | return $result
52 | }
53 | if ($fileData) {
54 | $creationDate = $fileData.LastWriteTime
55 | $now = Get-Date
56 | if (($now - $creationDate).Days -ge 9) {
57 | # Write-Verbose 'Data file requires refresh.'
58 | Write-Verbose 'Data file is older than 9 days. Checking if an update is available...'
59 | $metadataStatus = Confirm-MetadataUpdate
60 | if ($metadataStatus -eq $false) {
61 | Write-Verbose 'Refreshing data file...'
62 | $result = $false
63 | }
64 | else {
65 | Write-Verbose 'No update available. Data file is current.'
66 | }
67 | }
68 | else {
69 | Write-Verbose 'Data file verified'
70 | }
71 | } #if_fileData
72 | else {
73 | Write-Warning 'Unable to retrieve file information for PSGalleryExplorer data set.'
74 | $result = $false
75 | return $result
76 | } #else_fileData
77 | } #else_pathEval
78 |
79 | return $result
80 | } #Confirm-XMLDataSet
81 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Expand-XMLDataSet.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Unzips the XML data set.
4 | .DESCRIPTION
5 | Evaluates for previous version of XML data set and removes if required. Expands the XML data set for use.
6 | .EXAMPLE
7 | Expand-XMLDataSet
8 |
9 | Unzips and expands the XML data set.
10 | .OUTPUTS
11 | System.Boolean
12 | .NOTES
13 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
14 | .COMPONENT
15 | PSGalleryExplorer
16 | #>
17 | function Expand-XMLDataSet {
18 | [CmdletBinding()]
19 | param (
20 | )
21 | $result = $true #assume the best
22 | $dataFile = '{0}/{1}' -f $script:dataPath, $script:dataFile
23 |
24 | Write-Verbose -Message 'Testing if data set file already exists...'
25 | try {
26 | $pathEval = Test-Path -Path $dataFile -ErrorAction Stop
27 | Write-Verbose -Message "EVAL: $true"
28 | }
29 | catch {
30 | $result = $false
31 | Write-Error $_
32 | return $result
33 | }
34 |
35 | if ($pathEval) {
36 | Write-Verbose -Message 'Removing existing data set file...'
37 | try {
38 | $removeItemSplat = @{
39 | Force = $true
40 | Path = $dataFile
41 | ErrorAction = 'Stop'
42 | }
43 | Remove-Item @removeItemSplat
44 | } #try
45 | catch {
46 | $result = $false
47 | Write-Error $_
48 | return $result
49 | } #catch
50 | } #if_pathEval
51 |
52 | Write-Verbose -Message 'Expanding data set archive...'
53 | try {
54 | $expandArchiveSplat = @{
55 | DestinationPath = $script:dataPath
56 | Force = $true
57 | ErrorAction = 'Stop'
58 | Path = '{0}/{1}' -f $script:dataPath, $script:dataFileZip
59 | }
60 | $null = Expand-Archive @expandArchiveSplat
61 | Write-Verbose -Message 'Expand completed.'
62 | } #try
63 | catch {
64 | $result = $false
65 | Write-Error $_
66 | } #catch
67 |
68 | return $result
69 | } #Expand-XMLDataSet
70 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Get-RemoteFile.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Downloads file to device.
4 | .DESCRIPTION
5 | Retrieves file from web and downloads to device.
6 | .EXAMPLE
7 | Get-RemoteFile
8 |
9 | Downloads file to data path.
10 | .PARAMETER File
11 | File to download.
12 | .PARAMETER OutFileName
13 | Specify output file name.
14 | .OUTPUTS
15 | System.Boolean
16 | .NOTES
17 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
18 | Overwrites existing zip file.
19 | .COMPONENT
20 | PSGalleryExplorer
21 | #>
22 | function Get-RemoteFile {
23 | [CmdletBinding()]
24 | param (
25 | [Parameter(Mandatory = $true,
26 | HelpMessage = 'File to download')]
27 | [string]$File,
28 |
29 | [Parameter(Mandatory = $false,
30 | HelpMessage = 'Specify output file name.')]
31 | [string]$OutFileName
32 | )
33 | $result = $true #assume the best
34 |
35 | if ($OutFileName) {
36 | $OutFile = $OutFileName
37 | }
38 | else {
39 | $OutFile = $File
40 | }
41 |
42 | Write-Verbose -Message 'Downloading file...'
43 | try {
44 | $invokeWebRequestSplat = @{
45 | OutFile = [System.IO.Path]::Combine($script:dataPath, $OutFile)
46 | Uri = 'https://{0}/{1}' -f $script:dlURI, $File
47 | ErrorAction = 'Stop'
48 | }
49 | $oldProgressPreference = $progressPreference
50 | $progressPreference = 'SilentlyContinue'
51 | if ($PSEdition -eq 'Desktop') {
52 | $null = Invoke-WebRequest @invokeWebRequestSplat -PassThru -UseBasicParsing
53 | }
54 | else {
55 | $null = Invoke-WebRequest @invokeWebRequestSplat -PassThru
56 | }
57 | } #try
58 | catch {
59 | $result = $false
60 | Write-Error $_
61 | } #catch
62 | finally {
63 | $progressPreference = $oldProgressPreference
64 | } #finally
65 | return $result
66 | } #Get-RemoteFile
67 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Import-XMLDataSet.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Evaluates if XML data set is in memory and kicks of child processes to obtain XML data set.
4 | .DESCRIPTION
5 | XML data set will be evaluated if already in memory. If not, a series of processes will be kicked off to load the XML data set for use.
6 | .EXAMPLE
7 | Import-XMLDataSet
8 |
9 | Loads the XML data set into memory.
10 | .OUTPUTS
11 | System.Boolean
12 | .NOTES
13 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
14 | Parent process for getting XML data.
15 | .COMPONENT
16 | PSGalleryExplorer
17 | #>
18 | function Import-XMLDataSet {
19 | [CmdletBinding()]
20 | param (
21 | )
22 | $result = $true #assume the best
23 | Write-Verbose -Message 'Verifying current state of XML data set...'
24 | if ($null -eq $script:glData) {
25 | $dataCheck = Invoke-XMLDataCheck
26 | if ($dataCheck) {
27 | try {
28 | $getContentSplat = @{
29 | Path = "$script:dataPath\$script:dataFile"
30 | Raw = $true
31 | ErrorAction = 'Stop'
32 | }
33 | $fileData = Get-Content @getContentSplat
34 | $script:glData = $fileData | ConvertFrom-Clixml -ErrorAction Stop
35 | } #try
36 | catch {
37 | $result = $false
38 | Write-Error $_
39 | } #catch
40 | } #if_dataCheck
41 | else {
42 | $result = $false
43 | } #else_dataCheck
44 | } #if_gldata
45 | return $result
46 | } #Import-XMLDataSet
47 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Private/Invoke-XMLDataCheck.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Invokes all child functions required to process retrieving the XML data set file.
4 | .DESCRIPTION
5 | Runs all required child functions to successfully retrieve and process the XML data set file.
6 | .EXAMPLE
7 | Invoke-XMLDataCheck
8 |
9 | Downloads, expands, and verified the XML data set file.
10 | .OUTPUTS
11 | System.Boolean
12 | .NOTES
13 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
14 | Confirm-XMLDataSet
15 | Get-RemoteFile
16 | Expand-XMLDataSet
17 | .COMPONENT
18 | PSGalleryExplorer
19 | #>
20 | function Invoke-XMLDataCheck {
21 | [CmdletBinding(ConfirmImpact = 'Low',
22 | SupportsShouldProcess = $true)]
23 | param (
24 | [Parameter(Mandatory = $false,
25 | HelpMessage = 'Skip confirmation')]
26 | [switch]$Force
27 | )
28 | Begin {
29 |
30 | if (-not $PSBoundParameters.ContainsKey('Verbose')) {
31 | $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference')
32 | }
33 | if (-not $PSBoundParameters.ContainsKey('Confirm')) {
34 | $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference')
35 | }
36 | if (-not $PSBoundParameters.ContainsKey('WhatIf')) {
37 | $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference')
38 | }
39 |
40 | Write-Verbose -Message ('[{0}] Confirm={1} ConfirmPreference={2} WhatIf={3} WhatIfPreference={4}' -f $MyInvocation.MyCommand, $Confirm, $ConfirmPreference, $WhatIf, $WhatIfPreference)
41 |
42 | $results = $true #assume the best
43 | } #begin
44 | Process {
45 | # -Confirm --> $ConfirmPreference = 'Low'
46 | # ShouldProcess intercepts WhatIf* --> no need to pass it on
47 | if ($Force -or $PSCmdlet.ShouldProcess("ShouldProcess?")) {
48 | Write-Verbose -Message ('[{0}] Reached command' -f $MyInvocation.MyCommand)
49 | $ConfirmPreference = 'None'
50 |
51 | $dataOutputDir = Confirm-DataLocation
52 | if ($dataOutputDir -eq $true) {
53 | $confirm = Confirm-XMLDataSet
54 | if (-not $confirm -eq $true) {
55 | $retrieve = Get-RemoteFile -File $script:dataFileZip
56 | # remove metadata file if it exists
57 | $localMetaDataFilePath = [System.IO.Path]::Combine($script:dataPath, $script:metadataFile)
58 | if (Test-Path -Path $localMetaDataFilePath) {
59 | Remove-Item -Path $localMetaDataFilePath -Force
60 | }
61 | $retrieveMetadata = Get-RemoteFile -File $script:metadataFile
62 | if ($retrieve -eq $true -and $retrieveMetadata -eq $true) {
63 | $expand = Expand-XMLDataSet
64 | if (-not $expand -eq $true) {
65 | $results = $false
66 | }
67 | }
68 | else {
69 | $results = $false
70 | }
71 | } #if_Confirm
72 | } #if_data_output
73 | else {
74 | $results = $false
75 | } #else_data_output
76 |
77 | } #if_Should
78 | } #process
79 | End {
80 | return $results
81 | } #end
82 | } #Invoke-XMLDataCheck
83 |
--------------------------------------------------------------------------------
/src/PSGalleryExplorer/Public/Find-ModuleByCommand.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Searches for modules that contain a specific command or cmdlet name.
4 | .DESCRIPTION
5 | The Find-ModuleByCommand cmdlet searches for modules on the PowerShell Gallery that contain a specified command or cmdlet name. The cmdlet returns a list of modules that include the command or cmdlet, along with key metrics and information about the module. This cmdlet is useful when you need to quickly find a module that includes a particular command or cmdlet, without having to install or download the module first.
6 | .EXAMPLE
7 | Find-ModuleByCommand -CommandName New-ModuleProject
8 |
9 | Returns a list of modules that contain the command New-ModuleProject
10 | .EXAMPLE
11 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage'
12 |
13 | Returns a list of modules that contain the command Send-TelegramTextMessage
14 | .EXAMPLE
15 | Find-ModuleByCommand -CommandName 'Send-TelegramTextMessage' -InsightView
16 |
17 | Returns a list of modules that contain the command Send-TelegramTextMessage, with focused community insights about the module
18 | .PARAMETER CommandName
19 | Specifies the command name to search for
20 | .PARAMETER InsightView
21 | Output focuses on additional insights available through PSGalleryExplorer. This includes the module's size and file count, as well as repository metrics like stars, forks, and last repo update date
22 | .OUTPUTS
23 | PSGEFormat
24 | .NOTES
25 | Author: Jake Morrison - @jakemorrison - https://www.techthoughts.info/
26 | .COMPONENT
27 | PSGalleryExplorer
28 | .LINK
29 | https://psgalleryexplorer.readthedocs.io/en/latest/Find-ModuleByCommand/
30 | #>
31 | function Find-ModuleByCommand {
32 | [CmdletBinding()]
33 | param (
34 | [Parameter(Mandatory = $true,
35 | HelpMessage = 'Specifies the command name to search for')]
36 | [string]$CommandName,
37 |
38 | [Parameter(Mandatory = $false,
39 | HelpMessage = 'Output focus on community insights')]
40 | [switch]$InsightView
41 | )
42 | Write-Verbose -Message 'Verifying XML Data Set Availability...'
43 | if (Import-XMLDataSet) {
44 | Write-Verbose -Message 'Verified.'
45 | $dataSet = $script:glData
46 |
47 | Write-Verbose -Message ('Searching for Modules that contain the command: {0}' -f $CommandName)
48 | $find = $dataSet | Where-Object {
49 | $_.Includes.Function -contains $CommandName -or
50 | $_.Includes.Command -contains $CommandName -or
51 | $_.Includes.Cmdlet -contains $CommandName
52 | }
53 |
54 | } #if_Import-XMLDataSet
55 | else {
56 | Write-Warning -Message 'PSGalleryExplorer was unable to source the required data set file.'
57 | Write-Warning -Message 'Ensure you have an active internet connection'
58 | return
59 | } #else_Import-XMLDataSet
60 |
61 | Write-Verbose -Message 'Adding output properties to objects...'
62 | foreach ($item in $find) {
63 | $metrics = $null
64 | $metrics = @{
65 | Downloads = $item.AdditionalMetadata.downloadCount
66 | LastUpdate = $item.AdditionalMetadata.lastUpdated
67 | Star = $item.ProjectInfo.StarCount
68 | Sub = $item.ProjectInfo.Subscribers
69 | Watch = $item.ProjectInfo.Watchers
70 | Fork = $item.ProjectInfo.Forks
71 | Issues = $item.ProjectInfo.Issues
72 | RepoUpdate = $item.ProjectInfo.Updated
73 | }
74 | $item | Add-Member -NotePropertyMembers $metrics -TypeName Asset -Force
75 | if ($InsightView) {
76 | $item.PSObject.TypeNames.Insert(0, 'PSGEInsight')
77 | }
78 | else {
79 | $item.PSObject.TypeNames.Insert(0, 'PSGEFormat')
80 | }
81 | } #foreach_find
82 | Write-Verbose -Message 'Properties addition completed.'
83 |
84 | return $find
85 | } #Find-ModuleByCommand
86 |
--------------------------------------------------------------------------------
/src/PSScriptAnalyzerSettings.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | #________________________________________
3 | #IncludeDefaultRules
4 | IncludeDefaultRules = $true
5 | #________________________________________
6 | #Severity
7 | #Specify Severity when you want to limit generated diagnostic records to a specific subset: [ Error | Warning | Information ]
8 | Severity = @('Error', 'Warning')
9 | #________________________________________
10 | #CustomRulePath
11 | #Specify CustomRulePath when you have a large set of custom rules you'd like to reference
12 | #CustomRulePath = "Module\InjectionHunter\1.0.0\InjectionHunter.psd1"
13 | #________________________________________
14 | #IncludeRules
15 | #Specify IncludeRules when you only want to run specific subset of rules instead of the default rule set.
16 | #IncludeRules = @('PSShouldProcess',
17 | # 'PSUseApprovedVerbs')
18 | #________________________________________
19 | #ExcludeRules
20 | #Specify ExcludeRules when you want to exclude a certain rule from the the default set of rules.
21 | #ExcludeRules = @(
22 | # 'PSUseDeclaredVarsMoreThanAssignments'
23 | #)
24 | #________________________________________
25 | #Rules
26 | #Here you can specify customizations for particular rules. Several examples are included below:
27 | #Rules = @{
28 | # PSUseCompatibleCmdlets = @{
29 | # compatibility = @('core-6.1.0-windows', 'desktop-4.0-windows')
30 | # }
31 | # PSUseCompatibleSyntax = @{
32 | # Enable = $true
33 | # TargetVersions = @(
34 | # '3.0',
35 | # '5.1',
36 | # '6.2'
37 | # )
38 | # }
39 | # PSUseCompatibleCommands = @{
40 | # Enable = $true
41 | # TargetProfiles = @(
42 | # 'win-8_x64_10.0.14393.0_6.1.3_x64_4.0.30319.42000_core', # PS 6.1 on WinServer-2019
43 | # 'win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework', # PS 5.1 on WinServer-2019
44 | # 'win-8_x64_6.2.9200.0_3.0_x64_4.0.30319.42000_framework' # PS 3 on WinServer-2012
45 | # )
46 | # }
47 | # PSUseCompatibleTypes = @{
48 | # Enable = $true
49 | # TargetProfiles = @(
50 | # 'ubuntu_x64_18.04_6.1.3_x64_4.0.30319.42000_core',
51 | # 'win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework'
52 | # )
53 | # # You can specify types to not check like this, which will also ignore methods and members on it:
54 | # IgnoreTypes = @(
55 | # 'System.IO.Compression.ZipFile'
56 | # )
57 | # }
58 | #}
59 | #________________________________________
60 | }
61 |
--------------------------------------------------------------------------------
/src/Tests/Unit/ExportedFunctions.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | BeforeAll {
15 | Set-Location -Path $PSScriptRoot
16 | $ModuleName = 'PSGalleryExplorer'
17 | $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1")
18 | $manifestContent = Test-ModuleManifest -Path $PathToManifest
19 | $moduleExported = Get-Command -Module $ModuleName | Select-Object -ExpandProperty Name
20 | $manifestExported = ($manifestContent.ExportedFunctions).Keys
21 | }
22 | Describe $ModuleName {
23 |
24 | Context 'Exported Commands' -Fixture {
25 |
26 | Context 'Number of commands' -Fixture {
27 | It -Name 'Exports the same number of public functions as what is listed in the Module Manifest' -Test {
28 | $manifestExported.Count | Should -BeExactly $moduleExported.Count
29 | }
30 | }
31 |
32 | Context 'Explicitly exported commands' -ForEach $moduleExported {
33 | foreach ($command in $moduleExported) {
34 | BeforeAll {
35 | $command = $_
36 | }
37 | It -Name "Includes the $command in the Module Manifest ExportedFunctions" -Test {
38 | $manifestExported -contains $command | Should -BeTrue
39 | }
40 | }
41 | }
42 | }
43 |
44 | Context 'Command Help' -ForEach $moduleExported {
45 | foreach ($command in $moduleExported) {
46 | BeforeAll {
47 | $help = Get-Help -Name $_ -Full
48 | }
49 | Context $command -Fixture {
50 | $help = Get-Help -Name $command -Full
51 |
52 | It -Name 'Includes a Synopsis' -Test {
53 | $help.Synopsis | Should -Not -BeNullOrEmpty
54 | }
55 |
56 | It -Name 'Includes a Description' -Test {
57 | $help.description.Text | Should -Not -BeNullOrEmpty
58 | }
59 |
60 | It -Name 'Includes an Example' -Test {
61 | $help.examples.example | Should -Not -BeNullOrEmpty
62 | }
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/src/Tests/Unit/PSGalleryExplorer-Module.Tests.ps1:
--------------------------------------------------------------------------------
1 | BeforeAll {
2 | #-------------------------------------------------------------------------
3 | Set-Location -Path $PSScriptRoot
4 | #-------------------------------------------------------------------------
5 | $ModuleName = 'PSGalleryExplorer'
6 | $PathToManifest = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psd1")
7 | $PathToModule = [System.IO.Path]::Combine('..', '..', $ModuleName, "$ModuleName.psm1")
8 | #-------------------------------------------------------------------------
9 | }
10 | Describe 'Module Tests' -Tag Unit {
11 | Context "Module Tests" {
12 | $script:manifestEval = $null
13 | It 'Passes Test-ModuleManifest' {
14 | { $script:manifestEval = Test-ModuleManifest -Path $PathToManifest } | Should -Not -Throw
15 | $? | Should -BeTrue
16 | } #manifestTest
17 | It 'root module PSGalleryExplorer.psm1 should exist' {
18 | $PathToModule | Should -Exist
19 | $? | Should -BeTrue
20 | } #psm1Exists
21 | It 'manifest should contain PSGalleryExplorer.psm1' {
22 | $PathToManifest |
23 | Should -FileContentMatchExactly "PSGalleryExplorer.psm1"
24 | } #validPSM1
25 | It 'should have a matching module name in the manifest' {
26 | $script:manifestEval.Name | Should -BeExactly $ModuleName
27 | } #name
28 | It 'should have a valid description in the manifest' {
29 | $script:manifestEval.Description | Should -Not -BeNullOrEmpty
30 | } #description
31 | It 'should have a valid author in the manifest' {
32 | $script:manifestEval.Author | Should -Not -BeNullOrEmpty
33 | } #author
34 | It 'should have a valid version in the manifest' {
35 | $script:manifestEval.Version -as [Version] | Should -Not -BeNullOrEmpty
36 | } #version
37 | It 'should have a valid guid in the manifest' {
38 | { [guid]::Parse($script:manifestEval.Guid) } | Should -Not -Throw
39 | } #guid
40 | It 'should not have any spaces in the tags' {
41 | foreach ($tag in $script:manifestEval.Tags) {
42 | $tag | Should -Not -Match '\s'
43 | }
44 | } #tagSpaces
45 | It 'should have a valid project Uri' {
46 | $script:manifestEval.ProjectUri | Should -Not -BeNullOrEmpty
47 | } #uri
48 | } #context_ModuleTests
49 | } #describe_ModuleTests
50 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Confirm-DataLocation.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Confirm-DataLocation' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | } #before_all
21 |
22 | BeforeEach {
23 | Mock -CommandName Test-Path -MockWith {
24 | $true
25 | } #endMock
26 | Mock -CommandName New-Item -MockWith { } #endMock
27 | } #before_each
28 |
29 | Context 'Error' {
30 |
31 | It 'should return false if an error is encountered with Test-Path' {
32 | Mock -CommandName Test-Path -MockWith {
33 | throw 'FakeError'
34 | } #endMock
35 | Confirm-DataLocation | Should -BeExactly $false
36 | } #it
37 |
38 | It 'should return false if an error is encountered with New-Item' {
39 | Mock -CommandName Test-Path -MockWith {
40 | $false
41 | } #endMock
42 | Mock -CommandName New-Item -MockWith {
43 | throw 'FakeError'
44 | } #endMock
45 | Confirm-DataLocation | Should -BeExactly $false
46 | } #it
47 |
48 | } #context_Error
49 |
50 | Context 'Success' {
51 |
52 | It 'should return true if the output dir already exists' {
53 | Confirm-DataLocation | Should -BeExactly $true
54 | } #it
55 |
56 | It 'should return true if the output dir does not exists and is created' {
57 | Mock -CommandName Test-Path -MockWith {
58 | $false
59 | } #endMock
60 | Confirm-DataLocation | Should -BeExactly $true
61 | } #it
62 |
63 | } #context_Success
64 |
65 | } #describe_Confirm-DataLocation
66 |
67 | } #inModule
68 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Confirm-MetadataUpdate.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Confirm-MetadataUpdate' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | $metadataJSON = @'
21 | {
22 | "zipCreated": "1679500816"
23 | }
24 | '@
25 | $metadataJSON2 = @'
26 | {
27 | "zipCreated": "1679500817"
28 | }
29 | '@
30 | function Remove-Item {
31 | }
32 | } #before_all
33 |
34 | BeforeEach {
35 | Mock -CommandName Test-Path -MockWith {
36 | $true
37 | } #endMock
38 | Mock -CommandName Get-Content -MockWith {
39 | $metadataJSON
40 | } #endMock
41 | Mock -CommandName Remove-Item -MockWith {}
42 | Mock -CommandName Get-RemoteFile -MockWith {
43 | $true
44 | } #endMock
45 | } #before_each
46 |
47 | Context 'Error' {
48 |
49 | It 'should return false if an error is encountered with Test-Path' {
50 | Mock -CommandName Test-Path -MockWith {
51 | throw 'FakeError'
52 | } #endMock
53 | Confirm-MetadataUpdate | Should -BeExactly $false
54 | } #it
55 |
56 | It 'should return false if an error is encountered with Get-Content' {
57 | Mock -CommandName Get-Content -MockWith {
58 | throw 'FakeError'
59 | } #endMock
60 | Confirm-MetadataUpdate | Should -BeExactly $false
61 | } #it
62 |
63 | It 'should return false if the metadata file is not downloaded' {
64 | Mock -CommandName Get-RemoteFile -MockWith {
65 | $false
66 | } #endMock
67 | Confirm-MetadataUpdate | Should -BeExactly $false
68 | } #it
69 |
70 | It 'should return false if an error is encountered with second Get-Content' {
71 | $script:mockCalled = 0
72 | $mockInvoke = {
73 | $script:mockCalled++
74 | if ($script:mockCalled -eq 1) {
75 | return $metadataJSON
76 | }
77 | elseif ($script:mockCalled -eq 2) {
78 | throw 'FakeError'
79 | }
80 | }
81 | Mock -CommandName Get-Content -MockWith $mockInvoke
82 | Confirm-MetadataUpdate | Should -BeExactly $false
83 | } #it
84 |
85 | } #context_Error
86 |
87 | Context 'Success' {
88 |
89 | It 'should return false if the metadata file is not found' {
90 | Mock -CommandName Test-Path -MockWith {
91 | $false
92 | } #endMock
93 | Confirm-MetadataUpdate | Should -BeExactly $false
94 | } #it
95 |
96 | It 'should return true if the local and remote metadata files are the same' {
97 | Confirm-MetadataUpdate | Should -BeExactly $true
98 | } #it
99 |
100 | It 'should return false if the local and remote metadata files are different' {
101 | $script:mockCalled = 0
102 | $mockInvoke = {
103 | $script:mockCalled++
104 | if ($script:mockCalled -eq 1) {
105 | return $metadataJSON
106 | }
107 | elseif ($script:mockCalled -eq 2) {
108 | return $metadataJSON2
109 | }
110 | }
111 | Mock -CommandName Get-Content -MockWith $mockInvoke
112 | Confirm-MetadataUpdate | Should -BeExactly $false
113 | } #it
114 |
115 | } #context_Success
116 |
117 | } #describe_Confirm-MetadataUpdate
118 |
119 | } #inModule
120 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Confirm-XMLDataSet.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Confirm-XMLDataSet' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | } #before_all
21 |
22 | BeforeEach {
23 | Mock -CommandName Test-Path -MockWith {
24 | $true
25 | } #endMock
26 | Mock -CommandName Get-Item -MockWith {
27 | [PSCustomObject]@{
28 | Name = 'AzModI.xml'
29 | CreationTime = [datetime]'01/06/20 21:17:21'
30 | CreationTimeUtc = [datetime]'01/07/20 05:17:21'
31 | LastAccessTime = [datetime]'01/06/20 21:17:22'
32 | LastWriteTime = [datetime]'01/06/20 21:17:21'
33 | }
34 | } #endMock
35 | Mock -CommandName Get-Date -MockWith {
36 | [datetime]'01/06/20 21:17:22'
37 | } #endMock
38 | Mock -CommandName Confirm-MetadataUpdate -MockWith {
39 | $true
40 | } #endMock
41 | } #before_each
42 |
43 | Context 'Error' {
44 |
45 | It 'should return false if an error is encountered with Test-Path' {
46 | Mock -CommandName Test-Path -MockWith {
47 | throw 'FakeError'
48 | } #endMock
49 | Confirm-XMLDataSet | Should -BeExactly $false
50 | } #it
51 |
52 | It 'should return false if an error is encountered with Get-Item' {
53 | Mock -CommandName Get-Item -MockWith {
54 | throw 'FakeError'
55 | } #endMock
56 | Confirm-XMLDataSet | Should -BeExactly $false
57 | } #it
58 |
59 | It 'should return null false if no file information is returned from Get-Item' {
60 | Mock -CommandName Get-Item -MockWith { } #endMock
61 | Confirm-XMLDataSet | Should -BeExactly $false
62 | } #it
63 |
64 | } #context_Error
65 |
66 | Context 'Success' {
67 |
68 | It 'should return false if the data file is not found' {
69 | Mock -CommandName Test-Path -MockWith {
70 | $false
71 | } #endMock
72 | Confirm-XMLDataSet | Should -BeExactly $false
73 | } #it
74 |
75 | It 'should return true if the file is found and is less than 9 days old' {
76 | Confirm-XMLDataSet | Should -BeExactly $true
77 | } #it
78 |
79 | It 'should return true if the data file is older than 9 days but the metadata file is current' {
80 | Mock -CommandName Get-Date -MockWith {
81 | [datetime]'1/16/20 21:17:22'
82 | } #endMock
83 | Confirm-XMLDataSet | Should -BeExactly $true
84 | } #it
85 |
86 | It 'should return false if the data file is older than 9 days and the metadata file is also out of date' {
87 | Mock -CommandName Get-Date -MockWith {
88 | [datetime]'1/16/20 21:17:22'
89 | } #endMock
90 | Mock -CommandName Confirm-MetadataUpdate -MockWith {
91 | $false
92 | } #endMock
93 | Confirm-XMLDataSet | Should -BeExactly $false
94 | } #it
95 |
96 | It 'should check the metadata file if the data file is greater than 9 days old' {
97 | Mock -CommandName Get-Date -MockWith {
98 | [datetime]'1/16/20 21:17:22'
99 | } #endMock
100 | Confirm-XMLDataSet
101 | Should -Invoke -CommandName Confirm-MetadataUpdate -Exactly 1
102 | } #it
103 |
104 | } #context_Success
105 |
106 | } #describe_Confirm-XMLDataSet
107 |
108 | } #inModule
109 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Expand-XMLDataSet.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Expand-XMLDataSet' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | } #before_all
21 |
22 | BeforeEach {
23 | Mock -CommandName Test-Path -MockWith {
24 | $false
25 | } #endMock
26 | Mock -CommandName Remove-Item -MockWith {
27 |
28 | } #endMock
29 | Mock -CommandName Expand-Archive -MockWith {
30 | [PSCustomObject]@{
31 | Name = 'AzModI.xml'
32 | Exists = 'True'
33 | CreationTime = [datetime]'01 / 06 / 20 23:02:16'
34 | }
35 | } #endMock
36 | } #before_each
37 |
38 | Context 'Error' {
39 |
40 | It 'should return false if an error is encountered with Test-Path' {
41 | Mock -CommandName Test-Path -MockWith {
42 | throw 'FakeError'
43 | } #endMock
44 | Expand-XMLDataSet | Should -BeExactly $false
45 | } #it
46 |
47 | It 'should return false if an error is encountered with Remove-Item' {
48 | Mock -CommandName Test-Path -MockWith {
49 | $true
50 | } #endMock
51 | Mock -CommandName Remove-Item -MockWith {
52 | throw 'FakeError'
53 | } #endMock
54 | Expand-XMLDataSet | Should -BeExactly $false
55 | } #it
56 |
57 | It 'should return false if an error is encountered with Expand-Archive' {
58 | Mock -CommandName Expand-Archive -MockWith {
59 | throw 'FakeError'
60 | } #endMock
61 | Expand-XMLDataSet | Should -BeExactly $false
62 | } #it
63 |
64 | } #context_Error
65 |
66 | Context 'Success' {
67 |
68 | It 'should return true if the data file is expanded' {
69 | Expand-XMLDataSet | Should -BeExactly $true
70 | } #it
71 |
72 | } #context_Success
73 |
74 | } #describe_Expand-XMLDataSet
75 |
76 | } #inModule
77 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Get-RemoteFile.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Get-RemoteFile' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | $fileName = 'test.zip'
21 | } #before_all
22 |
23 | BeforeEach {
24 | Mock -CommandName Invoke-WebRequest -MockWith {
25 | [PSCustomObject]@{
26 | StatusCode = '200'
27 | StatusDescription = 'OK'
28 | Content = '{80, 75, 3, 4}'
29 | }
30 | } #endMock
31 | } #before_each
32 |
33 | Context 'Error' {
34 |
35 | It 'should return false if an error is encountered downloading the file' {
36 | Mock -CommandName Invoke-WebRequest -MockWith {
37 | throw 'FakeError'
38 | } #endMock
39 | Get-RemoteFile -File $fileName | Should -BeExactly $false
40 | } #it
41 |
42 | } #context_FunctionName
43 |
44 | Context 'Success' {
45 |
46 | It 'should return true if the file is downloaded' {
47 | Get-RemoteFile -File $fileName | Should -BeExactly $true
48 | } #it
49 |
50 | It 'should call Invoke-WebRequest with the correct parameters' {
51 | $outPath = [System.IO.Path]::Combine($script:dataPath, $fileName)
52 | Get-RemoteFile -File $fileName
53 | Should -Invoke -CommandName Invoke-WebRequest -Times 1 -Exactly -Scope It -ParameterFilter {
54 | $OutFile -eq $outPath -and $Uri -eq "https://$script:dlURI/$fileName"
55 | }
56 | } #it
57 |
58 | It 'should call Invoke-WebRequest with the correct parameters if OutFileName is specified' {
59 | $fileNameOverride = 'test2.zip'
60 | $outPath = [System.IO.Path]::Combine($script:dataPath, $fileNameOverride)
61 | Get-RemoteFile -File $fileName -OutFileName $fileNameOverride
62 | Should -Invoke -CommandName Invoke-WebRequest -Times 1 -Exactly -Scope It -ParameterFilter {
63 | $OutFile -eq $outPath -and $Uri -eq "https://$script:dlURI/$fileName"
64 | }
65 | } #it
66 |
67 | } #context_Success
68 |
69 | } #describe_Get-RemoteFile
70 |
71 | } #inModule
72 |
--------------------------------------------------------------------------------
/src/Tests/Unit/Private/Invoke-XMLDataCheck.Tests.ps1:
--------------------------------------------------------------------------------
1 | #-------------------------------------------------------------------------
2 | Set-Location -Path $PSScriptRoot
3 | #-------------------------------------------------------------------------
4 | $ModuleName = 'PSGalleryExplorer'
5 | $PathToManifest = [System.IO.Path]::Combine('..', '..', '..', $ModuleName, "$ModuleName.psd1")
6 | #-------------------------------------------------------------------------
7 | if (Get-Module -Name $ModuleName -ErrorAction 'SilentlyContinue') {
8 | #if the module is already in memory, remove it
9 | Remove-Module -Name $ModuleName -Force
10 | }
11 | Import-Module $PathToManifest -Force
12 | #-------------------------------------------------------------------------
13 |
14 | InModuleScope 'PSGalleryExplorer' {
15 |
16 | Describe 'Invoke-XMLDataCheck' -Tag Unit {
17 | BeforeAll {
18 | $WarningPreference = 'SilentlyContinue'
19 | $ErrorActionPreference = 'SilentlyContinue'
20 | function Confirm-DataLocation {
21 | }
22 | function Confirm-XMLDataSet {
23 | }
24 | function Expand-XMLDataSet {
25 | }
26 | function Get-RemoteFile {
27 | }
28 | function Remove-Item {
29 | }
30 | } #before_all
31 |
32 | Context 'ShouldProcess' {
33 | BeforeEach {
34 | Mock -CommandName Invoke-XMLDataCheck -MockWith { } #endMock
35 | } #before_each
36 | It 'Should process by default' {
37 | Invoke-XMLDataCheck
38 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 1
39 | } #it
40 | It 'Should not process on explicit request for confirmation (-Confirm)' {
41 | { Invoke-XMLDataCheck -Confirm }
42 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 0
43 | } #it
44 | It 'Should not process on implicit request for confirmation (ConfirmPreference)' {
45 | {
46 | $ConfirmPreference = 'Low'
47 | Invoke-XMLDataCheck
48 | }
49 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 0
50 | } #it
51 | It 'Should not process on explicit request for validation (-WhatIf)' {
52 | { Invoke-XMLDataCheck -WhatIf }
53 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 0
54 | } #it
55 | It 'Should not process on implicit request for validation (WhatIfPreference)' {
56 | {
57 | $WhatIfPreference = $true
58 | Invoke-XMLDataCheck
59 | }
60 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 0
61 | } #it
62 | It 'Should process on force' {
63 | $ConfirmPreference = 'Medium'
64 | Invoke-XMLDataCheck -Force
65 | Should -Invoke Invoke-XMLDataCheck -Scope It -Exactly -Times 1
66 | } #it
67 | } #context_ShouldProcess
68 |
69 | BeforeEach {
70 | Mock -CommandName Confirm-DataLocation -MockWith {
71 | $true
72 | } #endMock
73 | Mock -CommandName Confirm-XMLDataSet -MockWith {
74 | $true
75 | } #endMock
76 | Mock -CommandName Expand-XMLDataSet -MockWith {
77 | $true
78 | } #endMock
79 | Mock -CommandName Get-RemoteFile -MockWith {
80 | $true
81 | } #endMock
82 | Mock -CommandName Test-Path -MockWith {
83 | $true
84 | } #endMock
85 | Mock -CommandName Remove-Item -MockWith {}
86 | } #before_each
87 |
88 | Context 'Success' {
89 |
90 | It 'should return true if the data file is confirmed' {
91 | Invoke-XMLDataCheck -Force | Should -BeExactly $true
92 | } #it
93 |
94 | It 'should return false if the data output dir cannot be confirmed' {
95 | Mock -CommandName Confirm-DataLocation -MockWith {
96 | $false
97 | } #endMock
98 | Invoke-XMLDataCheck -Force | Should -BeExactly $false
99 | } #it
100 |
101 | It 'should return false if the data file is not confirmed and the file can not be downloaded' {
102 | Mock -CommandName Confirm-XMLDataSet -MockWith {
103 | $false
104 | } #endMock
105 | Mock -CommandName Get-RemoteFile -MockWith {
106 | $false
107 | } #endMock
108 | Invoke-XMLDataCheck -Force | Should -BeExactly $false
109 | } #it
110 |
111 | It 'should return false if the data file is not confirmed and the file is downloaded, but can not be expanded' {
112 | Mock -CommandName Confirm-XMLDataSet -MockWith {
113 | $false
114 | } #endMock
115 | Mock -CommandName Expand-XMLDataSet -MockWith {
116 | $false
117 | } #endMock
118 | Invoke-XMLDataCheck -Force | Should -BeExactly $false
119 | } #it
120 |
121 | It 'should return true if the data file is not confirmed and the file is downloaded and expanded' {
122 | Mock -CommandName Confirm-XMLDataSet -MockWith {
123 | $false
124 | } #endMock
125 | Invoke-XMLDataCheck -Force | Should -BeExactly $true
126 | } #it
127 |
128 | It 'should download 2 files if the data file is not confirmed' {
129 | Mock -CommandName Confirm-XMLDataSet -MockWith {
130 | $false
131 | } #endMock
132 | Invoke-XMLDataCheck -Force
133 | Should -Invoke Get-RemoteFile -Scope It -Exactly -Times 2
134 | } #it
135 |
136 | It 'should not attempt to remove the metadata file if it does not exist' {
137 | Mock -CommandName Confirm-XMLDataSet -MockWith {
138 | $false
139 | } #endMock
140 | Mock -CommandName Test-Path -MockWith {
141 | $false
142 | } #endMock
143 | Invoke-XMLDataCheck -Force
144 | Should -Invoke Remove-Item -Scope It -Exactly -Times 0
145 | } #it
146 |
147 | } #context_Success
148 |
149 | } #describe_Invoke-XMLDataCheck
150 |
151 | } #inModule
152 |
--------------------------------------------------------------------------------