Welcome to the Chocolatey Community Package Repository! The packages found in this section of the site are provided, maintained, and moderated by the community.
Moderation
Every version of each package undergoes a rigorous moderation process before it goes live that typically includes:
- Security, consistency, and quality checking
- Installation testing
- Virus checking through VirusTotal
- Human moderators who give final review and sign off
More detail at Security and Moderation.
Organizational Use
If you are an organization using Chocolatey, we want your experience to be fully reliable. Due to the nature of this publicly offered repository, reliability cannot be guaranteed. Packages offered here are subject to distribution rights, which means they may need to reach out further to the internet to the official locations to download files at runtime.
Fortunately, distribution rights do not apply for internal use. With any edition of Chocolatey (including the free open source edition), you can host your own packages and cache or internalize existing community packages.
Disclaimer
Your use of the packages on this site means you understand they are not supported or guaranteed in any way. Learn more...
-
STEP1
Package Review
-
STEP2
Integration Method
-
STEP3
Internal Repo Url
-
STEP4
Environment Setup
-
STEP5
Install Script
Step 1: Review Your Packages
Step 2: Choose Your Integration Method
Step 3: Enter Your Internal Repository Url
(this should look similar to https://community.chocolatey.org/api/v2/)
Step 3: Copy Your Script or Download Config
Option 1: Copy Script
Option 2: Download Config
Step 4: Setup Your Environment
1. Ensure you are set for organizational deployment
Please see the organizational deployment guide
2. Get the package into your environment
Option 1: Cached Package (Unreliable, Requires Internet - Same As Community)-
Open Source or Commercial:
- Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
-
You can also just download the packages and push them to a repository
Download Packages
-
Open Source
-
Download the packages:
Download Packages - Follow manual internalization instructions
-
-
Package Internalizer (C4B)
-
Run: (additional options)
-
For package and dependencies run:
- Automate package internalization
-
Run: (additional options)
Step 5: Copy Your Script
See options you can pass to upgrade.
See best practices for scripting.
Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.
If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:
## 1. REQUIREMENTS ##
### Here are the requirements necessary to ensure this is successful.
### a. Internal/Private Cloud Repository Set Up ###
#### You'll need an internal/private cloud repository you can use. These are
#### generally really quick to set up and there are quite a few options.
#### Chocolatey Software recommends Nexus, Artifactory Pro, or ProGet as they
#### are repository servers and will give you the ability to manage multiple
#### repositories and types from one server installation.
### b. Download Chocolatey Package and Put on Internal Repository ###
#### You need to have downloaded the Chocolatey package as well.
#### Please see https://chocolatey.org/install#organization
### c. Other Requirements ###
#### We initialize a few things that are needed by this script - there are no other requirements.
$ErrorActionPreference = "Stop"
#### Set TLS 1.2 (3072) as that is the minimum required by various up-to-date repositories.
#### Use integers because the enumeration value for TLS 1.2 won't exist
#### in .NET 4.0, even though they are addressable if .NET 4.5+ is
#### installed (.NET 4.5 is an in-place upgrade).
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
#### We use this variable for future REST calls.
$RequestArguments = @{
UseBasicParsing = $true
}
## 2. TOP LEVEL VARIABLES ##
### a. Your internal repository url (the main one). ###
#### Should be similar to what you see when you browse
#### to https://community.chocolatey.org/api/v2/
$NugetRepositoryUrl = "INTERNAL REPO URL"
### b. Internal Repository Credential ###
#### If required, add the repository access credential here
# $NugetRepositoryCredential = [PSCredential]::new(
# "username",
# ("password" | ConvertTo-SecureString -AsPlainText -Force)
# )
# $RequestArguments.Credential = $NugetRepositoryCredential
### c. Chocolatey nupkg download url ###
#### This url should result in an immediate download when you navigate to it
$ChocolateyDownloadUrl = "$($NugetRepositoryUrl.TrimEnd('/'))/package/chocolatey.1.1.0.nupkg"
### d. Chocolatey Central Management (CCM) ###
#### If using CCM to manage Chocolatey, add the following:
#### i. Endpoint URL for CCM
# $ChocolateyCentralManagementUrl = "https://chocolatey-central-management:24020/ChocolateyManagementService"
#### ii. If using a Client Salt, add it here
# $ChocolateyCentralManagementClientSalt = "clientsalt"
#### iii. If using a Service Salt, add it here
# $ChocolateyCentralManagementServiceSalt = "servicesalt"
## 3. ENSURE CHOCOLATEY IS INSTALLED ##
### Ensure Chocolatey is installed from your internal repository
#### Download the Nupkg, appending .zip to the filename to handle archive cmdlet limitations
if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) {
$TempDirectory = Join-Path $env:Temp "chocolateyInstall"
if (-not (Test-Path $TempDirectory -PathType Container)) {
$null = New-Item -Path $TempDirectory -ItemType Directory
}
$DownloadedNupkg = Join-Path $TempDirectory "$(Split-Path $ChocolateyDownloadUrl -Leaf).zip"
Invoke-WebRequest -Uri $ChocolateyDownloadUrl -OutFile $DownloadedNupkg @RequestArguments
#### Extract the Nupkg, and run the chocolateyInstall script
if (Get-Command Microsoft.PowerShell.Archive\Expand-Archive -ErrorAction SilentlyContinue) {
Microsoft.PowerShell.Archive\Expand-Archive -Path $DownloadedNupkg -DestinationPath $TempDirectory -Force
} else {
# PowerShell versions <4.0 do not have this function available
try {
$shellApplication = New-Object -ComObject Shell.Application
$zipPackage = $shellApplication.NameSpace($DownloadedNupkg)
$destinationFolder = $shellApplication.NameSpace($TempDirectory)
$destinationFolder.CopyHere($zipPackage.Items(), 0x10)
} catch {
Write-Warning "Unable to unzip package using built-in compression."
throw $_
}
}
& $(Join-Path $TempDirectory "tools\chocolateyInstall.ps1")
}
if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) {
refreshenv
}
## 4. CONFIGURE CHOCOLATEY BASELINE ##
### a. FIPS Feature ###
#### If you need FIPS compliance - make this the first thing you configure
#### before you do any additional configuration or package installations
# choco feature enable -n useFipsCompliantChecksums
### b. Apply Recommended Configuration ###
#### Move cache location so Chocolatey is very deterministic about
#### cleaning up temporary data and the location is secured to admins
choco config set --name cacheLocation --value C:\ProgramData\chocolatey\cache
#### Increase timeout to at least 4 hours
choco config set --name commandExecutionTimeoutSeconds --value 14400
#### Turn off download progress when running choco through integrations
choco feature disable --name showDownloadProgress
### c. Sources ###
#### Remove the default community package repository source
choco source list --limitoutput | ConvertFrom-Csv -Header 'Name', 'Location' -Delimiter '|' | ForEach-Object {
if ($_.Location -eq 'https://community.chocolatey.org/api/v2/') {
choco source remove -n $_.Name
}
}
#### Add internal default sources
#### You could have multiple sources here, so we will provide an example
#### of one using the remote repo variable here
#### NOTE: This EXAMPLE may require changes
if ($NugetRepositoryCredential) {
choco source add --name ChocolateyInternal --source $NugetRepositoryUrl --user $NugetRepositoryCredential.UserName --password $NugetRepositoryCredential.GetNetworkCredential().Password --priority 1
} else {
choco source add --name ChocolateyInternal --source $NugetRepositoryUrl --priority 1
}
### b. Keep Chocolatey Up To Date ###
#### Keep chocolatey up to date based on your internal source
#### You control the upgrades based on when you push an updated version
#### to your internal repository.
#### Note the source here is to the OData feed, similar to what you see
#### when you browse to https://community.chocolatey.org/api/v2/
choco upgrade chocolatey --confirm
## 5. ENSURE CHOCOLATEY FOR BUSINESS ##
### If you don't have Chocolatey for Business (C4B), you'll want to remove from here down.
### a. Ensure The License File Is Installed ###
#### Create a license package using script from https://docs.chocolatey.org/en-us/how-tos/setup-offline-installation#exercise-4-create-a-package-for-the-license
choco install chocolatey-license --source $NugetRepositoryUrl --confirm
### b. Disable The Licensed Source ###
#### The licensed source cannot be removed, so it must be disabled.
#### This must occur after the license has been set by the license package.
if ("chocolatey-license" -in (choco list --localonly --limitoutput | ConvertFrom-Csv -Header "Name" -Delimiter "|").Name) {
choco source disable --name chocolatey.licensed
} else {
Write-Warning "Not disabling 'chocolatey.licensed' feed, as Chocolatey-License has not been installed."
}
### c. Ensure Chocolatey Licensed Extension ###
#### You will have downloaded the licensed extension to your internal repository
#### as you have disabled the licensed repository in step 5b.
#### Ensure the chocolatey.extension package (aka Chocolatey Licensed Extension)
if ("chocolatey-license" -in (choco list --localonly --limitoutput | ConvertFrom-Csv -Header "Name" -Delimiter "|").Name) {
choco install chocolatey.extension --source $NugetRepositoryUrl --confirm
} else {
Write-Warning "Not installing 'chocolatey.extension', as Chocolatey-License has not been installed."
}
#### The Chocolatey Licensed Extension unlocks all of the following, which also have configuration/feature items available with them. You may want to visit the feature pages to see what you might want to also enable:
#### - Package Builder - https://docs.chocolatey.org/en-us/features/paid/package-builder
#### - Package Internalizer - https://docs.chocolatey.org/en-us/features/paid/package-internalizer
#### - Package Synchronization (3 components) - https://docs.chocolatey.org/en-us/features/paid/package-synchronization
#### - Package Reducer - https://docs.chocolatey.org/en-us/features/paid/package-reducer
#### - Package Audit - https://docs.chocolatey.org/en-us/features/paid/package-audit
#### - Package Throttle - https://docs.chocolatey.org/en-us/features/paid/package-throttle
#### - CDN Cache Access - https://docs.chocolatey.org/en-us/features/paid/private-cdn
#### - Branding - https://docs.chocolatey.org/en-us/features/paid/branding
#### - Self-Service Anywhere (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/self-service-anywhere
#### - Chocolatey Central Management (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/chocolatey-central-management
#### - Other - https://docs.chocolatey.org/en-us/features/paid/
### d. Ensure Self-Service Anywhere ###
#### If you have desktop clients where users are not administrators, you may
#### to take advantage of deploying and configuring Self-Service anywhere
choco feature disable --name showNonElevatedWarnings
choco feature enable --name useBackgroundService
choco feature enable --name useBackgroundServiceWithNonAdministratorsOnly
choco feature enable --name allowBackgroundServiceUninstallsFromUserInstallsOnly
choco config set --name allowedBackgroundServiceCommands --value "install,upgrade,uninstall"
### e. Ensure Chocolatey Central Management ###
#### If you want to manage and report on endpoints, you can set up and configure
### Central Management. There are multiple portions to manage, so you'll see
### a section on agents here along with notes on how to configure the server
### side components.
if ($ChocolateyCentralManagementUrl) {
choco install chocolatey-agent --source $NugetRepositoryUrl --confirm
choco config set --name CentralManagementServiceUrl --value $ChocolateyCentralManagementUrl
if ($ChocolateyCentralManagementClientSalt) {
choco config set --name centralManagementClientCommunicationSaltAdditivePassword --value $ChocolateyCentralManagementClientSalt
}
if ($ChocolateyCentralManagementServiceSalt) {
choco config set --name centralManagementServiceCommunicationSaltAdditivePassword --value $ChocolateyCentralManagementServiceSalt
}
choco feature enable --name useChocolateyCentralManagement
choco feature enable --name useChocolateyCentralManagementDeployments
}
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
If Applicable - Chocolatey Configuration/Installation
## 1. REQUIREMENTS ##
### Here are the requirements necessary to ensure this is successful.
### a. Internal/Private Cloud Repository Set Up ###
#### You'll need an internal/private cloud repository you can use. These are
#### generally really quick to set up and there are quite a few options.
#### Chocolatey Software recommends Nexus, Artifactory Pro, or ProGet as they
#### are repository servers and will give you the ability to manage multiple
#### repositories and types from one server installation.
### b. Download Chocolatey Package and Put on Internal Repository ###
#### You need to have downloaded the Chocolatey package as well.
#### Please see https://chocolatey.org/install#organization
### c. Other Requirements ###
#### i. chocolatey.chocolatey
##### You will require the chocolatey.chocolatey collection to be installed
##### on all machines using this playbook.
##### Please see https://github.com/chocolatey/chocolatey-ansible/#installing-the-collection-from-ansible-galaxy
- name: Install and Configure Chocolatey
hosts: all
## 2. TOP LEVEL VARIABLES ##
vars:
### a. Your internal repository url (the main one). ###
#### Should be similar to what you see when you browse
#### to https://community.chocolatey.org/api/v2/
nuget_repository_url: INTERNAL REPO URL
### b. Internal Repository Credential ###
#### If required, add the repository access credential here and
#### uncomment lines with source_username and source_password below
# nuget_repository_username: username
# nuget_repository_password: password
### c. Chocolatey Central Management (CCM) ###
#### If using CCM to manage Chocolatey, add the following:
#### i. Endpoint URL for CCM
# chocolatey_central_management_url: https://chocolatey-central-management:24020/ChocolateyManagementService
#### ii. If using a Client Salt, add it here
# chocolatey_central_management_client_salt: clientsalt
#### iii. If using a Service Salt, add it here
# chocolatey_central_management_service_salt: servicesalt
## 3. ENSURE CHOCOLATEY IS INSTALLED ##
### Ensure Chocolatey is installed from your internal repository
tasks:
- name: Install chocolatey
win_chocolatey:
name: chocolatey
source: {{ nuget_repository_url }}
# source_username: {{ nuget_repository_username }}
# source_password: {{ nuget_repository_password }}
## 4. CONFIGURE CHOCOLATEY BASELINE ##
### a. FIPS Feature ###
#### If you need FIPS compliance - make this the first thing you configure
#### before you do any additional configuration or package installations
# - name: Enable FIPS compliance
# win_chocolatey_feature:
# name: useFipsCompliantChecksums
# state: enabled
### b. Apply Recommended Configuration ###
#### Move cache location so Chocolatey is very deterministic about
#### cleaning up temporary data and the location is secured to admins
- name: Set the cache location
win_chocolatey_config:
name: cacheLocation
state: present
value: C:\ProgramData\chocolatey\cache
#### Increase timeout to at least 4 hours
- name: Set the command execution timeout
win_chocolatey_config:
name: commandExecutionTimeoutSeconds
state: present
value: 14400
#### Turn off download progress when running choco through integrations
- name: Disable showing download progress
win_chocolatey_feature:
name: showDownloadProgress
state: disabled
### c. Sources ###
#### Remove the default community package repository source
- name: Remove Chocolatey Community Repository
win_chocolatey_source:
name: chocolatey
state: absent
#### Add internal default sources
#### You could have multiple sources here, so we will provide an example
#### of one using the remote repo variable here
#### NOTE: This EXAMPLE may require changes
- name: Add Internal Repository
win_chocolatey_source:
name: ChocolateyInternal
state: present
source: {{ nuget_repository_url }}
# source_username: {{ nuget_repository_username }}
# source_password: {{ nuget_repository_password }}
priority: 1
### b. Keep Chocolatey Up To Date ###
#### Keep chocolatey up to date based on your internal source
#### You control the upgrades based on when you push an updated version
#### to your internal repository.
#### Note the source here is to the OData feed, similar to what you see
#### when you browse to https://community.chocolatey.org/api/v2/
- name: Upgrade Chocolatey
win_chocolatey:
name: chocolatey
state: latest
## 5. ENSURE CHOCOLATEY FOR BUSINESS ##
### If you don't have Chocolatey for Business (C4B), you'll want to remove from here down.
### a. Ensure The License File Is Installed ###
#### Create a license package using script from https://docs.chocolatey.org/en-us/how-tos/setup-offline-installation#exercise-4-create-a-package-for-the-license
- name: Install Chocolatey License
win_chocolatey:
name: chocolatey-license
source: ChocolateyInternal
state: latest
### b. Disable The Licensed Source ###
#### The licensed source cannot be removed, so it must be disabled.
#### This must occur after the license has been set by the license package.
- name: Disable Chocolatey Community Repository
win_chocolatey_source:
name: chocolatey.licensed
state: disabled
### c. Ensure Chocolatey Licensed Extension ###
#### You will have downloaded the licensed extension to your internal repository
#### as you have disabled the licensed repository in step 5b.
#### Ensure the chocolatey.extension package (aka Chocolatey Licensed Extension)
- name: Install Chocolatey Extension
win_chocolatey:
name: chocolatey.extension
source: ChocolateyInternal
state: latest
#### The Chocolatey Licensed Extension unlocks all of the following, which also have configuration/feature items available with them. You may want to visit the feature pages to see what you might want to also enable:
#### - Package Builder - https://docs.chocolatey.org/en-us/features/paid/package-builder
#### - Package Internalizer - https://docs.chocolatey.org/en-us/features/paid/package-internalizer
#### - Package Synchronization (3 components) - https://docs.chocolatey.org/en-us/features/paid/package-synchronization
#### - Package Reducer - https://docs.chocolatey.org/en-us/features/paid/package-reducer
#### - Package Audit - https://docs.chocolatey.org/en-us/features/paid/package-audit
#### - Package Throttle - https://docs.chocolatey.org/en-us/features/paid/package-throttle
#### - CDN Cache Access - https://docs.chocolatey.org/en-us/features/paid/private-cdn
#### - Branding - https://docs.chocolatey.org/en-us/features/paid/branding
#### - Self-Service Anywhere (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/self-service-anywhere
#### - Chocolatey Central Management (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/chocolatey-central-management
#### - Other - https://docs.chocolatey.org/en-us/features/paid/
### d. Ensure Self-Service Anywhere ###
#### If you have desktop clients where users are not administrators, you may
#### to take advantage of deploying and configuring Self-Service anywhere
- name: Hide not-elevated warnings
win_chocolatey_feature:
name: showNonElevatedWarnings
state: disabled
- name: Use background mode for self-service
win_chocolatey_feature:
name: useBackgroundService
state: enabled
- name: Use background service for non-admins
win_chocolatey_feature:
name: useBackgroundServiceWithNonAdministratorsOnly
state: enabled
- name: Allow background uninstallation for user installs
win_chocolatey_feature:
name: allowBackgroundServiceUninstallsFromUserInstallsOnly
state: enabled
- name: Set allowed background service commands
win_chocolatey_config:
name: backgroundServiceAllowedCommands
state: present
value: install,upgrade,uninstall
### e. Ensure Chocolatey Central Management ###
#### If you want to manage and report on endpoints, you can set up and configure
### Central Management. There are multiple portions to manage, so you'll see
### a section on agents here along with notes on how to configure the server
### side components.
- name: Install Chocolatey Agent
when: chocolatey_central_management_url is defined
win_chocolatey:
name: chocolatey-agent
source: ChocolateyInternal
state: latest
- name: Set the Central Management Service URL
when: chocolatey_central_management_url is defined
win_chocolatey_config:
name: CentralManagementServiceUrl
state: present
value: {{ chocolatey_central_management_url }}
- name: Set the Central Management Client Salt
when: chocolatey_central_management_client_salt is defined
win_chocolatey_config:
name: centralManagementClientCommunicationSaltAdditivePassword
state: present
value: {{ chocolatey_central_management_client_salt }}
- name: Set the Central Management Service Salt
when: chocolatey_central_management_service_salt is defined
win_chocolatey_config:
name: centralManagementServiceCommunicationSaltAdditivePassword
state: present
value: {{ chocolatey_central_management_service_salt }}
- name: Use Central Management
when: chocolatey_central_management_url is defined
win_chocolatey_feature:
name: useChocolateyCentralManagement
state: enabled
- name: Use Central Management Deployments
when: chocolatey_central_management_url is defined
win_chocolatey_feature:
name: useChocolateyCentralManagementDeployments
state: enabled
See docs at https://docs.chef.io/resource_chocolatey_package.html.
If Applicable - Chocolatey Configuration/Installation
## 1. REQUIREMENTS ##
### Here are the requirements necessary to ensure this is successful.
### a. Internal/Private Cloud Repository Set Up ###
#### You'll need an internal/private cloud repository you can use. These are
#### generally really quick to set up and there are quite a few options.
#### Chocolatey Software recommends Nexus, Artifactory Pro, or ProGet as they
#### are repository servers and will give you the ability to manage multiple
#### repositories and types from one server installation.
### b. Download Chocolatey Package and Put on Internal Repository ###
#### You need to have downloaded the Chocolatey package as well.
#### Please see https://chocolatey.org/install#organization
### c. Other Requirements ###
#### The Chocolatey resources are available with any recent version of Chef.
#### We utilise the Chocolatey recipe to install the Chocolatey binaries.
include_recipe "chocolatey"
## 2. TOP LEVEL VARIABLES ##
### a. Your internal repository url (the main one). ###
#### Should be similar to what you see when you browse
#### to https://community.chocolatey.org/api/v2/
NugetRepositoryUrl = "INTERNAL REPO URL"
### b. Internal Repository Credential ###
#### If required, add the repository access credential here
# NugetRepositoryUsername = "username"
# NugetRepositoryPassword = "password"
### c. Chocolatey nupkg download url ###
#### This url should result in an immediate download when you navigate to it in
#### a web browser
ChocolateyNupkgUrl = "INTERNAL REPO URL/package/chocolatey.1.1.0.nupkg",
### d. Chocolatey Central Management (CCM) ###
#### If using CCM to manage Chocolatey, add the following:
#### i. Endpoint URL for CCM
# ChocolateyCentralManagementUrl = "https://chocolatey-central-management:24020/ChocolateyManagementService"
#### ii. If using a Client Salt, add it here
# ChocolateyCentralManagementClientSalt = "clientsalt"
#### iii. If using a Service Salt, add it here
# ChocolateyCentralManagementServiceSalt = "servicesalt"
## 3. ENSURE CHOCOLATEY IS INSTALLED ##
### Ensure Chocolatey is installed from your internal repository
node['chocolatey']['install vars'] = {
'chocolateyDownloadUrl' => "#{ChocolateyNupkgUrl}",
}
## 4. CONFIGURE CHOCOLATEY BASELINE ##
### a. FIPS Feature ###
#### If you need FIPS compliance - make this the first thing you configure
#### before you do any additional configuration or package installations
# chocolatey_feature 'useFipsCompliantChecksums' do
# action :enable
# end
### b. Apply Recommended Configuration ###
#### Move cache location so Chocolatey is very deterministic about
#### cleaning up temporary data and the location is secured to admins
chocolatey_config 'cacheLocation' do
value 'C:\ProgramData\chocolatey\cache'
end
#### Increase timeout to at least 4 hours
chocolatey_config 'commandExecutionTimeoutSeconds' do
value '14400'
end
#### Turn off download progress when running choco through integrations
chocolatey_feature 'showDownloadProgress' do
action :disable
end
### c. Sources ###
#### Remove the default community package repository source
chocolatey_source 'chocolatey' do
action :remove
end
#### Add internal default sources
#### You could have multiple sources here, so we will provide an example
#### of one using the remote repo variable here
#### NOTE: This EXAMPLE may require changes
chocolatey_source 'ChocolateyInternal' do
source "#{NugetRepositoryUrl}"
priority 1
action :add
end
execute 'ChocolateyInternal' do
command "choco source add --name ChocolateyInternal -s #{NugetRepositoryUrl} -u=#{NugetRepositoryUsername} -p=#{NugetRepositoryPassword} --priority=1"
only_if { NugetRepositoryUsername != nil || NugetRepositoryPassword != nil }
end
### b. Keep Chocolatey Up To Date ###
#### Keep chocolatey up to date based on your internal source
#### You control the upgrades based on when you push an updated version
#### to your internal repository.
#### Note the source here is to the OData feed, similar to what you see
#### when you browse to https://community.chocolatey.org/api/v2/
chocolatey_package 'chocolatey' do
action :upgrade
source "#{NugetRepositoryUrl}"
end
## 5. ENSURE CHOCOLATEY FOR BUSINESS ##
### If you don't have Chocolatey for Business (C4B), you'll want to remove from here down.
### a. Ensure The License File Is Installed ###
#### Create a license package using script from https://docs.chocolatey.org/en-us/how-tos/setup-offline-installation#exercise-4-create-a-package-for-the-license
chocolatey_package 'chocolatey-license' do
action :install
source "#{NugetRepositoryUrl}"
end
### b. Disable The Licensed Source ###
#### The licensed source cannot be removed, so it must be disabled.
#### This must occur after the license has been set by the license package.
chocolatey_source 'chocolatey.licensed' do
action :disable
end
### c. Ensure Chocolatey Licensed Extension ###
#### You will have downloaded the licensed extension to your internal repository
#### as you have disabled the licensed repository in step 5b.
#### Ensure the chocolatey.extension package (aka Chocolatey Licensed Extension)
chocolatey_package 'chocolatey.extention' do
action install
source "#{NugetRepositoryUrl}"
end
#### The Chocolatey Licensed Extension unlocks all of the following, which also have configuration/feature items available with them. You may want to visit the feature pages to see what you might want to also enable:
#### - Package Builder - https://docs.chocolatey.org/en-us/features/paid/package-builder
#### - Package Internalizer - https://docs.chocolatey.org/en-us/features/paid/package-internalizer
#### - Package Synchronization (3 components) - https://docs.chocolatey.org/en-us/features/paid/package-synchronization
#### - Package Reducer - https://docs.chocolatey.org/en-us/features/paid/package-reducer
#### - Package Audit - https://docs.chocolatey.org/en-us/features/paid/package-audit
#### - Package Throttle - https://docs.chocolatey.org/en-us/features/paid/package-throttle
#### - CDN Cache Access - https://docs.chocolatey.org/en-us/features/paid/private-cdn
#### - Branding - https://docs.chocolatey.org/en-us/features/paid/branding
#### - Self-Service Anywhere (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/self-service-anywhere
#### - Chocolatey Central Management (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/chocolatey-central-management
#### - Other - https://docs.chocolatey.org/en-us/features/paid/
### d. Ensure Self-Service Anywhere ###
#### If you have desktop clients where users are not administrators, you may
#### to take advantage of deploying and configuring Self-Service anywhere
chocolatey_feature 'showNonElevatedWarnings' do
action :disable
end
chocolatey_feature 'useBackgroundService' do
action :enable
end
chocolatey_feature 'useBackgroundServiceWithNonAdministratorsOnly' do
action :enable
end
chocolatey_feature 'allowBackgroundServiceUninstallsFromUserInstallsOnly' do
action :enable
end
chocolatey_config 'backgroundServiceAllowedCommands' do
value 'install,upgrade,uninstall'
end
### e. Ensure Chocolatey Central Management ###
#### If you want to manage and report on endpoints, you can set up and configure
### Central Management. There are multiple portions to manage, so you'll see
### a section on agents here along with notes on how to configure the server
### side components.
chocolatey_package 'chocolatey-agent' do
action install
source "#{NugetRepositoryUrl}"
# user "#{NugetRepositoryUsername}"
# password "#{NugetRepositoryPassword}"
only_if { ChocolateyCentralManagementUrl != nil }
end
chocolatey_config 'CentralManagementServiceUrl' do
value "#{ChocolateyCentralManagementUrl}"
only_if { ChocolateyCentralManagementUrl != nil }
end
chocolatey_config 'centralManagementClientCommunicationSaltAdditivePassword' do
value "#{ChocolateyCentralManagementClientSalt}"
only_if { ChocolateyCentralManagementClientSalt != nil }
end
chocolatey_config 'centralManagementServiceCommunicationSaltAdditivePassword' do
value "#{ChocolateyCentralManagementServiceSalt}"
only_if { ChocolateyCentralManagementServiceSalt != nil }
end
chocolatey_feature 'useChocolateyCentralManagement' do
action :enable
only_if { ChocolateyCentralManagementUrl != nil }
end
chocolatey_feature 'useChocolateyCentralManagementDeployments' do
action :enable
only_if { ChocolateyCentralManagementUrl != nil }
end
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
If Applicable - Chocolatey Configuration/Installation
#requires -Modules cChoco
## 1. REQUIREMENTS ##
### Here are the requirements necessary to ensure this is successful.
### a. Internal/Private Cloud Repository Set Up ###
#### You'll need an internal/private cloud repository you can use. These are
#### generally really quick to set up and there are quite a few options.
#### Chocolatey Software recommends Nexus, Artifactory Pro, or ProGet as they
#### are repository servers and will give you the ability to manage multiple
#### repositories and types from one server installation.
### b. Download Chocolatey Package and Put on Internal Repository ###
#### You need to have downloaded the Chocolatey package as well.
#### Please see https://chocolatey.org/install#organization
### c. Other Requirements ###
#### i. Requires chocolatey\cChoco DSC module to be installed on the machine compiling the DSC manifest
#### NOTE: This will need to be installed before running the DSC portion of this script
if (-not (Get-Module cChoco -ListAvailable)) {
$null = Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
if (($PSGallery = Get-PSRepository -Name PSGallery).InstallationPolicy -ne "Trusted") {
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
}
Install-Module -Name cChoco
if ($PSGallery.InstallationPolicy -ne "Trusted") {
Set-PSRepository -Name PSGallery -InstallationPolicy $PSGallery.InstallationPolicy
}
}
#### ii. Requires a hosted copy of the install.ps1 script
##### This should be available to download without authentication.
##### The original script can be found here: https://community.chocolatey.org/install.ps1
Configuration ChocolateyConfig {
## 2. TOP LEVEL VARIABLES ##
param(
### a. Your internal repository url (the main one). ###
#### Should be similar to what you see when you browse
#### to https://community.chocolatey.org/api/v2/
$NugetRepositoryUrl = "INTERNAL REPO URL",
### b. Chocolatey nupkg download url ###
#### This url should result in an immediate download when you navigate to it in
#### a web browser
$ChocolateyNupkgUrl = "INTERNAL REPO URL/package/chocolatey.1.1.0.nupkg",
### c. Internal Repository Credential ###
#### If required, add the repository access credential here
# $NugetRepositoryCredential = [PSCredential]::new(
# "username",
# ("password" | ConvertTo-SecureString -AsPlainText -Force)
# ),
### d. Install.ps1 URL
#### The path to the hosted install script:
$ChocolateyInstallPs1Url = "https://community.chocolatey.org/install.ps1"
### e. Chocolatey Central Management (CCM) ###
#### If using CCM to manage Chocolatey, add the following:
#### i. Endpoint URL for CCM
# $ChocolateyCentralManagementUrl = "https://chocolatey-central-management:24020/ChocolateyManagementService",
#### ii. If using a Client Salt, add it here
# $ChocolateyCentralManagementClientSalt = "clientsalt",
#### iii. If using a Service Salt, add it here
# $ChocolateyCentralManagementServiceSalt = "servicesalt"
)
Import-DscResource -ModuleName PSDesiredStateConfiguration
Import-DscResource -ModuleName cChoco
Node 'localhost' {
## 3. ENSURE CHOCOLATEY IS INSTALLED ##
### Ensure Chocolatey is installed from your internal repository
Environment chocoDownloadUrl {
Name = "chocolateyDownloadUrl"
Value = $ChocolateyNupkgUrl
}
cChocoInstaller installChocolatey {
DependsOn = "[Environment]chocoDownloadUrl"
InstallDir = Join-Path $env:ProgramData "chocolatey"
ChocoInstallScriptUrl = $ChocolateyInstallPs1Url
}
## 4. CONFIGURE CHOCOLATEY BASELINE ##
### a. FIPS Feature ###
#### If you need FIPS compliance - make this the first thing you configure
#### before you do any additional configuration or package installations
# cChocoFeature featureFipsCompliance {
# FeatureName = "useFipsCompliantChecksums"
# }
### b. Apply Recommended Configuration ###
#### Move cache location so Chocolatey is very deterministic about
#### cleaning up temporary data and the location is secured to admins
cChocoConfig cacheLocation {
DependsOn = "[cChocoInstaller]installChocolatey"
ConfigName = "cacheLocation"
Value = "C:\ProgramData\chocolatey\cache"
}
#### Increase timeout to at least 4 hours
cChocoConfig commandExecutionTimeoutSeconds {
DependsOn = "[cChocoInstaller]installChocolatey"
ConfigName = "commandExecutionTimeoutSeconds"
Value = 14400
}
#### Turn off download progress when running choco through integrations
cChocoFeature showDownloadProgress {
DependsOn = "[cChocoInstaller]installChocolatey"
FeatureName = "showDownloadProgress"
Ensure = "Absent"
}
### c. Sources ###
#### Remove the default community package repository source
cChocoSource removeCommunityRepository {
DependsOn = "[cChocoInstaller]installChocolatey"
Name = "chocolatey"
Ensure = "Absent"
}
#### Add internal default sources
#### You could have multiple sources here, so we will provide an example
#### of one using the remote repo variable here.
#### NOTE: This EXAMPLE may require changes
cChocoSource addInternalSource {
DependsOn = "[cChocoInstaller]installChocolatey"
Name = "ChocolateyInternal"
Source = $NugetRepositoryUrl
Credentials = $NugetRepositoryCredential
Priority = 1
}
### b. Keep Chocolatey Up To Date ###
#### Keep chocolatey up to date based on your internal source
#### You control the upgrades based on when you push an updated version
#### to your internal repository.
#### Note the source here is to the OData feed, similar to what you see
#### when you browse to https://community.chocolatey.org/api/v2/
cChocoPackageInstaller updateChocolatey {
DependsOn = "[cChocoSource]addInternalSource", "[cChocoSource]removeCommunityRepository"
Name = "chocolatey"
AutoUpgrade = $true
}
## 5. ENSURE CHOCOLATEY FOR BUSINESS ##
### If you don't have Chocolatey for Business (C4B), you'll want to remove from here down.
### a. Ensure The License File Is Installed ###
#### Create a license package using script from https://docs.chocolatey.org/en-us/how-tos/setup-offline-installation#exercise-4-create-a-package-for-the-license
cChocoPackageInstaller chocolateyLicense {
DependsOn = "[cChocoPackageInstaller]updateChocolatey"
Name = "chocolatey-license"
}
### b. Disable The Licensed Source ###
#### The licensed source cannot be removed, so it must be disabled.
#### This must occur after the license has been set by the license package.
Script disableLicensedSource {
DependsOn = "[cChocoPackageInstaller]chocolateyLicense"
GetScript = {
$Source = choco source list --limitoutput | `
ConvertFrom-Csv -Delimiter '|' -Header Name, Source, Disabled | `
Where-Object Name -eq "chocolatey.licensed"
return @{
Result = if ($Source) {
[bool]::Parse($Source.Disabled)
} else {
Write-Warning "Source 'chocolatey.licensed' was not present."
$true # Source does not need disabling
}
}
}
SetScript = {
$null = choco source disable --name "chocolatey.licensed"
}
TestScript = {
$State = [ScriptBlock]::Create($GetScript).Invoke()
return $State.Result
}
}
### c. Ensure Chocolatey Licensed Extension ###
#### You will have downloaded the licensed extension to your internal repository
#### as you have disabled the licensed repository in step 5b.
#### Ensure the chocolatey.extension package (aka Chocolatey Licensed Extension)
cChocoPackageInstaller chocolateyLicensedExtension {
DependsOn = "[Script]disableLicensedSource"
Name = "chocolatey.extension"
}
#### The Chocolatey Licensed Extension unlocks all of the following, which also have configuration/feature items available with them. You may want to visit the feature pages to see what you might want to also enable:
#### - Package Builder - https://docs.chocolatey.org/en-us/features/paid/package-builder
#### - Package Internalizer - https://docs.chocolatey.org/en-us/features/paid/package-internalizer
#### - Package Synchronization (3 components) - https://docs.chocolatey.org/en-us/features/paid/package-synchronization
#### - Package Reducer - https://docs.chocolatey.org/en-us/features/paid/package-reducer
#### - Package Audit - https://docs.chocolatey.org/en-us/features/paid/package-audit
#### - Package Throttle - https://docs.chocolatey.org/en-us/features/paid/package-throttle
#### - CDN Cache Access - https://docs.chocolatey.org/en-us/features/paid/private-cdn
#### - Branding - https://docs.chocolatey.org/en-us/features/paid/branding
#### - Self-Service Anywhere (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/self-service-anywhere
#### - Chocolatey Central Management (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/chocolatey-central-management
#### - Other - https://docs.chocolatey.org/en-us/features/paid/
### d. Ensure Self-Service Anywhere ###
#### If you have desktop clients where users are not administrators, you may
#### to take advantage of deploying and configuring Self-Service anywhere
cChocoFeature hideElevatedWarnings {
DependsOn = "[cChocoPackageInstaller]chocolateyLicensedExtension"
FeatureName = "showNonElevatedWarnings"
Ensure = "Absent"
}
cChocoFeature useBackgroundService {
DependsOn = "[cChocoPackageInstaller]chocolateyLicensedExtension"
FeatureName = "useBackgroundService"
Ensure = "Present"
}
cChocoFeature useBackgroundServiceWithNonAdmins {
DependsOn = "[cChocoPackageInstaller]chocolateyLicensedExtension"
FeatureName = "useBackgroundServiceWithNonAdministratorsOnly"
Ensure = "Present"
}
cChocoFeature useBackgroundServiceUninstallsForUserInstalls {
DependsOn = "[cChocoPackageInstaller]chocolateyLicensedExtension"
FeatureName = "allowBackgroundServiceUninstallsFromUserInstallsOnly"
Ensure = "Present"
}
cChocoConfig allowedBackgroundServiceCommands {
DependsOn = "[cChocoFeature]useBackgroundService"
ConfigName = "backgroundServiceAllowedCommands"
Value = "install,upgrade,uninstall"
}
### e. Ensure Chocolatey Central Management ###
#### If you want to manage and report on endpoints, you can set up and configure
### Central Management. There are multiple portions to manage, so you'll see
### a section on agents here along with notes on how to configure the server
### side components.
if ($ChocolateyCentralManagementUrl) {
cChocoPackageInstaller chocolateyAgent {
DependsOn = "[cChocoPackageInstaller]chocolateyLicensedExtension"
Name = "chocolatey-agent"
}
cChocoConfig centralManagementServiceUrl {
DependsOn = "[cChocoPackageInstaller]chocolateyAgent"
ConfigName = "CentralManagementServiceUrl"
Value = $ChocolateyCentralManagementUrl
}
if ($ChocolateyCentralManagementClientSalt) {
cChocoConfig centralManagementClientSalt {
DependsOn = "[cChocoPackageInstaller]chocolateyAgent"
ConfigName = "centralManagementClientCommunicationSaltAdditivePassword"
Value = $ChocolateyCentralManagementClientSalt
}
}
if ($ChocolateyCentralManagementServiceSalt) {
cChocoConfig centralManagementServiceSalt {
DependsOn = "[cChocoPackageInstaller]chocolateyAgent"
ConfigName = "centralManagementServiceCommunicationSaltAdditivePassword"
Value = $ChocolateyCentralManagementServiceSalt
}
}
cChocoFeature useCentralManagement {
DependsOn = "[cChocoPackageInstaller]chocolateyAgent"
FeatureName = "useChocolateyCentralManagement"
Ensure = "Present"
}
cChocoFeature useCentralManagementDeployments {
DependsOn = "[cChocoPackageInstaller]chocolateyAgent"
FeatureName = "useChocolateyCentralManagementDeployments"
Ensure = "Present"
}
}
}
}
# If working this into an existing configuration with a good method for
$ConfigData = @{
AllNodes = @(
@{
NodeName = "localhost"
PSDscAllowPlainTextPassword = $true
}
)
}
try {
Push-Location $env:Temp
$Config = ChocolateyConfig -ConfigurationData $ConfigData
Start-DscConfiguration -Path $Config.PSParentPath -Wait -Verbose -Force
} finally {
Pop-Location
}
Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.
If Applicable - Chocolatey Configuration/Installation
## 1. REQUIREMENTS ##
### Here are the requirements necessary to ensure this is successful.
### a. Internal/Private Cloud Repository Set Up ###
#### You'll need an internal/private cloud repository you can use. These are
#### generally really quick to set up and there are quite a few options.
#### Chocolatey Software recommends Nexus, Artifactory Pro, or ProGet as they
#### are repository servers and will give you the ability to manage multiple
#### repositories and types from one server installation.
### b. Download Chocolatey Package and Put on Internal Repository ###
#### You need to have downloaded the Chocolatey package as well.
#### Please see https://chocolatey.org/install#organization
### c. Other Requirements ###
#### i. Requires puppetlabs/chocolatey module
#### See https://forge.puppet.com/puppetlabs/chocolatey
## 2. TOP LEVEL VARIABLES ##
### a. Your internal repository url (the main one). ###
#### Should be similar to what you see when you browse
#### to https://community.chocolatey.org/api/v2/
$_repository_url = 'INTERNAL REPO URL'
### b. Chocolatey nupkg download url ###
#### This url should result in an immediate download when you navigate to it in
#### a web browser
$_choco_download_url = 'INTERNAL REPO URL/package/chocolatey.1.1.0.nupkg'
### c. Chocolatey Central Management (CCM) ###
#### If using CCM to manage Chocolatey, add the following:
#### i. Endpoint URL for CCM
# $_chocolatey_central_management_url = 'https://chocolatey-central-management:24020/ChocolateyManagementService'
#### ii. If using a Client Salt, add it here
# $_chocolatey_central_management_client_salt = "clientsalt"
#### iii. If using a Service Salt, add it here
# $_chocolatey_central_management_service_salt = 'servicesalt'
## 3. ENSURE CHOCOLATEY IS INSTALLED ##
### Ensure Chocolatey is installed from your internal repository
### Note: `chocolatey_download_url is completely different than normal
### source locations. This is directly to the bare download url for the
### chocolatey.nupkg, similar to what you see when you browse to
### https://community.chocolatey.org/api/v2/package/chocolatey
class {'chocolatey':
chocolatey_download_url => $_choco_download_url,
use_7zip => false,
}
## 4. CONFIGURE CHOCOLATEY BASELINE ##
### a. FIPS Feature ###
#### If you need FIPS compliance - make this the first thing you configure
#### before you do any additional configuration or package installations
#chocolateyfeature {'useFipsCompliantChecksums':
# ensure => enabled,
#}
### b. Apply Recommended Configuration ###
#### Move cache location so Chocolatey is very deterministic about
#### cleaning up temporary data and the location is secured to admins
chocolateyconfig {'cacheLocation':
value => 'C:\ProgramData\chocolatey\cache',
}
#### Increase timeout to at least 4 hours
chocolateyconfig {'commandExecutionTimeoutSeconds':
value => '14400',
}
#### Turn off download progress when running choco through integrations
chocolateyfeature {'showDownloadProgress':
ensure => disabled,
}
### c. Sources ###
#### Remove the default community package repository source
chocolateysource {'chocolatey':
ensure => absent,
location => 'https://community.chocolatey.org/api/v2/',
}
#### Add internal default sources
#### You could have multiple sources here, so we will provide an example
#### of one using the remote repo variable here
#### NOTE: This EXAMPLE requires changes
chocolateysource {'internal_chocolatey':
ensure => present,
location => $_repository_url,
priority => 1,
username => 'optional',
password => 'optional,not ensured',
bypass_proxy => true,
admin_only => false,
allow_self_service => false,
}
### b. Keep Chocolatey Up To Date ###
#### Keep chocolatey up to date based on your internal source
#### You control the upgrades based on when you push an updated version
#### to your internal repository.
#### Note the source here is to the OData feed, similar to what you see
#### when you browse to https://community.chocolatey.org/api/v2/
package {'chocolatey':
ensure => latest,
provider => chocolatey,
source => $_repository_url,
}
## 5. ENSURE CHOCOLATEY FOR BUSINESS ##
### If you don't have Chocolatey for Business (C4B), you'll want to remove from here down.
### a. Ensure The License File Is Installed ###
#### Create a license package using script from https://docs.chocolatey.org/en-us/guides/organizations/organizational-deployment-guide#exercise-4-create-a-package-for-the-license
# TODO: Add resource for installing/ensuring the chocolatey-license package
package {'chocolatey-license':
ensure => latest,
provider => chocolatey,
source => $_repository_url,
}
### b. Disable The Licensed Source ###
#### The licensed source cannot be removed, so it must be disabled.
#### This must occur after the license has been set by the license package.
## Disabled sources still need all other attributes until
## https://tickets.puppetlabs.com/browse/MODULES-4449 is resolved.
## Password is necessary with user, but not ensurable, so it should not
## matter what it is set to here. If you ever do get into trouble here,
## the password is your license GUID.
chocolateysource {'chocolatey.licensed':
ensure => disabled,
priority => '10',
user => 'customer',
password => '1234',
require => Package['chocolatey-license'],
}
### c. Ensure Chocolatey Licensed Extension ###
#### You will have downloaded the licensed extension to your internal repository
#### as you have disabled the licensed repository in step 5b.
#### Ensure the chocolatey.extension package (aka Chocolatey Licensed Extension)
package {'chocolatey.extension':
ensure => latest,
provider => chocolatey,
source => $_repository_url,
require => Package['chocolatey-license'],
}
#### The Chocolatey Licensed Extension unlocks all of the following, which also have configuration/feature items available with them. You may want to visit the feature pages to see what you might want to also enable:
#### - Package Builder - https://docs.chocolatey.org/en-us/features/paid/package-builder
#### - Package Internalizer - https://docs.chocolatey.org/en-us/features/paid/package-internalizer
#### - Package Synchronization (3 components) - https://docs.chocolatey.org/en-us/features/paid/package-synchronization
#### - Package Reducer - https://docs.chocolatey.org/en-us/features/paid/package-reducer
#### - Package Audit - https://docs.chocolatey.org/en-us/features/paid/package-audit
#### - Package Throttle - https://docs.chocolatey.org/en-us/features/paid/package-throttle
#### - CDN Cache Access - https://docs.chocolatey.org/en-us/features/paid/private-cdn
#### - Branding - https://docs.chocolatey.org/en-us/features/paid/branding
#### - Self-Service Anywhere (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/self-service-anywhere
#### - Chocolatey Central Management (more components will need to be installed and additional configuration will need to be set) - https://docs.chocolatey.org/en-us/features/paid/chocolatey-central-management
#### - Other - https://docs.chocolatey.org/en-us/features/paid/
### d. Ensure Self-Service Anywhere ###
#### If you have desktop clients where users are not administrators, you may
#### to take advantage of deploying and configuring Self-Service anywhere
chocolateyfeature {'showNonElevatedWarnings':
ensure => disabled,
}
chocolateyfeature {'useBackgroundService':
ensure => enabled,
}
chocolateyfeature {'useBackgroundServiceWithNonAdministratorsOnly':
ensure => enabled,
}
chocolateyfeature {'allowBackgroundServiceUninstallsFromUserInstallsOnly':
ensure => enabled,
}
chocolateyconfig {'backgroundServiceAllowedCommands':
value => 'install,upgrade,uninstall',
}
### e. Ensure Chocolatey Central Management ###
#### If you want to manage and report on endpoints, you can set up and configure
### Central Management. There are multiple portions to manage, so you'll see
### a section on agents here along with notes on how to configure the server
### side components.
if $_chocolatey_central_management_url {
package {'chocolatey-agent':
ensure => latest,
provider => chocolatey,
source => $_repository_url,
require => Package['chocolatey-license'],
}
chocolateyconfig {'CentralManagementServiceUrl':
value => $_chocolatey_central_management_url,
}
if $_chocolatey_central_management_client_salt {
chocolateyconfig {'centralManagementClientCommunicationSaltAdditivePassword':
value => $_chocolatey_central_management_client_salt,
}
}
if $_chocolatey_central_management_service_salt {
chocolateyconfig {'centralManagementClientCommunicationSaltAdditivePassword':
value => $_chocolatey_central_management_client_salt,
}
}
chocolateyfeature {'useChocolateyCentralManagement':
ensure => enabled,
require => Package['chocolatey-agent'],
}
chocolateyfeature {'useChocolateyCentralManagementDeployments':
ensure => enabled,
require => Package['chocolatey-agent'],
}
}
Need Help? View our docs or file an issue.
There is already a version of this package in your Script Builder
Current Version | New Version |
---|---|
- Passing
- Failing
- Pending
- Unknown / Exempted

Downloads:
4,724
Downloads of v 2020.09.21:
461
Last Update:
21 Sep 2020
Package Maintainer(s):
Software Author(s):
- Bill Curran
Tags:
bcurran3 cnc choco unofficial nuspec checker validator script chocolateasy
(unofficial) Chocolatey .nuspec Checker (Script)
- 1
- 2
- 3
2020.09.21 | Updated: 21 Sep 2020
Downloads:
4,724
Downloads of v 2020.09.21:
461
Maintainer(s):
Software Author(s):
- Bill Curran
Edit Package
To edit the metadata for a package, please upload an updated version of the package.
Chocolatey's Community Package Repository currently does not allow updating package metadata on the website. This helps ensure that the package itself (and the source used to build the package) remains the one true source of package metadata.
This does require that you increment the package version.
- 1
- 2
- 3
(unofficial) Chocolatey .nuspec Checker (Script)
2020.09.21
- 1
- 2
- 3
All Checks are Passing
3 Passing Tests
Deployment Method: Individual Install, Upgrade, & Uninstall
To install (unofficial) Chocolatey .nuspec Checker (Script), run the following command from the command line or from PowerShell:
To upgrade (unofficial) Chocolatey .nuspec Checker (Script), run the following command from the command line or from PowerShell:
To uninstall (unofficial) Chocolatey .nuspec Checker (Script), run the following command from the command line or from PowerShell:
Deployment Method:
📝 NOTE: This applies to both open source and commercial editions of Chocolatey.
1. Enter Your Internal Repository Url
(this should look similar to https://community.chocolatey.org/api/v2/)
2. Setup Your Environment
1. Ensure you are set for organizational deployment
Please see the organizational deployment guide
2. Get the package into your environment
Option 1: Cached Package (Unreliable, Requires Internet - Same As Community)-
Open Source or Commercial:
- Proxy Repository - Create a proxy nuget repository on Nexus, Artifactory Pro, or a proxy Chocolatey repository on ProGet. Point your upstream to https://community.chocolatey.org/api/v2/. Packages cache on first access automatically. Make sure your choco clients are using your proxy repository as a source and NOT the default community repository. See source command for more information.
- You can also just download the package and push it to a repository Download
-
Open Source
-
Download the package:
Download - Follow manual internalization instructions
-
-
Package Internalizer (C4B)
-
Run: (additional options)
choco download choco-nuspec-checker --internalize --source=https://community.chocolatey.org/api/v2/
-
For package and dependencies run:
choco push --source="'INTERNAL REPO URL'"
- Automate package internalization
-
Run: (additional options)
3. Copy Your Script
choco upgrade choco-nuspec-checker -y --source="'INTERNAL REPO URL'" [other options]
See options you can pass to upgrade.
See best practices for scripting.
Add this to a PowerShell script or use a Batch script with tools and in places where you are calling directly to Chocolatey. If you are integrating, keep in mind enhanced exit codes.
If you do use a PowerShell script, use the following to ensure bad exit codes are shown as failures:
choco upgrade choco-nuspec-checker -y --source="'INTERNAL REPO URL'"
$exitCode = $LASTEXITCODE
Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
- name: Install choco-nuspec-checker
win_chocolatey:
name: choco-nuspec-checker
version: '2020.09.21'
source: INTERNAL REPO URL
state: present
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
chocolatey_package 'choco-nuspec-checker' do
action :install
source 'INTERNAL REPO URL'
version '2020.09.21'
end
See docs at https://docs.chef.io/resource_chocolatey_package.html.
cChocoPackageInstaller choco-nuspec-checker
{
Name = "choco-nuspec-checker"
Version = "2020.09.21"
Source = "INTERNAL REPO URL"
}
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
package { 'choco-nuspec-checker':
ensure => '2020.09.21',
provider => 'chocolatey',
source => 'INTERNAL REPO URL',
}
Requires Puppet Chocolatey Provider module. See docs at https://forge.puppet.com/puppetlabs/chocolatey.
4. If applicable - Chocolatey configuration/installation
See infrastructure management matrix for Chocolatey configuration elements and examples.
This package was approved as a trusted package on 21 Sep 2020.
choco://choco-nuspec-checker
To use choco:// protocol URLs, install (unofficial) choco:// Protocol support
choco-nuspec-checker (CNC) is a PowerShell script I designed for Chocolatey package maintainers/creators to check Chocolatey .nuspec files for common errors and omissions... and automatically fix most of them! Find out AND FIX what the Chocolatey validator is going to tell you BEFORE you submit your package. CNC also goes beyond it's original scope and checks for common Chocolatey install/uninstall script errors and omissions as well.
FEATURES:
- CNC checks all .nuspec elements and reports any missing or template default values, now recursively too!
- CNC checks for all verifier messages (guidelines, suggestions, and notes) and reports them if applicable
- CNC checks for dead URLs and reports them
- CNC checks for GitHub direct links, reports them, and can convert them to various CDN URLs (default=Staticaly)
- CNC checks for RawGit CDN links, reports them, and can convert them to various CDN URLs (default=Staticaly)
- CNC can open all your .nuspec element URLs in your default browser for quick viewing
- CNC checks and reports current status of your package on chocolatey.org
- CNC can add a standard template header, footer, and/or package notes to your .nuspec description with variables
- CNC checks nuspec and PowerShell scripts for correct UTF-8 encoding and reports if the encoding is incorrect
- CNC can re-write your nuspec in UTF-8 w/o BOM format
- CNC can re-write your PowerShell scripts in UTF-8 w/ BOM format
- CNC checks all your PowerShell scripts for syntax errors
- CNC checks for and can add $ErrorActionPreference = 'Stop' to your PowerShell scripts
- CNC can optimize PNG files in your nuspec directory if PNGOptimizer.commandline is installed
- CNC can be run from the Command Prompt AND PowerShell
Helps make packaging Chocolateasy!
INSTRUCTIONS:
- CNC -help for help with options and switches
- Run CNC to check the .nuspec in your current directory or run CNC X:\SOMEWHERE to check the .nuspec in that directory. (Do not specify the file, just the directory.)
If you find choco-nuspec-checker useful please consider donating: https://www.paypal.me/bcurran3donations or become a patron at https://www.patreon.com/bcurran3
$ErrorActionPreference = 'Stop'
$packageName = 'choco-nuspec-checker'
$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$scriptDir = "$(Get-ToolsLocation)\BCURRAN3"
$script = 'CNC.ps1'
# Setup
# New storage location moving forward for all my Chocolatey scripts
if (!(Test-Path "$ENV:ChocolateyToolsLocation\BCURRAN3")) { New-Item -Path "$ENV:ChocolateyToolsLocation" -Name "BCURRAN3" -ItemType "directory" | Out-Null }
# Migration
# Move files before v2019.08.26 from old to new storage location
if (Test-Path "$ENV:ChocolateyInstall\bin\$script") { Remove-Item "$ENV:ChocolateyInstall\bin\$script" -Force }
if (Test-Path "$ENV:ChocolateyInstall\bin\CNCHeader.txt") { Move-Item "$ENV:ChocolateyInstall\bin\CNCHeader.txt" "$scriptDir" -Force }
if (Test-Path "$ENV:ChocolateyInstall\bin\CNCFooter.txt") { Move-Item "$ENV:ChocolateyInstall\bin\CNCFooter.txt" "$scriptDir" -Force }
if (Test-Path "$scriptDir\CNC.cmd") { Remove-Item "$scriptDir\CNC.cmd" -Force | Out-Null } # in v2019.08.26 only
# Install
# Move new files and support files (if applicable)
Move-Item "$toolsDir\$script" "$scriptDir" -Force
Install-ChocolateyPowershellCommand -PackageName 'CNC' -PSFileFullPath "$scriptDir\$script"
if (!(Test-Path "$scriptDir\CNCHeader.txt")) { Move-Item "$toolsDir\CNCHeader.txt" "$scriptDir" -Force }
if (!(Test-Path "$scriptDir\CNCFooter.txt")) { Move-Item "$toolsDir\CNCFooter.txt" "$scriptDir" -Force }
if (!(Test-Path "$scriptDir\CNCPackageNotes.txt")) { Move-Item "$toolsDir\CNCPackageNotes.txt" "$scriptDir" -Force }
#if (!(Test-Path "$scriptDir\CNC.config")) { Move-Item "$toolsDir\CNC.config" "$scriptDir" -Force }
if ($ENV:Path -NotMatch '\BCURRAN3'){ Install-ChocolateyPath "$scriptDir" "Machine" ; refreshenv }
# Cleanup
Remove-Item "$toolsDir\*.txt" -Force -ErrorAction SilentlyContinue | Out-Null
Remove-Item "$toolsDir\*.config" -Force -ErrorAction SilentlyContinue | Out-Null
$ErrorActionPreference = 'Stop'
$packageName = 'choco-nuspec-checker'
$scriptDir = "$(Get-ToolsLocation)\BCURRAN3"
Remove-Item "$ENV:ChocolateyInstall\bin\CNC.bat" -Force | Out-Null
Remove-Item "$scriptDir\CNC*.*" -Force | Out-Null
if (!(Get-ChildItem -Path "$ENV:ChocolateyToolsLocation\BCURRAN3" | Measure-Object | %{$_.Count})) {
$ENV:Path.Replace("$ChocolateyToolsLocation\BCURRAN3","") | Out-Null
Remove-Item "$ENV:ChocolateyToolsLocation\BCURRAN3" | Out-Null
}
<?xml version="1.0"?>
<Settings>
<Preferences>
<CDN>Staticaly</CDN>
<UseFooter>false</UseFooter>
<Footer>
---
$NuspecTitle packaged with pride by $NuspecOwners.
---
</Footer>
<UseHeader>false</UseHeader>
<Header>
---
###[choco://$NuspecID](choco://$NuspecID)
To use choco:// protocol URLs, install [(unofficial) choco:// Protocol support ](https://chocolatey.org/packages/choco-protocol-support)
---
</Header>
<UsePackageNotes>false</UsePackageNotes>
<PackageNotes>**[PACKAGE NOTES](https://github.com/$NuspecOwners/ChocolateyPackages/blob/master/$NuspecID/readme.md)**</PackageNotes>
</Preferences>
</Settings>
<!--
choco-nuspec-checker.config preferences notes:
CDN - which CDN to use for image links: GitHack, GitCDN, jsDelivr, Staticaly
UseFooter - Insert footer into description: true/false
UseHeader - Insert header into description: true/false
UsePackageNotes - Insert package notes into description: true/false
Header - header message
Footer - footer message
PackageNotes - package notes message
-->
# $ErrorActionPreference = 'Stop'
# CNC.ps1 Copyleft 2018-2020 by Bill Curran AKA BCURRAN3
# LICENSE: GNU GPL v3 - https://www.gnu.org/licenses/gpl.html
# Open a GitHub issue at https://github.com/bcurran3/ChocolateyPackages/issues if you have suggestions for improvement.
# REF: https://docs.microsoft.com/en-us/nuget/reference/nuspec
# REF: https://github.com/chocolatey/package-validator/wiki
param (
[string]$path=(Get-Location).path,
[switch]$recurse
)
Write-Host "CNC.ps1 v2020.09.20 - (unofficial) Chocolatey .nuspec Checker ""CNC - Run it through the Bill.""" -Foreground White
Write-Host "Copyleft 2018-2020 Bill Curran ([email protected]) - free for personal and commercial use`n" -Foreground White
# Verify ChocolateyToolsLocation was created by Get-ToolsLocation during install and is in the environment
if (!($ENV:ChocolateyToolsLocation)) {$ENV:ChocolateyToolsLocation = "$ENV:SystemDrive\tools"}
if (!(Test-Path "$ENV:ChocolateyToolsLocation\BCURRAN3")) {Write-Warning "Configuration not found. Please re-install.";throw}
# parameters and variables -------------------------------------------------------------------------------------
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
[email protected]("png","svg")
# All 7Zip supported formats plus EXE, MSU, MSP, APPX, APPXBUNDLE, IMG - What else is needed?
[email protected]("*.exe","*.img","*.msu","*.msp","*.appx","*.appxbundle","*.7z","*.xz","*.bzip2","*.gzip","*.tar","*.zip","*.wim","*.ar","*.arj","*.cab","*.chm","*.cpio","*.cramfs","*.dmg","*.ext","*.fat","*.gpt""*.hfs","*.ihex","*.iso","*.lzh","*.lzma","*.mbr","*.msi","*.nsis","*.ntfs","*.qcow2","*.rar","*.rpm","*.squashfs","*.udf","*.uefi","*.vdi","*.vhd","*.vmdk","*.xar","*.z")
$CDNlist = "https://www.staticaly.com, https://raw.githack.com, https://gitcdn.link, or https://www.jsdelivr.com"
$CNCHeader = "$ENV:ChocolateyToolsLocation\BCURRAN3\CNCHeader.txt"
$CNCFooter = "$ENV:ChocolateyToolsLocation\BCURRAN3\CNCFooter.txt"
$CNCPackageNotes = "$ENV:ChocolateyToolsLocation\BCURRAN3\CNCPackageNotes.txt"
$PNGOptimizer = (Test-Path $ENV:ChocolateyInstall\bin\PngOptimizerCL.exe)
$OptimizeImages=$False
$NewCDN = "Staticly"
$StaticlyCDN = $True
$XMLComment = "Do not remove this test for UTF-8: if `“Ω`” doesn`’t appear as greek uppercase omega letter enclosed in quotation marks, you should use an editor that supports UTF-8, not this one."
$XMLNamespace = "http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd"
# <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
if (($args -eq '-help') -or ($args -eq '-?') -or ($args -eq '/?')) {
Write-Host "OPTIONS AND SWITCHES:" -Foreground Magenta
Write-Host "-help, -?, or /?"
Write-Host " Displays this information."
Write-Host "-AddFooter"
Write-Host " Adds and saves a footer from $CNCFooter to your <description>."
Write-Host "-AddHeader"
Write-Host " Adds and saves a header from $CNCHeader to your <description>."
Write-Host "-AddPackageNotes"
Write-Host " Adds and saves a package notes link from $CNCPackageNotes to your <description>."
Write-Host "-EditFooter"
Write-Host " Edit $CNCFooter with Notepad++ or Notepad."
Write-Host "-EditHeader"
Write-Host " Edit $CNCHeader with Notepad++ or Notepad."
Write-Host "-EditPackageNotes"
Write-Host " Edit $CNCPackageNotes with Notepad++ or Notepad."
Write-Host "-MakeBackups"
Write-Host " Make filename.ext.CNC.BAK of all modified files."
Write-Host "-OpenURLs"
Write-Host " Opens all URLs in your browser for inspection when finished."
Write-Host "-OpenValidatorInfo"
Write-Host " Opens the Chocolatey package-validator info page on GitHub in your default browser."
Write-Host "-ShowFooter"
Write-Host " Displays $CNCFooter."
Write-Host "-ShowHeader"
Write-Host " Displays $CNCHeader."
Write-Host "-OptimizeImages, -OptimizePNGs"
Write-Host " Runs PNGOptimizerCL on supported image files."
Write-Host "-Recurse"
Write-Host " Runs CNC recursively."
Write-Host "-Update"
Write-Host " Will re-write out your nuspec file; e.g. change to UTF-8 w/o BOM."
Write-Host "-UpdateAll"
Write-Host " Rights all wrongs."
Write-Host "-UpdateImageURLs"
Write-Host " Updates image URLs with Staticaly CDN URLs (default)."
Write-Host "-UpdateScripts"
Write-Host " Will re-write out your PowerShell scripts, e.g. change to UTF-8 w/BOM, and add ErrorActionPreference=Stop."
Write-Host "-UpdateXMLComment"
Write-Host " Updates the XML comment for UTF-8 checking."
Write-Host "-UpdateXMLDeclaration"
Write-Host " Updates the XML declaration."
Write-Host "-UpdateXMLNamespace"
Write-Host " Updates the XML Namespace"
Write-Host "-UseGitHack"
Write-Host " Use GitHack for image URLs replacement, for use with -UpdateImageURLs or -UpdateAll."
Write-Host "-UseGitCDN"
Write-Host " Use GitCDN for image URLs replacement, for use with -UpdateImageURLs or -UpdateAll."
Write-Host "-UsejsDelivr"
Write-Host " Use jsDeliver for image URLs replacement, for use with -UpdateImageURLs or -UpdateAll."
Write-Host "-WhatIf"
Write-Host " Test run, don't save changes."
Write-Host "From your packages' root directory, run CNC -Recurse to check all your packages." -Foreground Magenta
return
}
if (Test-Path $ENV:ChocolateyInstall\bin\notepad++.exe){
$Editor="notepad++.exe"
} else {
$Editor="notepad.exe"
}
if ($args -eq "-EditFooter") {
Write-Host " ** Editing contents of $CNCFooter." -Foreground Magenta
&$Editor $CNCFooter
return
}
if ($args -eq "-EditHeader") {
Write-Host " ** Editing contents of $CNCHeader." -Foreground Magenta
&$Editor $CNCHeader
return
}
if ($args -eq "-EditPackageNotes") {
Write-Host " ** Editing contents of $CNCPackageNotes." -Foreground Magenta
&$Editor $CNCPackageNotes
return
}
if ($args -eq "-ShowFooter") {
Write-Host " ** Displaying contents of $CNCFooter." -Foreground Magenta
Write-Host
Get-Content $CNCFooter
return
}
if ($args -eq "-ShowHeader") {
Write-Host " ** Displaying contents of $CNCHeader." -Foreground Magenta
Write-Host
Get-Content $CNCHeader
return
}
if ($args -eq "-ShowPackageNotes") {
Write-Host " ** Displaying contents of $CNCPackageNotes." -Foreground Magenta
Write-Host
Get-Content $CNCPackageNotes
return
}
if ($args -eq "-OpenValidatorInfo") {
Write-Host " ** Opening https://github.com/chocolatey/package-validator/wiki." -Foreground Magenta
Write-Host
&start https://github.com/chocolatey/package-validator/wiki
return
}
if ($args -eq "-AddHeader") {$AddHeader=$True} else {$AddHeader=$False}
if ($args -eq "-AddFooter") {$AddFooter=$True} else {$AddFooter=$False}
if ($args -eq "-AddPackageNotes") {$AddPackageNotes=$True} else {$AddPackageNotes=$False}
if ($args -eq "-MakeBackups") {$MakeBackups=$True} else {$MakeBackups=$False}
if ($args -eq "-Debug") {$Debug=$True} else {$Debug=$False}
if ($args -eq "-OpenURLs") {$OpenURLs=$True} else {$OpenURLs=$False}
if ($args -eq "-OptimizeImages") {$OptimizeImages=$True}
if ($args -eq "-OptimizePNGs") {$OptimizeImages=$True}
if ($args -eq "-UpdateImageURLs") {$UpdateImageURLs=$True} else {$UpdateImageURLs=$False}
if ($args -eq "-UpdateScripts") {$UpdateScripts=$True} else {$UpdateScripts=$False}
if ($args -eq "-UpdateXMLComment") {$UpdateXMLComment=$True} else {$UpdateXMLComment=$False}
if ($args -eq "-UpdateXMLDeclaration") {$UpdateXMLDeclaration=$True} else {$UpdateXMLDeclaration=$False}
if ($args -eq "-UpdateXMLNamespace") {$UpdateXMLns=$True} else {$UpdateXMLns=$False}
if ($args -eq "-Update") {$GLOBAL:UpdateNuspec=$True}
if ($args -eq "-UpdateAll") {
$UpdateAll=$True
$UpdateImageURLs=$True
$OptimizeImages=$True
$UpdateScripts=$True
$UpdateXMLComment=$True
$UpdateXMLDeclaration=$True
$UpdateXMLns=$True
$GLOBAL:AddPS1EAP=$True
$GLOBAL:UpdateNuspec=$True
} else {
$UpdateAll=$False
}
if ($args -eq "-UseGitHack") {
$GitHackCDN=$True
$StaticlyCDN=$False
$NewCDN="GitHack"
} else {
$GitHackCDN=$False
}
if ($args -eq "-UsegitCDN") {
$GitCDN=$True
$StaticlyCDN=$False
$NewCDN="GitCDN"
} else {
$GitCDN=$False
}
if ($args -eq "-UsejsDelivr") {
$jsDelivrCDN=$True
$StaticlyCDN=$False
$NewCDN="jsDelivr"
} else {
$jsDelivrCDN=$False
}
if ($args -eq "-WhatIf") {$WhatIf=$True} else {$WhatIf=$False}
if ($path -eq "\"){
$path=(Get-Location).Drive.Name + ":" + "\"
}
if (!(Test-Path $path)){
Write-Host " ** $path is an invalid path." -Foreground Red
return
}
# functions ------------------------------------------------------------------------------------------------
# Borrowed and slightly modified from
# https://blogs.technet.microsoft.com/samdrey/2014/03/26/determine-the-file-encoding-of-a-file-csv-file-with-french-accents-or-other-exotic-characters-that-youre-trying-to-import-in-powershell/
# UTF-8 w/o BOM reports as ASCII. ASCII is a subset of UTF-8.
function Get-FileEncoding
{
[CmdletBinding()] Param (
[Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] [string]$Path
)
[byte[]]$byte = get-content -Encoding byte -ReadCount 4 -TotalCount 4 -Path $Path
if ($byte[0] -eq 0xef -and $byte[1] -eq 0xbb -and $byte[2] -eq 0xbf)
{ Write-Output 'UTF-8 w/ BOM' }
elseif ($byte[0] -eq 0xfe -and $byte[1] -eq 0xff)
{ Write-Output 'Unicode' }
elseif ($byte[0] -eq 0 -and $byte[1] -eq 0 -and $byte[2] -eq 0xfe -and $byte[3] -eq 0xff)
{ Write-Output 'UTF-32' }
elseif ($byte[0] -eq 0x2b -and $byte[1] -eq 0x2f -and $byte[2] -eq 0x76)
{ Write-Output 'UTF-7'}
else
{ Write-Output 'ASCII or UTF-8 w/o BOM' }
}
# Get iconUrl dimensions
# Supports BMP, GIF, EXIF, JPG, PNG and TIFF
# Will error on URLs such as
# https://lh3.googleusercontent.com/n6kpA-xZE_0iEy9A8WkJpGT45XB6MEq09t9UdBoIrCfwIoBm3CA9gqI13AqbBN6yx7GwVDjx=s26-h26-e365-rw
function Get-ImageDimensions{
Write-Host "(Downloading icon)" -NoNewLine -Foreground Magenta
(New-Object System.Net.WebClient).DownloadFile($NuspecIconURL, "$pwd\iconURL.image")
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b `b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b" -NoNewLine
if (Test-Path "$pwd\iconURL.image"){
add-type -AssemblyName System.Drawing
$image = New-Object System.Drawing.Bitmap "$pwd\iconURL.image"
$height=$image.height
$width=$image.width
$image.dispose()
if (($height -lt 128) -and ($width -lt 128)){
if (!$height){$height="?"}
if (!$width){$width="?"}
Write-Warning " ** <iconUrl> - icon dimensions are h$height x w$width."
Write-Host " ** Suggestion: Use package icons with at least 128 pixels in width or height if available." -Foreground Cyan
$GLOBAL:Suggestions++
}
Remove-Item "$pwd\iconURL.image" -Force
}
}
# Borrowed from
# https://web.archive.org/web/20160430132409/http://powershell.org:80/wp/forums/topic/how-to-check-syntax-of-scripts-automatically/
function Test-PowerShellSyntax
{
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[string[]]
$Path
)
process
{
foreach ($scriptPath in $Path) {
$contents = Get-Content -Path $scriptPath
if ($null -eq $contents)
{
continue
}
$errors = $null
$null = [System.Management.Automation.PSParser]::Tokenize($contents, [ref]$errors)
New-Object psobject -Property @{
Path = $scriptPath
SyntaxErrorsFound = ($errors.Count -gt 0)
}
}
}
}
# Validate that URL elements are actually URLs and verify the URLs are good
# Thanks https://stackoverflow.com/questions/23760070/the-remote-server-returned-an-error-401-unauthorized
function Validate-URL([string]$element,[string]$url){
if (($url -match "http://") -or ($url -match "https://")){
Write-Host "(Validating URL)" -NoNewLine -Foreground Magenta
$HTTP_Response = $null
$HTTP_Request = [System.Net.WebRequest]::Create($url)
try{
$HTTP_Response = $HTTP_Request.GetResponse()
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b `b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b" -NoNewLine
$HTTP_Status = [int]$HTTP_Response.StatusCode
if ($HTTP_Status -eq 200) {
$GLOBAL:ValidURL=$True
} else {
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b `b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b" -NoNewLine
Write-Warning (" ** $element - the URL:`n $url`n site might be OK, status code:" + $HTTP_Status)
if ($element -notmatch ".PS1"){
Write-Host " ** Suggestion: Consider using CNC's -OpenURLs option to open and view all URLs in the .nuspec." -Foreground Cyan
} else {
Write-Host " ** Suggestion: Check your download link, it appears to be bad." -Foreground Cyan
}
$GLOBAL:Suggestions++
$GLOBAL:ValidURL=$False
}
$HTTP_Response.Close()
} catch {
$HTTP_Status = [regex]::matches($_.exception.message, "(?<=\()[\d]{3}").Value
Write-Host "`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b `b`b`b`b`b`b`b`b`b`b`b`b`b`b`b`b" -NoNewLine
if ($element -notmatch ".PS1"){
Write-Host "WARNING: ** $element - the URL:`n $url`n is probably bad, status code: $HTTP_Status. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: The $element element in the nuspec file should be a valid Url. Please correct this" -Foreground Cyan
Write-Host " ** Suggestion: Consider using CNC's -OpenURLs option to open and view all URLs in the .nuspec." -Foreground Cyan
$GLOBAL:Required++
} else {
Write-Warning (" ** $element - the URL:`n $url`n site might be OK, status code: $HTTP_Status.")
Write-Host " ** Suggestion: Check your download link, it appears to be bad." -Foreground Cyan
$GLOBAL:Suggestions++
}
$GLOBAL:ValidURL=$False
}
}
}
# Check for license files when binaries are included
function Check-LicenseFile{
$LicenseFile=(Get-ChildItem -Path $path -Include *LICENSE* -Recurse)
if ($LicenseFile){
Write-Host 'FYI: ** Binary files - '$LicenseFile.Name'file(s) found.' -Foreground Green
$GLOBAL:FYIs++
} else {
Write-Host "WARNING: ** Binary files - LICENSE.txt file NOT found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirements: Binary files (.exe, .msi, .zip, etc) have been included without including a LICENSE.txt`n file. This file is required when including binaries " -Foreground Cyan
$GLOBAL:Required++
}
}
# Check for verification file when binaries are included
function Check-VerificationFile{
$VerificationFile=(Get-ChildItem -Path $path -Include *VERIFICATION* -Recurse)
if ($VerificationFile){
Write-Host 'FYI: ** Binary files - '$VerificationFile.Name'file(s) found.' -Foreground Green
$GLOBAL:FYIs++
} else {
Write-Host "WARNING: ** Binary files - VERIFICATION.txt file NOT found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirements: Binary files (.exe, .msi, .zip) have been included without including a VERIFICATION.txt`n file. This file is required when including binaries" -Foreground Cyan
$GLOBAL:Required++
}
}
# check for binaries
function Check-Binaries{
$IncludedBinaries=(Get-ChildItem -Path $path -Include $BinaryExtensions -Recurse)
if ($IncludedBinaries){
Write-Warning " ** Binary files found in package. This will trigger a message from the verifier:"
Write-Host " ** Note: Binary files (.exe, .msi, .zip) have been included. The reviewer will ensure the maintainers have`n distribution rights." -Foreground Cyan
$GLOBAL:Notes++
Check-LicenseFile
Check-VerificationFile
}
}
# check for OS index files that should be excluded
function Check-OSIndexFiles{
$NotWanted=(Get-ChildItem -Path $path -Include "*.ds_store","thumbs.db" -Recurse)
if ($NotWanted){
Write-Host "WARNING: ** Operating System index files found in directory. If found in the package, this will trigger a message`n from the verifier:" -Foreground Red
Write-Host " ** Required: The package contains Operating System index files, .ds_store or thumbs.db. Please remove all`n index files from the package. " -Foreground Cyan
$GLOBAL:Required++
}
}
# check for PNG files for possible optimization
function Check-PNGs{
$ImageFiles=(Get-ChildItem -Path $path -Include *.PNG,*.BMP,*.GIF,*.TGA -Recurse)
if ($ImageFiles){
Write-Host 'FYI: ** Binary files - PNG, BMP, GIF, or TGA image file(s) found.' -Foreground Yellow
$GLOBAL:FYIs++
if (!$OptimizeImages){
Write-Host ' ** Suggestion: Consider running CNC -OptimizeImages to optimize your image file(s).' -Foreground Cyan
$GLOBAL:Suggestions++
}
}
}
# I'm making an educated guess that these are requirements to be fixed, not verified.
function Check-PackageInternalFilesIncluded{
if (Test-Path '`[Content_Types`].xml') {
Write-Host "WARNING: ** [Content_Types].xml file found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Required: You have repackaged an existing package that you unpacked without removing some of the `n packaging files from the original." -Foreground Cyan
$GLOBAL:Required++
}
if (Test-Path *.psmd) {
Write-Host "WARNING: ** PSMD file(s) found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Required: You have repackaged an existing package that you unpacked without removing some of the `n packaging files from the original." -Foreground Cyan
$GLOBAL:Required++
}
if (Test-Path *.rels) {
Write-Host "WARNING: ** RELS file(s) found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Required: You have repackaged an existing package that you unpacked without removing some of the `n packaging files from the original." -Foreground Cyan
$GLOBAL:Required++
}
if (Test-Path _rels) {
Write-Host "WARNING: ** _RELS directory found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Required: You have repackaged an existing package that you unpacked without removing some of the `n packaging files from the original." -Foreground Cyan
$GLOBAL:Required++
}
}
# check if header template is in the description
function Check-Header{
$NuspecDescription=$NuspecDescription.Trim()
if ($NuspecDescription.StartsWith("***") -or $NuspecDescription.StartsWith("---") -or $NuspecDescription.StartsWith("___")){
Write-Host "FYI: ** <description> - header template found." -Foreground Green
$GLOBAL:FYIs++
$GLOBAL:FoundHeader=$True
} else {
$GLOBAL:FoundHeader=$False
$GLOBAL:Suggestions++
if (!($AddPackageNotes)) {
Write-Host ' ** Suggestion: Consider adding a header and help propagate (unofficial) choco:// Protocol support' -Foreground Cyan
}
}
}
# add header template to <description>
function Add-Header{
if ($GLOBAL:FoundHeader){
Write-Host "FYI: ** <description> - header template previously added." -Foreground Cyan
$GLOBAL:FYIs++
return $NuspecDescription
}
if (Test-Path $CNCHeader){
$Header=[IO.File]::ReadAllText($CNCHeader)
if ($Header -match '\$NuspecAuthors') {$Header=$Header -replace '\$NuspecAuthors',"$NuspecAuthors"}
if ($Header -match '\$NuspecID') {$Header=$Header -replace '\$NuspecID',"$NuspecID"}
if ($Header -match '\$NuspecOwners') {$Header=$Header -replace '\$NuspecOwners',"$NuspecOwners"}
if ($Header -match '\$NuspecTitle') {$Header=$Header -replace '\$NuspecTitle',"$NuspecTitle"}
if ($Header -match '\$NuspecVersion') {$Header=$Header -replace '\$NuspecVersion',"$NuspecVersion"}
$NuspecDescription="`n" + $Header + $NuspecDescription + "`n"
Write-Host " ** <description> - ADDED header template." -Foreground Green
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $NuspecDescription
} else {
Write-Warning " ** $CNCHeader not found."
return $NuspecDescription
}
}
# check if footer template is in the description
function Check-Footer{
$NuspecDescription=$NuspecDescription.Trim()
if ($NuspecDescription.EndsWith("***") -or $NuspecDescription.EndsWith("---") -or $NuspecDescription.EndsWith("___")){
Write-Host "FYI: ** <description> - footer template found." -Foreground Green
$GLOBAL:FYIs++
$GLOBAL:FoundFooter=$True
} else {
$GLOBAL:FoundFooter=$False
}
}
# add footer template to <description>
function Add-Footer{
if ($GLOBAL:FoundFooter){
Write-Host "FYI: ** <description> - footer template previously added." -Foreground Cyan
$GLOBAL:FYIs++
return $NuspecDescription
}
if (Test-Path $CNCFooter){
$Footer=[IO.File]::ReadAllText($CNCFooter)
if ($Footer -match '\$NuspecAuthors') {$Footer=$Footer -replace '\$NuspecAuthors',"$NuspecAuthors"}
if ($Footer -match '\$NuspecID') {$Footer=$Footer -replace '\$NuspecID',"$NuspecID"}
if ($Footer -match '\$NuspecOwners') {$Footer=$Footer -replace '\$NuspecOwners',"$NuspecOwners"}
if ($Footer -match '\$NuspecTitle') {$Footer=$Footer -replace '\$NuspecTitle',"$NuspecTitle"}
if ($Footer -match '\$NuspecVersion') {$Footer=$Footer -replace '\$NuspecVersion',"$NuspecVersion"}
$NuspecDescription=$NuspecDescription + "`n" + $Footer + "`n"
Write-Host " ** <description> - ADDED footer template." -Foreground Green
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $NuspecDescription
} else {
Write-Warning " ** $CNCFooter NOT found."
return $NuspecDescription
}
}
# TDL - check only head and tail of the description; maybe 5 lines
# check if package release notes are in the description
function Check-PackageNotes{
$NuspecDescription=$NuspecDescription.Trim()
if (($NuspecDescription -match 'PACKAGE NOTES') -or ($NuspecDescription -match 'PACKAGE RELEASE NOTES')){
Write-Host "FYI: ** <description> - package release notes found." -Foreground Green
$GLOBAL:FYIs++
$GLOBAL:FoundPackageNotes=$True
} else {
$GLOBAL:FoundPackageNotes=$False
$GLOBAL:Suggestions++
if (!($AddPackageNotes)) {
Write-Host ' ** Suggestion: Consider adding PACKAGE NOTES to inform users of any special information about the package.' -Foreground Cyan
}
}
}
# add package notes template to <description>
function Add-PackageNotes{
if ($GLOBAL:FoundPackageNotes){
Write-Host "FYI: ** <description> - package notes template previously added." -Foreground Cyan
$GLOBAL:FYIs++
return $NuspecDescription
}
if (Test-Path $CNCPackageNotes){
$PackageNotes=[IO.File]::ReadAllText($CNCPackageNotes)
if ($PackageNotes -match '\$NuspecAuthors') {$PackageNotes=PackageNotes -replace '\$NuspecAuthors',"$NuspecAuthors"}
if ($PackageNotes -match '\$NuspecID') {$PackageNotes=$PackageNotes -replace '\$NuspecID',"$NuspecID"}
if ($PackageNotes -match '\$NuspecOwners') {$PackageNotes=$PackageNotes -replace '\$NuspecOwners',"$NuspecOwners"}
if ($PackageNotes -match '\$NuspecTitle') {$PackageNotes=$PackageNotes -replace '\$NuspecTitle',"$NuspecTitle"}
if ($PackageNotes -match '\$NuspecVersion') {$PackageNotes=$PackageNotes -replace '\$NuspecVersion',"$NuspecVersion"}
$NuspecDescription=$NuspecDescription + "`n" + $PackageNotes + "`n"
Write-Host " ** <description> - ADDED package notes template." -Foreground Green
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $NuspecDescription
} else {
Write-Warning " ** $CNCPackageNotes NOT found."
return $NuspecDescription
}
}
# check Markdown header problems after chocolatey.org Sept. 2019 updates
function Check-Markdown([string]$element,[string]$text){
if ($NuspecDescription -match "#\w") { # alphanumeric whitespace only (no /, [, etc)
Write-Host "WARNING: ** $element - invalid Markdown heading syntax found. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Required: Package Description should not contain invalid Markdown Headings." -Foreground Cyan
$GLOBAL:Required++
}
}
# TDL
# Add whitespace after #, ##, and ### when found followed by characters
function Fix-Markdown{
}
# Check package current status on chocolatey.org
function Check-OnlineStatus{
$PackagePageInfo = try { (Invoke-WebRequest -Uri "https://chocolatey.org/packages/$NuspecID" -UseBasicParsing -DisableKeepAlive).StatusCode } catch [Net.WebException]{ [int]$_.Exception.Response.StatusCode }
if ($PackagePageInfo -eq '404'){
Write-Host "FYI: ** This appears to be a brand new package. Cool!" -Foreground Green
$GLOBAL:FYIs++
return
}
$PackagePageInfo = (Invoke-WebRequest -DisableKeepAlive -Uri "https://chocolatey.org/packages/$NuspecID")
if ($PackagePageInfo -match "This package was approved as <a href=""https://chocolatey.org/faq#what-is-a-trusted-package"">a trusted package"){
Write-Host "FYI: ** $NuspecID is a trusted package. (Congrats!)" -Foreground Green
$GLOBAL:FYIs++
}
if ($PackagePageInfo -match 'All Checks are Passing'){
Write-Host "FYI: ** $NuspecID current status: All Checks are Passing" -Foreground Green
$GLOBAL:FYIs++
}
if (($NuspecID -ne 'choco-nuspec-checker') -and ($PackagePageInfo -match '
Some Checks Have Failed or Are Not Yet Complete')){
Write-Host "FYI: ** $NuspecID current status:
Some Checks Have Failed or Are Not Yet Complete" -Foreground Red
$GLOBAL:FYIs++
}
if ($PackagePageInfo -match 'There are versions of this package awaiting moderation'){
Write-Host "FYI: ** $NuspecID may have submitted/unapproved versions pending moderation." -Foreground Yellow
$GLOBAL:FYIs++
}
if ($PackagePageInfo -match 'Waiting for Maintainer'){
Write-Host "FYI: ** $NuspecID may have a version waiting for corrective action." -Foreground Yellow
$GLOBAL:FYIs++
}
}
# Open all .nuspec URLs for viewing
function Open-URLs{
if ($NuspecBugTrackerURL){&start $NuspecBugTrackerURL}
if ($NuspecDocsURL){&start $NuspecDocsURL}
if ($NuspecIconURL){&start $NuspecIconURL}
if ($NuspecLicenseURL){&start $NuspecLicenseURL}
if ($NuspecMailingListURL){&start $NuspecMailingListURL}
if ($NuspecPackageSourceURL){&start $NuspecPackageSourceURL}
if ($NuspecProjectSourceURL){&start $NuspecProjectSourceURL}
if ($NuspecProjectURL){&start $NuspecProjectURL}
}
# Run PNGOptimizerCL on supported image files
function Run-PNGOptimizer{
if ($OptimizeImages){
if (!$PNGOptimizer){
Write-Warning " ** -OptimizeImages parameter given but PNGOptimizerCL.exe not found."
Write-Host " ** Run choco install pngoptimizer.commandline first to use this feature." -Foreground Cyan
return
}
$ImageFiles=(Get-ChildItem -Path $path -Include *.PNG,*.BMP,*.GIF,*.TGA -Recurse)
if ($ImageFiles -and $PNGOptimizer){
Write-Host " ** Running PNGOptimzerCL on supported image files." -Foreground Green
if ($WhatIf){
Write-Host "CNC did NOT optimize your image files, -WhatIf parameter was used." -Foreground Magenta
} else {
if ($MakeBackups){
&pngoptimizercl.exe -file:""$path/"" -recurs -BackupOldPngFiles
} else {
&pngoptimizercl.exe -file:""$path/"" -recurs
}
$GLOBAL:Fixes++
}
}
}
}
# TODO check for "main" when GH stops making new repos with "master" in 10/2020
# Convert RawGit and non-CDN URLs to supported CDN URLs
function Update-CDNURL([string]$oldURL){
if ($StaticlyCDN){
if ($oldURL -match 'https://raw.githubusercontent.com'){$StaticalyURL=($oldURL -replace 'https://raw.githubusercontent.com','https://cdn.staticaly.com/gh')}
if ($oldURL -match 'https://cdn.rawgit.com'){$StaticalyURL=($oldURL -replace 'https://cdn.rawgit.com','https://cdn.staticaly.com/gh')}
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $StaticalyURL
}
if ($GitCDN){
if ($oldURL -match 'https://raw.githubusercontent.com'){$GitCNDURL=($oldURL -replace 'https://raw.githubusercontent.com','https://gitcdn.link/repo')}
if ($oldURL -match 'https://cdn.rawgit.com'){$GitCNDURL=($oldURL -replace 'https://cdn.rawgit.com','https://gitcdn.link/repo')}
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $GitCNDURL
}
if ($GitHackCDN){
if ($oldURL -match 'https://raw.githubusercontent.com'){$GitHackURL=($oldURL -replace 'https://raw.githubusercontent.com','https://rawcdn.githack.com')}
if ($oldURL -match 'https://cdn.rawgit.com'){$GitHackURL=($oldURL -replace 'https://cdn.rawgit.com','https://rawcdn.githack.com')}
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $GitHackURL
}
if ($jsDelivrCDN){
# this will fail if link is not to the master branch
if ($oldURL -match 'https://raw.githubusercontent.com'){
$jsDelivrURL=($oldURL -replace 'https://raw.githubusercontent.com','https://cdn.jsdelivr.net/gh')
$jsDelivrURL=($jsDelivrURL -replace 'master/','')
}
if ($oldURL -match 'https://cdn.rawgit.com'){
$jsDelivrURL=($oldURL -replace 'https://cdn.rawgit.com','https://cdn.jsdelivr.net/gh')
$jsDelivrURL=($jsDelivrURL -replace 'master/','')
}
$GLOBAL:UpdateNuspec=$True
$GLOBAL:Fixes++
return $jsDelivrURL
}
}
# Update the nuspec XML declaration with encoding info
function Update-XMLDeclaration{
Write-Host " ** XML declaration changed to version=""1.0"" encoding=""utf-8""" -Foreground Green
$nuspecFile.xml="version=""1.0"" encoding=""utf-8"""
$GLOBAL:Fixes++
$GLOBAL:UpdateNuspec=$True
}
# Update the nuspec with any changes and save as UTF-8 w/o BOM
# Thanks https://stackoverflow.com/questions/8160613/powershell-saving-xml-and-preserving-format
Function Update-nuspec{
if ($GLOBAL:UpdateNuspec){
$UpdatednuspecFile = [xml]([System.IO.File]::ReadAllText($LocalnuspecFile))
$UpdatednuspecFile.PreserveWhitespace = $true
$settings = New-Object System.Xml.XmlWriterSettings
$settings.Indent = $true
$settings.NewLineChars ="`r`n"
$settings.Encoding = New-Object System.Text.UTF8Encoding($false)
# changes
if ($UpdateXMLComment -and !$nuspecFile.'#comment'){$UpdatednuspecFile.InsertAfter($UpdatednuspecFile.CreateComment($XMLComment), $UpdatednuspecFile.FirstChild) | Out-Null}
if ($nuspecFile.xml){$UpdatednuspecFile.xml = $nuspecFile.xml}
if ($nuspecFile.package.metadata.description.'#cdata-section'){
# $NuspecDescription.'#cdata-section' = $NuspecDescription
# Write-Host " ** <description> - CDATA found, not changing it." -Foreground Magenta
} else {
$UpdatednuspecFile.package.metadata.description=$NuspecDescription
}
if ($NuspecIconURL){$UpdatednuspecFile.package.metadata.iconurl=$NuspecIconURL}
if ($MakeBackups){Copy-Item "$LocalnuspecFile" "$LocalnuspecFile.CNC.bak" -Force}
$xfile = [System.Xml.XmlWriter]::Create($LocalnuspecFile, $settings)
try{
$UpdatednuspecFile.Save($xfile)
} finally {
$xfile.Dispose()
}
}
}
# checks PowerShell scripts for $ErrorActionPreference statement
function Check-PS1EAP($ScriptFile){
if ($scriptFile -match "UPDATE.PS1") {return}
$CheckEAP=Get-Content $ScriptFile -First 5
if ($checkEAP -match '\$ErrorActionPreference') {
return $True
} else {
$ScriptFile=(Get-Item $ScriptFile).Name
$ScriptFile=$ScriptFile.toupper()
if ($UpdateScripts){
Write-Host " ** $ScriptFile - recommended ErrorActionPreference statement has been added." -Foreground Green
} else {
Write-Warning " ** $ScriptFile - is missing the recommended ErrorActionPreference statement."
Write-Host " ** Suggestion: Consider running CNC -UpdateScripts to add it." -Foreground Cyan
$GLOBAL:Suggestions++
return $False
}
}
}
# Add EAP statement to top of PowerShell script
function Add-PS1EAP($ScriptFile){
if ($scriptFile -match "UPDATE.PS1") {return}
if ($UpdateScripts -and !$WhatIf){
if ($MakeBackups){Copy-Item "$ScriptFile" "$ScriptFile.CNC.bak" -Force}
$header = "`$ErrorActionPreference = 'Stop'"
$Body=Get-Content $ScriptFile
$NewContent=$header+$Body
Write-Output $header $body | Out-File $ScriptFile
$GLOBAL:Fixes++
}
}
# Re-write PS script as UTF-8 w/BOM
function Update-PS1($ScriptFile){
if ($scriptFile -match "UPDATE.PS1") {return}
if ($UpdateScripts -and !$WhatIf){
if ($MakeBackups){Copy-Item "$ScriptFile" "$ScriptFile.CNC.bak" -Force}
# Write-Host " ** $ScriptFile - will be converted to UTF-8 w/ BOM and saved." -Foreground Green
$Body=Get-Content $ScriptFile
Write-Output $Body | Out-File $ScriptFile
$GLOBAL:Fixes++
}
}
# Check chocolateyInstall.ps1 for SourceForge download links
function Check-DiscouragedDownloadLinks{
if (Test-Path $path\tools\chocolateyInstall.ps1){
$test=Get-Content $path\tools\chocolateyInstall.ps1
if ($test -match "sourceforge"){
Write-Warning " ** CHOCOLATEYINSTALL.PS1 uses SourceForge as download source. This will trigger a message from the verifier:"
Write-Host " ** Guideline: Using SourceForge as the download source of installers is not recommended. Please consider an`n alternative, official distribution location if one is available." -Foreground Cyan
$GLOBAL:Guidelines++
}
if ($test -match "fosshub"){
Write-Warning " ** CHOCOLATEYINSTALL.PS1 uses FossHub as download source."
Write-Host " ** Guideline: In Dec. 2016 FossHub requested ""Please help us keep our costs down by not using scripts`n to download software from our site.""" -Foreground Cyan
$GLOBAL:Guidelines++
}
}
}
function Check-ScriptNames{
$ChocoInstallScript=Get-ChildItem "$path\chocolateyinstall.ps1" -Recurse
$NugetInstallScript=Get-ChildItem "$path\install.ps1" -Recurse
if (!$ChocoInstallScript -and $NugetInstallScript){
Write-Host "WARNING: ** Install Script Named Incorrectly." -Foreground Red
Write-Host " ** Your script is named incorrectly and will need to be renamed. A script named chocolateyInstall.ps1 was`n not found in your package, but another script ending in install.ps1 was found. The install script should`n be named chocolateyInstall.ps1 and be found in the tools folder." -Foreground Cyan
$GLOBAL:Required++
}
}
# borrowed from https://www.jonathanmedd.net/2012/05/quick-and-easy-powershell-test-xmlfile.html
function Test-XMLFile {
<#
.SYNOPSIS
Test the validity of an XML file
#>
[CmdletBinding()]
param (
[parameter(mandatory=$true)][ValidateNotNullorEmpty()][string]$xmlFilePath
)
# Check the file exists
if (!(Test-Path -Path $xmlFilePath)){
throw "$xmlFilePath is not valid. Please provide a valid path to the .xml fileh"
}
# Check for Load or Parse errors when loading the XML file
$xml = New-Object System.Xml.XmlDocument
try {
$xml.Load((Get-ChildItem -Path $xmlFilePath).FullName)
return $true
}
catch [System.Xml.XmlException] {
Write-Verbose "$xmlFilePath : $($_.toString())"
return $false
}
}
# Update the nuspec XML namespace declaration
# Only checks for the common 2011/08/nuspec.xsd namespace, could be much better using regex.
# Messages related to this happening or not (-WhatIf) are difficult to implement because this change happens independly of other changes to the .nuspec, notifications need to be implemented in most cases.
function Update-XMLnsDeclaration{
if ($MakeBackups){Copy-Item "$LocalnuspecFile" "$LocalnuspecFile.CNC.XMLnamespace.bak" -Force}
((Get-Content -Path $LocalnuspecFile -Raw) -Replace 'http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd','http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd') | Set-Content -Path $LocalnuspecFile
$GLOBAL:DelayedUpdateXMLnsDeclarationMessage=$True
$GLOBAL:Fixes++
}
#Start running the actual script --------------------------------------------------------------------------------------------
if ($recurse) {
$folderlist = Split-Path (Get-ChildItem -Path $path -Recurse -Filter "*.nuspec").fullname
} else {
$folderlist = $path
}
ForEach ($path in $folderlist) {
# Finds nuspec file for processing. Defaults to current working directory.
# You can specify a directory path, but do NOT specify the file itself, just the directory.
#if (!$path) {$LocalnuspecFile = Get-Item -Path $path\*.nuspec}
if ($path) {$LocalnuspecFile = Get-Item $path\*.nuspec}
if (!($LocalnuspecFile)) {
Write-Host " ** No .nuspec file found in $path" -Foreground Red
return
}
if ($LocalnuspecFile.count -gt 1){
Write-Host " ** Multiple .nuspec files found in $path. Please remove or rename the extras." -Foreground Red
return
}
if ($LocalnuspecFile.length -lt 168){ # approximate value of a minimal blank nuspec template
Write-Host " ** $LocalnuspecFile file appears to be blank or corrupt." -Foreground Red
return
}
if (!(Test-XMLFile $LocalnuspecFile)){
Write-Warning " ** $LocalnuspecFile is not a valid XML file."
Write-Host "FYI: ** Common problems:" -Foreground Cyan
Write-Host " choco pack will report: ""An error occurred while parsing EntityName."" for unexpected/malformed ""&""'s." -Foreground Cyan
Write-Host " choco pack will report: ""'<' is an unexpected token. The expected token is '>'."" for bad/unclosed elements." -Foreground Cyan
Write-Host " choco pack will report: ""The <tag> start tag on line x position x does not match the end tag of <tag>`n. Line x, position x."" for elements with mismatched case.`n" -Foreground Cyan
break
}
if ($UpdateXMLns){
if ($WhatIf){
$GLOBAL:DelayedUpdateXMLnsDeclarationMessage=$False
} else {
Update-XMLnsDeclaration
}
}
# variables for end results
$GLOBAL:Required=0
$GLOBAL:Guidelines=0
$GLOBAL:Suggestions=0
$GLOBAL:Notes=0
$GLOBAL:Fixes=0
$GLOBAL:FYIs=0
$GLOBAL:UpdateNuspec=$False
$GLOBAL:TemplateError=0
$GLOBAL:DelayedUpdateXMLnsDeclarationMessage=$False
# Import package.nuspec file to get values
$nuspecXML = $LocalnuspecFile
[xml]$nuspecFile = Get-Content $nuspecXML
$NuspecAuthors = $nuspecFile.package.metadata.authors
$NuspecBugTrackerURL = $nuspecFile.package.metadata.bugtrackerurl
$NuspecConflicts = $nuspecFile.package.metadata.conflicts # Built for the future
$NuspecCopyright = $nuspecFile.package.metadata.copyright
$NuspecDependencies = $nuspecFile.package.metadata.dependencies
$NuspecDescription = $nuspecFile.package.metadata.description
$NuspecDocsURL = $nuspecFile.package.metadata.docsurl
$NuspecFiles = $nuspecFile.package.files.file
$NuspecIconURL = $nuspecFile.package.metadata.iconurl
$NuspecID = $nuspecFile.package.metadata.id
$NuspecLicenseURL = $nuspecFile.package.metadata.licenseurl
$NuspecMailingListURL = $nuspecFile.package.metadata.mailinglisturl
$NuspecOwners = $nuspecFile.package.metadata.owners
$NuspecPackageSourceURL = $nuspecFile.package.metadata.packagesourceurl
$NuspecProjectSourceURL = $nuspecFile.package.metadata.projectsourceurl
$NuspecProjectURL = $nuspecFile.package.metadata.projecturl
$NuspecProvides = $nuspecFile.package.metadata.provides # Built for the future
$NuspecReleaseNotes = $nuspecFile.package.metadata.releasenotes
$NuspecReplaces = $nuspecFile.package.metadata.replaces # Built for the future
$NuspecRequireLicenseAcceptance = $nuspecFile.package.metadata.requirelicenseacceptance
$NuspecSummary = $nuspecFile.package.metadata.summary
$NuspecTags = $nuspecFile.package.metadata.tags
$NuspecTitle = $nuspecFile.package.metadata.title
$NuspecVersion = $nuspecFile.package.metadata.version
$NuspecXMLComment = $nuspecFile.'#comment'
$NuspecXMLNamespace = $nuspecFile.package.xmlns
$NuspecDisplayName=$LocalnuspecFile.Name
$NuspecDisplayName=$NuspecDisplayName.ToUpper()
$ENV:ChocolateyPackageVersion=$NuspecVersion
# Start outputting check results
Write-Host "CNC Summary of $NuspecDisplayName (v$NuspecVersion):" -Foreground Magenta
# Open all .nuspec URLs for viewing if -OpenURLs is passed
if ($OpenURLs) {
Write-Host " ** Opening all .nuspec URLs in your default browser for viewing." -Foreground Magenta
Open-URLs
}
# checks ------------------------------------------------------------------------------------------------
# Trusted package check
Check-OnlineStatus
if (Test-Path 'update.ps1') {
Write-Host "FYI: ** UPDATE.PS1 found. You must be smarter than the average bear..." -Foreground Green
$GLOBAL:FYIs++
}
# check for UTF8 encoding
# UTF-8 w/BOM is not desired per "You must save your files with UTF–8 character encoding without BOM."
$NuspecEncoding=(Get-FileEncoding -Path $LocalnuspecFile)
if ($NuspecEncoding -ne 'ASCII or UTF-8 w/o BOM'){
Write-Warning " ** $NuspecDisplayName is encoded using $NuspecEncoding."
if ($GLOBAL:UpdateNuspec) {
Write-Host " ** $NuspecDisplayName will be converted to UTF-8 w/o BOM and saved." -Foreground Green
$GLOBAL:Fixes++
} else {
Write-Host " ** Guideline: You must save your files with UTF–8 character encoding without BOM." -Foreground Cyan
$GLOBAL:Guidelines++
Write-Host " ** Suggestion: Consider running CNC -Update to re-write`n $NuspecDisplayName to UTF-8 w/o BOM." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
# check XML declaration
if ($nuspecFile.xml -eq "version=""1.0"""){
Write-Warning " ** XML declaration is version=""1.0"""
if ($UpdateXMLDeclaration){
Update-XMLDeclaration
} else {
Write-Host " ** Suggestion: Consider running CNC -UpdateXMLDeclaration to add a UTF-8 encoding statement." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
# check XML comment
if (!$nuspecFile.'#comment'){
if ($UpdateXMLComment){
Write-Host " ** XML comment to test UTF-8 encoding added." -Foreground Green
$GLOBAL:Fixes++
$GLOBAL:UpdateNuspec=$True
} else {
Write-Warning " ** The recommended XML comment to test UTF-8 encoding was not found."
Write-Host " ** Suggestion: Consider running CNC -UpdateXMLComment to add a UTF-8 encoding test XML comment." -Foreground Cyan
$GLOBAL:Suggestions++
if ($nuspecFile.'#comment' -match "Read this before creating packages"){
Write-Host "WARNING: ** XML comment contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
}
# check XML Namespace
if ($NuspecXMLNamespace -ne "$XMLNamespace"){
Write-Warning " ** XML namespace declaration is $NuspecXMLNamespace"
Write-Host " ** The current schema is $XMLNamespace" -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateXMLNamespace to update the XML namespace declaration." -Foreground Cyan
$GLOBAL:Suggestions++
}
if ($GLOBAL:DelayedUpdateXMLnsDeclarationMessage) {Write-Host " ** XML namespace declaration changed to http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd" -Foreground Green}
# <authors> checks
if (!($NuspecAuthors)) {
Write-Host "WARNING: ** <authors> element is empty, this element is a requirement." -Foreground Red
$GLOBAL:Required++
} else {
if ($NuspecAuthors -match "@"){
Write-Host "WARNING: ** <authors> - contains an e-mail address. This will trigger a message from the verifier:" -Foreground Red
Write-Host ' ** Requirements: Email address should not be used in the Author and Copyright fields of the nuspec file. ' -Foreground Cyan
$GLOBAL:Required++
}
if ($NuspecAuthors -cmatch "REPLACE"){
Write-Host "WARNING: ** <authors> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
# <bugTrackerUrl> checks
if (!($NuspecBugTrackerURL)) {
Write-Warning " ** <bugTrackerUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Suggestion: bugTrackerUrl - points to the location where issues and tickets can be accessed' -Foreground Cyan
$GLOBAL:Suggestions++
} else {
Validate-URL "<bugTrackerUrl>" $NuspecBugTrackerURL
}
# <conflicts> checks - Built for the future
#if (!($NuspecConflicts)) {Write-Warning " ** <conflicts> element is empty."}
# <copyright> checks
if (!($NuspecCopyright)) {
Write-Host "FYI: ** <copyright> - element is empty." -Foreground Yellow
$GLOBAL:FYIs++
} else {
if ($NuspecCopyright.Length -lt 5) {
Write-Host "WARNING: ** <copyright> - is less than 4 characters. This will trigger a message from the verifier:" -Foreground Red
Write-Host ' ** Requirements: If you are going to use copyright in the nuspec, please use more than 4 characters.' -Foreground Cyan
$GLOBAL:Required++
}
if ($NuspecAuthors -match "@"){
Write-Host "WARNING: ** <copyright> - contains an e-mail address. This will trigger a message from the verifier:" -Foreground Red
Write-Host ' ** Requirements: Email address should not be used in the Author and Copyright fields of the nuspec file. ' -Foreground Cyan
$GLOBAL:Required++
}
if ($NuspecCopyright -eq "Year Software Vendor"){
Write-Host "WARNING: ** <copyright> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
# <dependencies> checks
if (!($NuspecDependencies)) {
Write-Host "FYI: ** <dependencies> - element is empty." -Foreground Yellow
$GLOBAL:FYIs++
} else {
if ((!$NuspecDependencies) -and ($NuspecTitle -match "deprecated")){
Write-Host "WARNING: ** <dependencies> - Deprecated packages must have a dependency." -Foreground Red
$GLOBAL:Required++
}
if ($NuspecDependencies.dependency.id -eq 'chocolatey'){
Write-Warning " ** <dependencies> - ""chocolatey"" is a dependency. This will trigger a message from the verifier:"
Write-Host " ** Note: The package takes a dependency on Chocolatey. The reviewer will ensure the package uses a specific`n Chocolatey feature that requires a minimum version." -Foreground Cyan
$GLOBAL:Notes++
}
$DependencyName=$NuspecDependencies.dependency.id
if ($NuspecDependencies.dependency.id.count -eq 1){
if ($NuspecDependencies.dependency.version -eq $null){
Write-Warning " ** <dependencies> - $DependencyName has no version. This will trigger a message from the verifier:"
Write-Host " ** Guideline: Package contains dependencies with no specified version. You should at least specify`n a minimum version of a dependency." -Foreground Cyan
$GLOBAL:Guidelines++
}
} else {
$DependencyNumber=0
do{
$DependencyName=$NuspecDependencies.dependency.id[$DependencyNumber]
if ($NuspecDependencies.dependency[$DependencyNumber].version -eq $null){
Write-Warning " ** <dependencies> - ""$DependencyName"" has no version. This will trigger a message from the verifier:"
Write-Host " ** Guideline: Package contains dependencies with no specified version. You should at least specify`n a minimum version of a dependency." -Foreground Cyan
$GLOBAL:Guidelines++
}
$DependencyNumber++
} while ($DependencyNumber -lt $NuspecDependencies.dependency.id.count)
}
}
# <description> checks
if ($NuspecDescription.'#cdata-section'){
$NuspecDescription=$nuspecFile.package.metadata.description.'#cdata-section'
}
if (!$NuspecDescription){
Write-Host "WARNING: ** <description> - element is empty, this element is a requirement." -Foreground Red
$GLOBAL:Required++
} else {
Check-Header
if ($AddHeader) {
$NuspecDescription=(Add-Header)
}
Check-PackageNotes
if ($AddPackageNotes) {
$NuspecDescription=(Add-PackageNotes)
}
Check-Footer
if ($AddFooter) {
$NuspecDescription=(Add-Footer)
}
Check-Markdown "<description>" $NuspecDescription
if ($NuspecDescription.Length -lt 30) {
Write-Warning " ** <description> - is less than 30 characters."
Write-Host " ** Guideline: Description should be sufficient to explain the software. Please fill in the description`n with more information about the software. Feel free to use use markdown." -Foreground Cyan
$GLOBAL:Guidelines++
}
if ($NuspecDescription.Length -gt 4000) {
Write-Host "WARNING: ** <description> - is greater than 4,000 characters. Pushing the package will generate the error:" -Foreground Red
Write-Host " ** Failed to process request. 'This package had an issue pushing: A nuget package's Description property may`n not be more than 4000 characters long.'. The remote server returned an error: (409) Conflict.." -Foreground Cyan
$GLOBAL:Required++
}
if ($NuspecDescription -match "raw.githubusercontent"){
if ($UpdateImageURLs){
# Write-Warning " ** <description> - includes a GitHub raw link."
Write-Host " ** <description> - URL(s) updated to use $NewCDN." -Foreground Green
$NuspecDescription=(Update-CDNURL "$NuspecDescription")
} else {
Write-Warning " ** <description> - includes a GitHub raw link. Please change to a CDN such as:"
Write-Host " ** $CDNlist" -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateImageURLs to update it." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
if ($NuspecDescription -match "cdn.rawgit.com"){
if ($UpdateImageURLs){
# Write-Warning " ** <description> - includes a link to RawGit which will be going offline October 2019."
Write-Host " ** <description> - URL(s) updated to use $NewCDN." -Foreground Green
$NuspecDescription=(Update-CDNURL "$NuspecDescription")
} else {
Write-Warning " ** <description> - includes a link to RawGit which will be going offline October 2019. Please change to a`n CDN such as:"
Write-Host " ** $CDNlist" -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateImageURLs to update it." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
if ($NuspecDescription -cmatch "REPLACE"){
Write-Host "WARNING: ** <description> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
# below checking doesn't work as PowerShell will already give an error reading the nuspec
# Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: "An error occurred while parsing
# EntityName.
if ($NuspecDescription -match ' `& '){
Write-Warning " ** <description> - `& found and needs to be replaced with `&"
Write-Host " ** Packing will error: ""An error occurred while parsing EntityName.""" -Foreground Red
if ($UpdateAll){
$NuspecDescription=$NuspecDescription -replace "`&","`&"
Write-Host " ** <description> - `& replaced with `&" -Foreground Green
$GLOBAL:Fixes++
} else {
Write-Host " ** Suggestion: Consider running CNC -UpdateAll to update it." -Foreground Cyan
$GLOBAL:Suggestions++
$GLOBAL:Required++
}
}
if (($nuspecFile.package.metadata.description.'#cdata-section') -and ($GLOBAL:UpdateNuspec)){
Write-Host " ** <description> - CDATA found, not saving description changes." -Foreground Magenta
}
}
# <docsUrl> checks
if (!($NuspecDocsURL)) {
Write-Warning " ** <docsUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Suggestion: docsUrl - points to the location of the wiki or docs of the software' -Foreground Cyan
$GLOBAL:Suggestions++
} else {
if ($NuspecDocsURL -match "docs located"){
Write-Host "WARNING: ** <docsUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
} else {
Validate-URL "<docsUrl>" $NuspecDocsURL
}
}
# <files> checks
if (!($NuspecFiles)) {
Write-Host "FYI: ** <files> - element is empty. All of the following files will be packaged:" -Foreground Yellow
Get-ChildItem -Path $path -Recurse -Exclude *.nupkg,tools |% $_.file {Write-Host " ** $_" -Foreground Cyan -ea SilentlyContinue}
$GLOBAL:FYIs++
}
# <iconUrl> checks
if (!($NuspecIconURL)) {
Write-Warning " ** <iconUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Guideline: The iconUrl should be added if there is one. Please correct this in the nuspec, if applicable.' -Foreground Cyan
$GLOBAL:Guidelines++
} else {
if ($NuspecIconURL -cmatch "REPLACE"){
Write-Host "WARNING: ** <iconUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
Validate-URL "<iconUrl>" $NuspecIconURL
if ($GLOBAL:ValidURL){
Get-ImageDimensions
}
$IconExt=($NuspecIconURL | Select-String -Pattern $AcceptableIconExts)
if (!($IconExt)){
Write-Warning " ** <iconUrl> - Your package icon is NOT a .PNG or .SVG. This will trigger a message from the verifier:"
Write-Host ' ** Suggestion: As per the packaging guidelines icons should be either a png or svg file.' -Foreground Cyan
$GLOBAL:Suggestions++
}
if ($NuspecIconURL -match "raw.githubusercontent"){
if ($UpdateImageURLs) {
$NuspecIconURL=(Update-CDNURL "$NuspecIconURL")
Write-Host " ** <iconUrl> - URL updated to: `n $NuspecIconURL" -Foreground Green
} else {
Write-Warning " ** <iconUrl> - uses a GitHub raw link. Please use a CDN such as:"
Write-Host " ** $CDNlist" -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateImageURLs to update it." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
if ($NuspecIconURL -match "cdn.rawgit.com"){
if ($UpdateImageURLs) {
$NuspecIconURL=(Update-CDNURL "$NuspecIconURL")
Write-Host " ** <iconUrl> - URL updated to: `n $NuspecIconURL" -Foreground Green
} else {
Write-Warning " ** <iconUrl> - uses RawGit which will be going offline October 2019. Please change to a CDN such as:"
Write-Host " ** $CDNlist" -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateImageURLs to update it." -Foreground Cyan
$GLOBAL:Suggestions++
}
}
}
# <id> checks
if (!($NuspecID)) {
Write-Host "WARNING: ** <id> - element is empty, this element is a requirement." -Foreground Red
$GLOBAL:Required++
} else {
if (($NuspecID.Length -gt 20) -and (!$NuspecID.Contains("-")) -and (!$NuspecID.Contains("."))) {
Write-Warning " ** <id> - is greater than 20 characters. This will trigger a message from the verifier:"
Write-Host " ** Note: If this is a new package that has never been approved, moderators will review and reject the`n package for one that will be pushed with a new id that meets the package naming guidelines." -Foreground Cyan
$GLOBAL:Notes++
}
if ($NuspecID -cmatch "[A-Z]") {
Write-Warning " ** <id> - includes UPPERcase letters."
$GLOBAL:Guidelines++
}
if (($NuspecID.Contains(".")) -and (!$NuspecID.Contains(".install")) -and (!$NuspecID.Contains(".portable")) -and (!$NuspecID.Contains(".extension"))) {
Write-Warning " ** <id> - includes a '.'. This will trigger a message from the verifier:"
Write-Host " ** Note: The package id includes dots (.). Usually the package id is separated by '-' instead of dots`n (except in the case of *.install and *.portable). The reviewer will ensure this is not a new package." -Foreground Cyan
$GLOBAL:Notes++
}
if ($NuspecID.Contains(".config")){
Write-Host "WARNING: ** <id> - includes a '.config'. This is not allowed." -Foreground Red
$GLOBAL:Required++
}
}
# <licenseUrl> checks
if (!($NuspecLicenseURL)) {
Write-Warning " ** <licenseUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host " ** Guideline: The licenseUrl should be added if there is one. Please correct this in the nuspec,`n if applicable." -Foreground Cyan
$GLOBAL:Guidelines++
} else {
if ($NuspecLicenseURL -eq $NuspecprojectUrl) {
Write-Warning " ** <licenseUrl> - is the same as <projectUrl>. This will trigger a message from the verifier:"
Write-Host " ** Guideline: The licenseUrl should not usually be an exact match to softwareUrl. Please correct this in the`n nuspec, if applicable. ." -Foreground Cyan
$GLOBAL:Guidelines++
}
if ($NuspecLicenseURL -cmatch "REMOVE"){
Write-Host "WARNING: ** <licenseUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
} else {
Validate-URL "<licenseUrl>" $NuspecLicenseURL
}
}
# <mailingListUrl> checks
if (!($NuspecMailingListURL)) {
Write-Warning " ** <mailingListUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Suggestion: mailingListUrl - points to the forum or email list group for the software' -Foreground Cyan
$GLOBAL:Suggestions++
} else {
Validate-URL "<mailingListUrl>" $NuspecMailingListURL
}
# <owners> checks
if (!($NuspecOwners)) {
Write-Host "WARNING: ** <owners> element is empty, this element is a requirement." -Foreground Red
$GLOBAL:Required++
} else {
if ($NuspecID -cmatch "REPLACE"){
Write-Host "WARNING: ** <owners> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
if ($NuspecAuthors -eq $NuspecOwners){
Write-Warning " ** <owners> and <authors> elements are the same. This will trigger a message from the verifier:"
Write-Host " ** Note: The package maintainer field (owners) matches the software author field (authors) in the nuspec.`n The reviewer will ensure that the package maintainer is also the software author." -Foreground Cyan
$GLOBAL:Notes++
}
}
# <packageSourceUrl> checks
if (!($NuspecPackageSourceURL)) {
Write-Warning " ** <packageSourceUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host " ** Guideline: The nuspec has been enhanced to allow packageSourceUrl, pointing to the url where the package`n source resides. This is a strong guideline because it simplifies collaboration.`n Please add it to the nuspec." -Foreground Cyan
$GLOBAL:Guidelines++
} else {
if ($NuspecPackageSourceURL -cmatch "packageSourceUrl"){
Write-Host "WARNING: ** <packageSourceUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
} else {
Validate-URL "<packageSourceUrl>" $NuspecPackageSourceURL
}
}
# <projectSourceUrl> checks
if (!$NuspecProjectSourceURL) {
Write-Warning " ** <projectSourceUrl> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Suggestion: projectSourceUrl - points to the location of the underlying software source' -Foreground Cyan
$GLOBAL:Suggestions++
} else {
if ($NuspecProjectSourceURL -match "Software Source Location"){
Write-Host "WARNING: ** <projectSourceUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
} else {
Validate-URL "<projectSourceUrl>" $NuspecProjectSourceURL
}
if ($NuspecProjectURL -eq $NuspecProjectSourceURL){
Write-Warning " ** <projectUrl> and <projectSourceUrl> elements are the same. This will trigger a message from the verifier:"
Write-Host " ** Guideline: ProjectUrl and ProjectSourceUrl are typically different, but not always. Please ensure`n that projectSourceUrl is pointing to software source code or remove the field from the nuspec." -Foreground Cyan
$GLOBAL:Guidelines++
}
}
# <projectUrl> checks
if (!($NuspecProjectURL)) {
Write-Host "WARNING: ** <projectUrl> - element is empty. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: ProjectUrl (projectUrl) in the nuspec file is required. Please add it to the nuspec." -Foreground Cyan
$GLOBAL:Required++
} else {
if ($NuspecProjectURL -cmatch "REMOVE"){
Write-Host "WARNING: ** <projectUrl> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
} else {
Validate-URL "<projectUrl>" $NuspecProjectURL
}
}
# <provides> checks - Built for the future
#if (!($NuspecProvides)) {Write-Warning " ** <provides> element is empty"}
# <releaseNotes> checks
if (!($NuspecReleaseNotes)) {
Write-Warning " ** <releaseNotes> - element is empty. This will trigger a message from the verifier:"
Write-Host " ** Guideline: Release Notes (releaseNotes) are a short description of changes in each version of a package.`n Please include releasenotes in the nuspec. NOTE: To prevent the need to continually update this field,`n providing a URL to an external list of Release Notes is perfectly acceptable." -Foreground Cyan
$GLOBAL:Guidelines++
} else {
Check-Markdown "<releaseNotes>" $NuspecReleaseNotes
if ($NuspecReleaseNotes -cmatch "REPLACE"){
Write-Host "WARNING: ** <releaseNotes> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
# <replaces> checks - Built for the future
#if (!($NuspecReplaces)) {Write-Warning " ** <replaces> element is empty."}
# <requireLicenseAcceptance> checks
if (!($NuspecRequireLicenseAcceptance)) {
Write-Host "FYI: ** <requireLicenseAcceptance> - element is empty." -Foreground Yellow
$GLOBAL:FYIs++
} else {
if (($NuspecRequireLicenseAcceptance -eq "true") -and (!($NuspecLicenseURL))) {
Write-Host "WARNING: ** <requireLicenseAcceptance> is set to true but <licenseUrl> is empty." -Foreground Red
$GLOBAL:Required++
}
}
# <summary> checks
if (!($NuspecSummary)) {
Write-Warning " ** <summary> - element is empty. This will trigger a message from the verifier:"
Write-Host ' ** Guideline: Summary (summary) is a short explanation of the software. Please include summary in the nuspec.' -Foreground Cyan
$GLOBAL:Guidelines++
} else {
if ($NuspecSummary -cmatch "REPLACE"){
Write-Host "WARNING: ** <summary> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
# <tags> checks
if (!($NuspecTags)) {
Write-Host "WARNING: ** <tags> - element is empty." -Foreground Red
$GLOBAL:Required++
} else {
if ($NuspecTags -match ","){
Write-Host "WARNING: ** <tags> - tags are separated with commas. They should only be separated with spaces." -Foreground Red
$GLOBAL:Required++
}
if ($NuspecTags -match "admin"){
Write-Host "FYI: ** <tags> - there is a tag named ""admin"" which is now deemed unnecessary." -Foreground Yellow
Write-Host ' ** The majority of Chocolatey packages require admin rights to install, this is considered default behavior.' -Foreground Cyan
$GLOBAL:FYIs++
}
if ($NuspecTags -match "chocolatey"){
Write-Warning " ** <tags> - there is a tag named ""chocolatey"" which will trigger a message from the verifier:"
Write-Host ' ** Guideline: Tags (tags) should not contain 'chocolatey' as a tag. Please remove that in the nuspec.' -Foreground Cyan
$GLOBAL:Guidelines++
}
if ($NuspecTags -match "notsilent"){
Write-Warning " ** <tags> - there is a tag named ""notsilent"" which will trigger a message from the verifier:"
Write-Host ' ** Note: notSilent tag is being used. The reviewer will ensure this is being used appropriately. ' -Foreground Cyan
$GLOBAL:Notes++
}
if ($NuspecTags -cmatch "SEPARATED"){
Write-Host "WARNING: ** <tags> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
# <title> checks
if (!($NuspecTitle)) {
Write-Warning " ** <title> - element is empty."
$GLOBAL:Guidelines++
} else {
if ($NuspecTitle -eq $NuspecID){
Write-Warning " ** <title> and <id> are the same which will trigger a message from the verifier:"
Write-Host " ** Guideline: Title (title) matches id exactly. Please consider using something slightly more descriptive`n for the title in the nuspec." -Foreground Cyan
$GLOBAL:Guidelines++
}
}
# <version> checks
if (!($NuspecVersion)) {
Write-Host "WARNING: ** <version> - element is empty, this element is a requirement." -Foreground Red
$GLOBAL:Required++
} else {
if ($NuspecVersion -match "REPLACE"){
Write-Host "WARNING: ** <version> - contains templated values. This will trigger a message from the verifier:" -Foreground Red
Write-Host " ** Requirement: Nuspec file contains templated values which should be removed." -Foreground Cyan
$GLOBAL:Required++
}
}
#### BUG: error when run via Get-ChildItem | ?{if ($_.PSIsContainer){cls;cd $_.Name;cnc;cd ..;pause}} ###
#% : Input name "(dir name or package name)" cannot be resolved to a method.
#At C:\ProgramData\chocolatey\bin\CNC.ps1:1198 char:40
#+ Get-ChildItem "$path\*.ps1" -Recurse | % $_ {
#+ ~~~~~~
# + CategoryInfo : InvalidArgument: (S:\dev\GitHub\C...ateyinstall.ps1:PSObject) [ForEach-Object],PSArgumentException
# + FullyQualifiedErrorId : MethodNotFound,Microsoft.PowerShell.Commands.ForEachObjectCommand
# check PowerShell script files, out of scope, but nice to have
# This should probably be broken down into small functions
Get-ChildItem "$path\*.ps1" -Recurse | % $_ {
if ($debug){
write-host "PATH = $path" -foreground red -background white
write-host "FOREACH = $_" -foreground red -background white
}
$ScriptFile=(Get-Item $_).Name
$ScriptFile=$ScriptFile.toupper()
$HasPS1EAP=Check-PS1EAP $_
if (!$HasPS1EAP){
Add-PS1EAP $_
}
$PS1Encoding=Get-FileEncoding $_
if ($PS1Encoding -ne 'UTF-8 w/ BOM'){
if (!$UpdateScripts){
if ($scriptFile -match "UPDATE.PS1") {return}
Write-Warning " ** $ScriptFile - is encoded using $PS1Encoding."
Write-Host " ** PowerShell scripts need to be saved in UTF–8 with BOM." -Foreground Cyan
Write-Host " ** Suggestion: Consider running CNC -UpdateScripts to re-write $ScriptFile to UTF-8 w/ BOM." -Foreground Cyan
$GLOBAL:Suggestions++
} else {
Write-Host " ** $ScriptFile - will be converted to UTF-8 w/ BOM and saved." -Foreground Green
Update-PS1 $_
}
}
$ScriptError=Test-PowerShellSyntax ($_)
if ($ScriptError.SyntaxErrorsFound){
Write-Host "WARNING: ** $ScriptFile - has PowerShell syntax errors." -Foreground Red
$GLOBAL:Required++
}
if ($_ -match "install"){
$count=0
$InstallScript=Get-Content $_
$urlsfound = @()
$InstallScript | foreach-object {
if ($_ -match "\b(?:(?:https?|ftp|file)://|www\.|ftp\.)(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[-A-Z0-9+&@#/%=~_|$?!:,.])*(?:\([-A-Z0-9+&@#/%=~_|$?!:,.]*\)|[A-Z0-9+&@#/%=~_|$])"){
$urlsfound += $matches[0]
$validateurl=$urlsfound[$count]
Validate-URL "$ScriptFile" "$validateurl"
$count++
}
}
if ($InstallScript -match "msiexec"){
Write-Warning " ** $ScriptFile calls msiexec - This will trigger a message from the verifier:"
Write-Host " ** Note: Package automation scripts make use of msiexec. The reviewer will ensure there is a valid reason`n the package has not used the built-in helpers." -Foreground Cyan
$GLOBAL:Notes++
}
if (($InstallScript -match 'cinst ') -or ($InstallScript -match 'choco install') -or ($InstallScript -match 'choco upgrade') -or ($InstallScript -match ' cup ')){
Write-Host "WARNING: ** $ScriptFile - uses a cinst, choco install, cup, or choco upgrade command." -Foreground Red
Write-Host " ** In automation scripts (.ps1/.psm1), the package has used a chocolatey command that should not be used.`n Rather a dependency should be taken on a package. Please add dependencies to the nuspec." -Foreground Cyan
$GLOBAL:Required++
}
}
}
# Check for correctly named install script
Check-ScriptNames
# FossHub and SourceForge DL links check
Check-DiscouragedDownloadLinks
# Binaries checks
Check-Binaries
# OS index files check
Check-OSIndexFiles
#PNG checks
Check-PNGs
# Check for Internal Packaging Files
Check-PackageInternalFilesIncluded
# Git 'er done ------------------------------------------------------------------------------------------------
# Optimize any images files supported by PngOptimizerCL.exe
Run-PNGOptimizer
Write-Host "CNC found " -NoNewLine -Foreground Magenta
Write-Host "$GLOBAL:Required REQUIRED changes, " -NoNewLine -Foreground Red
Write-Host "$GLOBAL:Guidelines GUIDELINE changes, " -NoNewLine -Foreground Yellow
Write-Host "$GLOBAL:Suggestions SUGGESTED changes, " -NoNewLine -Foreground Yellow
Write-Host "$GLOBAL:Notes NOTES, " -NoNewLine -Foreground Yellow
Write-Host "$GLOBAL:FYIs FYIs, " -NoNewLine -Foreground Yellow
Write-Host "and made $GLOBAL:Fixes changes." -ForeGround Green
if ($GLOBAL:UpdateNuspec) {
if ($WhatIf){
Write-Host "CNC did NOT update $LocalnuspecFile, -WhatIf parameter was used." -Foreground Magenta
} else {
Update-nuspec
}
}
if ($UpdateScripts) {
if ($WhatIf){
Write-Host "CNC did NOT update your scripts, -WhatIf parameter was used." -Foreground Magenta
}
}
$ENV:ChocolateyPackageVersion=''
if ($recurse) {
#leave space between output if recursing
Write-Host "`n"
}
# main recurse foreach loop ends here
}
Write-Host "`nFound CNC.ps1 useful?" -Foreground White
Write-Host "Buy me a beer at https://www.paypal.me/bcurran3donations" -Foreground White
Write-Host "Become a patron at https://www.patreon.com/bcurran3" -Foreground White
return
# TDL
# Update CDN checking for "main" as well as "master" post 10/2020
# Check validity of URLs in description, checked by the package verifier as of 01/11/2020
# Reformat invalid Markdown headings automagically
# Move header, footer, and package notes into one XML config file
# Could use a CNC...not updated...-WhatIf message when -UpdateXMLNamespace and -WhatIf are used
# option of displaying useful tips and tweaks (AutoHotKey, BeCyIconGrabber, PngOptimizer, Regshot, service viewer program, Sumo, etc)
# Add option to save to an error log when recursivly checking files
# MAYBE do full params statement and get rid of args checking - low priority
# MAYBE check http links to see if https links are available and report if so - low priority
# MAYBE edit and re-write handling CDATA in description (not sure if there is a need)
# https://github.com/chocolatey/package-validator/wiki/ChecksumShouldBeUsed
# There may be more new validator checking that can be addressed
# What else?
---
$NuspecTitle packaged with pride by $NuspecOwners.
---
---
### [choco://$NuspecID](choco://$NuspecID)
To use choco:// protocol URLs, install [(unofficial) choco:// Protocol support ](https://chocolatey.org/packages/choco-protocol-support)
---
**[PACKAGE NOTES](https://github.com/$NuspecOwners/ChocolateyPackages/blob/master/$NuspecID/readme.md)**
Log in or click on link to see number of positives.
In cases where actual malware is found, the packages are subject to removal. Software sometimes has false positives. Moderators do not necessarily validate the safety of the underlying software, only that a package retrieves software from the official distribution point and/or validate embedded software against official distribution point (where distribution rights allow redistribution).
Chocolatey Pro provides runtime protection from possible malware.
Copyleft Bill Curran
CHANGELOG:
- 2020.09.21 - recurse switch has been added, thanks TheCakeIsNaOH!
- 2020.09.20 - An AddPackageNotes feature has been added, works the same as the AddHeader and AddFooter options. Updated nuspec URL errors as requirements to be fixed. Updated online package status messages. Added "PackageInternalFilesIncluded" checking. Minor cosmetic updates.
- 2020.09.15 - CNC will now ignore update.ps1 files.
- 2020.04.06.0001 - Updated CNC.cmd for ChocolateyToolsLocation handling. Fixed markdown heading error in CNCHeader.txt.
- 2020.04.06 - Better error handling when $env:ChocolateyToolsLocation is not defined. (Usually due to running under a different account than installed from.)
- 2020.01.16 - Updated message related to Markdown heading issues (now a requirement to fix), added Operating System index files checking, added verification that $env:ChocolateyToolsLocation exists (variable, not location)
- 2019.12.14 - Added checking for Markdown heading declarations that are incompatible with the Sept. 2019 changes to chocolatey.org. (Plan to autofix in a future update.)
- 2019.09.01 - Added Powershell v3 as a dependency due to Invoke-WebRequest use. Eliminated iwr error for new packages that weren't pushed to chocolatey.org yet, added reporting for packages that are in submitted or waiting for maintainer status, added to the common problems for not a valid XML file messages.
- 2019.08.26 - "Kicked out of bin release" - script installation endpoint changed. Now works from Command Prompt as well as PowerShell. Additional 7Zip supported formats checked for as binaries.
- 2019.08.22 - -UpdateXMLNamespace implemented (unreleased due to new moderation demands)
- 2019.08.21 - added checking for package release notes in description (unreleased due to new moderation demands)
- 2019.08.14 - now validates the nuspec as a valid XML file and reports common errors, notifies if there is a submitted/unapproved version on chocolatey.org, better checking for failed and trusted package notifications (unreleased due to new moderation demands)
- 2019.08.13 - minor fix to cinst checking in chocolateyinstall.ps1 (unreleased due to new moderation demands)
- 2019.03.04 - now checks for msiexec calls in scripts, checks for correctly named install script, checks that install scripts don't use choco commands, checks the XML namespace/schema, cosmetic changes
- 2019.02.22 - now notifies if the package is trusted and if the package is failing tests on chocolatey.org, -OptimizePNGs superseded by -OptimizeImages which will now optimize BMP, GIF, and TGA files as well as PNG files, added checking for FossHub download links in chocolateyInstall.ps1, more minor tweaks
- 2019.02.18 - now checks download URLs in install scripts, minor message updates
- 2019.02.16 - -UpdateScripts will re-write PowerShell scripts to UTF-8 w/BOM (even if EAP statement doesn't need to be added), now checks for and reports templated values, adding the XML UTF-8 check comment now implemented, more updates to summary, added checking for SourceForge download links in chocolateyInstall.ps1, -MakeBackups option to create *.CNC.bak files - this is a breaking change from v2019.01.29 where making backups was default, check for CDATA in description and parse it for problems but not change it when saving, some more tweaks that I forgot before writing this
- 2019.02.04 - New -UpdateScripts will add EAP statement to script files and re-write out to UTF-8 w/BOM, New -UseGitHack, -UseGitCDN, and -UsejsDelivr allows you to use image CDNs other than Staticaly (default), CNC now gives a summary count of warnings and fixes, now checks for header/footer before adding so duplicates aren't created, now checks all PowerShell scripts (previously only chocolateyinstall/uninstall), cosmetic changes to highlight required changes
- 2019.01.29 - you can now use the following tokens in your header and footer files: $NuspecAuthors, $NuspecID, $NuspecOwners, $NuspecTitle, and $NuspecVersion - they will be parsed and replaced with the values from your nuspec file, added checking iconUrl image dimensions, new -OptimizePNGs option to run PNGOptimizerCL (if installed via Chocolatey) on PNG files in nuspec dir, added checking for lack of BOM in install/uninstall scripts, added checking for $ErrorActionPreference statement in install/uninstall scripts, now aborts when there are multiple nuspec files found in the same directory, now aborts if nuspec appears corrupt, cosmetic enhancements, now makes a backup file upon updates.
- 2019.01.26 - "Birthday Release" CNC is now considered "Ready for Prime Time." (I still have more updates planned.) CNC can now write changes to your nuspec file including the iconUrl, description, and XML declaration (Finally!!!), added ability to update the XML declaration, added -UpdateAll and -Update options, updates are written as UTF-8 w/o BOM, cleaned up UTF-8 reporting, added PowerShell syntax error checking of chocolateyInstall.ps1 and chocolateyUninstall.ps1, new -WhatIf option for testing without saving changes, the normal minor tweaks and cosmetic changes. I will keep making it better though, of course.
- 2019.01.22 - added XML declaration and UTF-8 comment checking, better dependency version checking, a rare verifier message I missed
- 2019.01.15 - you can now specify a path to a directory containing a .nuspec file to check, misc minor tweaks
- 2019.01.13 - finished the dependencies checking, all verifier messages (guidelines, suggestions, and notes) now reporting in CNC
- 2019.01.12 - minor fixes
- 2019.01.09 - many more checks and warnings added, almost all known verifier guidelines, suggestions and notes added, some beautifications, added option to view Chocolatey validator info page, added optional image GitHub direct and RawGit URL conversions to Staticaly CDN URLs
- 2019.01.07 - added help, added option to open and view all URLs in your default browser, added options to view, edit, and add "standard" (template) headers and footers to the description (can't save yet), added reporting of standard header and footer if found, added more verifier messages, added checking for descriptions that are too large (>4,000), now checks for license files other than LICENSE.txt, probably more I don't remember :)
- 2019.01.04 - implemented included binary files checking and messages, laid out the groundwork for the future enhancements
- 2019.01.03 - fixed some URL checking handling that could cause PS errors, updated list of CDN recommendations, added checking for RawGit URLs in description, cosmetic updates
- 2018.12.22-2018-12.28 - initial release
ROADMAP:
- Update CDN checking for "main" as well as "master" post 10/2020
- Check validity of URLs in description, checked by the package verifier as of 01/11/2020
- Reformat invalid Markdown headings automagically
- Could use a CNC...not updated...-WhatIf message when -UpdateXMLNamespace and -WhatIf are used
- option of displaying useful tips and tweaks (AutoHotKey, BeCyIconGrabber, PngOptimizer, Regshot, service viewer program, Sumo, etc)
- MAYBE do full params statement and get rid of args checking - low priority
- MAYBE check http links to see if https links are available and report if so - low priority
- MAYBE edit and re-write handling CDATA in description (not sure if there is a need)
- https://github.com/chocolatey/package-validator/wiki/ChecksumShouldBeUsed
- add packaging tips/tweaks/etc
- What else? (PRs accepted)
-
- powershell (≥ 3.0)
Ground Rules:
- This discussion is only about (unofficial) Chocolatey .nuspec Checker (Script) and the (unofficial) Chocolatey .nuspec Checker (Script) package. If you have feedback for Chocolatey, please contact the Google Group.
- This discussion will carry over multiple versions. If you have a comment about a particular version, please note that in your comments.
- The maintainers of this Chocolatey Package will be notified about new comments that are posted to this Disqus thread, however, it is NOT a guarantee that you will get a response. If you do not hear back from the maintainers after posting a message below, please follow up by using the link on the left side of this page or follow this link to contact maintainers. If you still hear nothing back, please follow the package triage process.
- Tell us what you love about the package or (unofficial) Chocolatey .nuspec Checker (Script), or tell us what needs improvement.
- Share your experiences with the package, or extra configuration or gotchas that you've found.
- If you use a url, the comment will be flagged for moderation until you've been whitelisted. Disqus moderated comments are approved on a weekly schedule if not sooner. It could take between 1-5 days for your comment to show up.