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:
34,556
Downloads of v 2016.12.17:
530
Last Update:
17 Dec 2016
Package Maintainer(s):
Software Author(s):
- Miodrag Milić
Tags:
admin powershell module package chocolatey
Chocolatey Automatic Package Updater Module
This is not the latest version of Chocolatey Automatic Package Updater Module available.
- 1
- 2
- 3
2016.12.17 | Updated: 17 Dec 2016
Downloads:
34,556
Downloads of v 2016.12.17:
530
Maintainer(s):
Software Author(s):
- Miodrag Milić
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
Chocolatey Automatic Package Updater Module
2016.12.17
This is not the latest version of Chocolatey Automatic Package Updater Module available.
- 1
- 2
- 3
This Package Contains an Exempted Check
Not All Tests Have Passed
Deployment Method: Individual Install, Upgrade, & Uninstall
To install Chocolatey Automatic Package Updater Module, run the following command from the command line or from PowerShell:
To upgrade Chocolatey Automatic Package Updater Module, run the following command from the command line or from PowerShell:
To uninstall Chocolatey Automatic Package Updater Module, 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 au --internalize --version=2016.12.17 --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 au -y --source="'INTERNAL REPO URL'" --version="'2016.12.17'" [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 au -y --source="'INTERNAL REPO URL'" --version="'2016.12.17'"
$exitCode = $LASTEXITCODE
Write-Verbose "Exit code was $exitCode"
$validExitCodes = @(0, 1605, 1614, 1641, 3010)
if ($validExitCodes -contains $exitCode) {
Exit 0
}
Exit $exitCode
- name: Install au
win_chocolatey:
name: au
version: '2016.12.17'
source: INTERNAL REPO URL
state: present
See docs at https://docs.ansible.com/ansible/latest/modules/win_chocolatey_module.html.
chocolatey_package 'au' do
action :install
source 'INTERNAL REPO URL'
version '2016.12.17'
end
See docs at https://docs.chef.io/resource_chocolatey_package.html.
cChocoPackageInstaller au
{
Name = "au"
Version = "2016.12.17"
Source = "INTERNAL REPO URL"
}
Requires cChoco DSC Resource. See docs at https://github.com/chocolatey/cChoco.
package { 'au':
ensure => '2016.12.17',
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 by moderator ferventcoder on 27 Dec 2016.
AU is Powershell module that helps you to automate Chocolatey package updates.
Features
- Use only PowerShell to create automatic update script for given package.
- Automatically downloads installers and provides/verifies checksums for x32 and x64 versions.
- Verifies URLs, nuspec versions, remote repository existence etc.
- Can use global variables to change functionality.
- Sugar functions for Chocolatey package maintainers.
- Update single package or any subset of previously created AU packages with a single command.
- Multithread support when updating multiple packages.
- Plugin system when updating everything, with few integrated plugins to send email notifications, save results to gist and push updated packages to git repository.
#
# Module manifest for module 'AU'
#
# Generated by: Miodrag Milic
#
# Generated on: 17.12.2016.
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'AU.psm1'
# Version number of this module.
ModuleVersion = '2016.12.17'
# ID used to uniquely identify this module
GUID = 'b2cb6770-ecc4-4a51-a57a-3a34654a0938'
# Author of this module
Author = 'Miodrag Milic'
# Company or vendor of this module
CompanyName = 'Unknown'
# Copyright statement for this module
Copyright = '(c) 2016 Miodrag Milic. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Chocolatey Automatic Package Updater Module'
# Minimum version of the Windows PowerShell engine required by this module
PowerShellVersion = '5.0'
# Name of the Windows PowerShell host required by this module
# PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module
# DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @()
# Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @()
# Functions to export from this module
FunctionsToExport = 'Get-AUPackages', 'Get-RemoteChecksum', 'Push-Package', 'Test-Package',
'Update-AUPackages', 'Update-Package'
# Cmdlets to export from this module
CmdletsToExport = '*'
# Variables to export from this module
VariablesToExport = '*'
# Aliases to export from this module
AliasesToExport = 'gau', 'lsau', 'update', 'updateall'
# DSC resources to export from this module
# DscResourcesToExport = @()
# List of all modules packaged with this module
# ModuleList = @()
# List of all files packaged with this module
# FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
PrivateData = @{
PSData = @{
# Tags applied to this module. These help with module discovery in online galleries.
Tags = 'chocolatey', 'update'
# A URL to the license for this module.
LicenseUri = 'https://opensource.org/licenses/MIT'
# A URL to the main website for this project.
ProjectUri = 'https://github.com/majkinetor/au'
# A URL to an icon representing this module.
# IconUri = ''
# ReleaseNotes of this module
ReleaseNotes = 'https://github.com/majkinetor/au/blob/master/CHANGELOG.md'
} # End of PSData hashtable
} # End of PrivateData hashtable
# HelpInfo URI of this module
HelpInfoURI = 'https://github.com/majkinetor/au/blob/master/README.md'
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = ''
}
#requires -version 3
$paths = "Private", "Public"
foreach ($path in $paths) {
ls $PSScriptRoot\$path\*.ps1 | % { . $_ }
}
# Chocolatey Automatic Package Updater Module
This PowerShell module implements functions that can be used to automate [Chocolatey](https://chocolatey.org) package updates.
To learn more about Chocolatey automatic packages, please refer to the relevant [documentation](https://github.com/chocolatey/choco/wiki/AutomaticPackages).
To see AU in action see [video tutorial](https://www.youtube.com/watch?v=m2XpV2LxyEI&feature=youtu.be).
## Features
- Use only PowerShell to create automatic update script for given package.
- Automatically downloads installers and provides/verifies checksums for x32 and x64 versions.
- Verifies URLs, nuspec versions, remote repository existence etc.
- Can use global variables to change functionality.
- Sugar functions for Chocolatey package maintainers.
- Update single package or any subset of previously created AU packages with a single command.
- Multithread support when updating multiple packages.
- Plugin system when updating everything, with few integrated plugins to send email notifications, save results to gist and push updated packages to git repository.
## Installation
AU module requires minimally PowerShell version 5: `$host.Version -ge '5.0'`
To install it, use one of the following methods:
- PowerShell Gallery: [`Install-Module au`](https://www.powershellgallery.com/packages/AU).
- Chocolatey: [`cinst au`](https://chocolatey.org/packages/au).
- [Download](https://github.com/majkinetor/au/releases/latest) latest 7z package or latest build [artifact](https://ci.appveyor.com/project/majkinetor/au/build/artifacts).
To quickly start using AU, fork [au-packages-template](https://github.com/majkinetor/au-packages-template) repository and rename it to `au-packages`.
**NOTE**: All module functions work from within specific root folder. The folder contains all of your Chocolatey packages.
## Creating the package updater script
The AU uses `update.ps1` script that package maintainers should create in the package directory. No templates are used, just plain PowerShell.
To write the package update script, it is generally required to implement 2 functions: `au_GetLatest` and `au_SearchReplace`.
### `au_GetLatest`
This function is used to get the latest package information.
As an example, the following function uses [Invoke-WebRequest](https://technet.microsoft.com/en-us/library/hh849901.aspx?f=255&MSPPError=-2147217396) to download a page (#1). After that it takes a `href` attribute from the first page link that ends with `.exe` word as a latest URL for the package (#2). Then it conveniently splits the URL to get the latest version for the package (#3), a step that is highly specific to the URL but very easy to determine.
```powershell
function global:au_GetLatest {
$download_page = Invoke-WebRequest -Uri $releases #1
$regex = '.exe$'
$url = $download_page.links | ? href -match $regex | select -First 1 -expand href #2
$version = $url -split '-|.exe' | select -Last 1 -Skip 2 #3
return @{ Version = $version; URL32 = $url }
}
```
The returned version is later compared to the one in the nuspec file and if remote version is higher, the files will be updated. The returned keys of this HashTable are available via global variable `$global:Latest` (along with some keys that AU generates). You can put whatever data you need in the returned HashTable - this data can be used later in `au_SearchReplace`.
### `au_SearchReplace`
Function returns HashTable containing search and replace data for any package file in the form:
```powershell
@{
file_path1 = @{
search1 = replace1
...
searchN = replaceN
}
file_path2 = @{ ... }
...
}
```
Search and replace strings are operands for PowerShell [replace](http://www.regular-expressions.info/powershell.html) operator. You do not have to write them most of the time however, they are rarely changed.
File paths are relative to the package directory. The function can use `$global:Latest` variable to get any type of information obtained when `au_GetLatest` was executed along with some AU generated data such as `PackageName`, `NuspecVersion` etc.
The following example illustrates the usage:
```powershell
function global:au_SearchReplace {
@{
"tools\chocolateyInstall.ps1" = @{
"(^[$]url32\s*=\s*)('.*')" = "`$1'$($Latest.URL32)'" #1
"(^[$]checksum32\s*=\s*)('.*')" = "`$1'$($Latest.Checksum32)'" #2
}
}
}
```
Here, line of the format `$url32 = '<package_url>'` in the file `tools\chocolateyInstall.ps1` will have its quoted string replaced with latest URL (#1). The next line replaces value of the variable `$checksum32` on the start of the line with the latest checksum that is automatically injected in the `$Latest` variable by the AU framework (#2). Replacement of the latest version in the nuspec file is handled automatically.
**NOTE**: The search and replace works on lines, multiple lines can not be matched with single regular expression.
### Update
With above functions implemented calling the `Update-Package` (alias `update`) function from the AU module will update the package when needed.
You can then update the individual package by running the appropriate `update.ps1` script from within the package directory:
```
PS C:\chocolatey\dngrep> .\update.ps1
dngrep - checking updates using au version 2016.9.14
nuspec version: 2.8.15.0
remote version: 2.8.16.0
New version found
Automatic checksum started
Downloading dngrep 32 bit
from 'https://github.com/dnGrep/dnGrep/releases/download/v2.8.16.0/dnGREP.2.8.16.x86.msi'
Download of dnGREP.2.8.16.x86.msi (3.36 MB) completed.
Package downloaded and hash calculated for 32 bit version
Downloading dngrep 64 bit
from 'https://github.com/dnGrep/dnGrep/releases/download/v2.8.16.0/dnGREP.2.8.16.x64.msi'
Download of dnGREP.2.8.16.x64.msi (3.39 MB) completed.
Package downloaded and hash calculated for 64 bit version
Updating files
dngrep.nuspec
updating version: 2.8.15.0 -> 2.8.16.0
tools\chocolateyInstall.ps1
(^[$]url32\s*=\s*)('.*') = $1'https://github.com/dnGrep/dnGrep/releases/download/v2.8.16.0/dnGREP.2.8.16.x86.msi'
(^[$]url64\s*=\s*)('.*') = $1'https://github.com/dnGrep/dnGrep/releases/download/v2.8.16.0/dnGREP.2.8.16.x64.msi'
(^[$]checksum32\s*=\s*)('.*') = $1'CE4753735148E1F48FE0E1CD9AA4DFD019082F4F43C38C4FF4157F08D346700C'
(^[$]checksumType32\s*=\s*)('.*') = $1'sha256'
(^[$]checksum64\s*=\s*)('.*') = $1'025BD4101826932E954AACD3FE6AEE9927A7198FEEFFB24F82FBE5D578502D18'
(^[$]checksumType64\s*=\s*)('.*') = $1'sha256'
Attempting to build package from 'dngrep.nuspec'.
Successfully created package 'dngrep.2.8.16.0.nupkg'
Package updated
```
This is best understood via the example - take a look at the real life package [installer script](https://github.com/majkinetor/au-packages/blob/master/dngrep/tools/chocolateyInstall.ps1) and its [AU updater](https://github.com/majkinetor/au-packages/blob/master/dngrep/update.ps1).
### Checks
The `update` function does the following checks:
- The `$Latest.Version` will be checked to match a valid nuspec pattern.
- Any hash key that starts with the word `Url`, will be checked for existence and MIME textual type, since binary is expected here.
- If the remote version is higher then the nuspec version, the Chocolatey site will be checked for existence of this package version (this works for unpublished packages too). This allows multiple users to update same set of packages without a conflict. Besides, this feature makes it possible not to persist state between the updates as once the package is updated and pushed, the next update will not push the package again. To persist the state of updated packages you can use for instance [Git](https://github.com/majkinetor/au/blob/master/AU/Plugins/Git.ps1) plugin which saves the updated and published packages to the git repository.
- The regex patterns in `au_SearchReplace` will be checked for existence.
If any of the checks fails, package will not get updated. This feature releases you from the worries about how precise is your pattern match in both `au_` functions - if for example, a vendor site changes, the package update will fail because of the wrongly parsed data.
For some packages, you may want to disable some of the checks by specifying additional parameters of the `update` function (not all can be disabled):
| Parameter | Description |
| --------- | ------------ |
| `NoCheckUrl` | Disable URL checks |
| `NoCheckChocoVersion` | Disable the Chocolatey site check |
| `ChecksumFor none` | Disable automatic checksum |
### Automatic checksums
When new version is available, the `update` function will by default download both x32 and x64 versions of the installer and calculate the desired checksum. It will inject this info in the `$global:Latest` HashTable variable so you can use it via `au_SearchReplace` function to update hashes. The parameter `ChecksumFor` can contain words `all`, `none`, `32` or `64` to further control the behavior.
You can disable this feature by calling update like this:
update -ChecksumFor none
You can define the hash algorithm by returning corresponding `ChecksumTypeXX` hash keys in the `au_GetLatest` function:
return @{ ... ChecksumType32 = 'sha512'; ... }
If the checksum is actually obtained from the vendor's site, you can provide it along with its type (SHA256 by default) by returning corresponding `ChecksumXX` hash keys in the `au_GetLatest` function:
return @{ ... Checksum32 = 'xxxxxxxx'; ChecksumType32 = 'md5'; ... }
If the `ChecksumXX` hash key is present, the AU will change to checksum verification mode - it will download the installer and verify that its checksum matches the one provided. If the key is not present, the AU will calculate hash with the given `ChecksumTypeXX` algorithm.
**NOTE**: This feature works by monkey patching the `Get-ChocolateyWebFile` helper function and invoking the `chocolateyInstall.ps1` afterwards for the package in question. This means that it downloads the files using whatever method is specified in the package installation script.
### Manual checksums
Sometimes invoking `chocolateyInstall.ps1` during the automatic checksum could be problematic so you need to disable it using update option `ChecksumFor none` and get the checksum some other way. Function `Get-RemoteChecksum` can be used to simplify that:
```powershell
$url = $download_page.links | ? href -match '\.exe$' | select -First 1 -expand href
$version = $url -split '/' | select -Last 1 -Skip 1
@{
URL32 = $url
Version = $version
Checksum = Get-RemoteChecksum $url
}
```
### Force update
You can force the update even if no new version is found by using the parameter `Force` (or global variable `$au_Force`). This can be useful for testing the update and bug fixing, recalculating the checksum after the package was created and already pushed to Chocolatey or if URLs to installer changed without change in version.
**Example**:
```
PS C:\chocolatey\cpu-z.install> $au_Force = $true; .\update.ps1
cpu-z.install - checking updates
nuspec version: 1.77
remote version: 1.77
No new version found, but update is forced
Automatic checksum started
...
Updating files
cpu-z.install.nuspec
updating version using Chocolatey fix notation: 1.77 -> 1.77.0.20160814
...
```
Force option changes how package version is used. Without force, the `NuspecVersion` determines what is going on. Normally, if `NuspecVersion` is lower or equal then the `RemoteVersion` update happens. With `Force` this changes:
1. If `NuspecVersion` is lower then `RemoteVersion`, Force is ignored and update happens as it would normally
2. If `NuspecVersion` is the same as the `RemoteVersion`, the version will change to chocolatey fix notation.
3. If the `NuspecVersion` is already using chocolatey fix notation, the version will be updated to fix notation for the current date.
4. If the `NuspecVersion` is higher then the `RemoteVersion` update will happen but `RemoteVersion` will be used.
Points 2-4 do not apply if you set the explicit version using the variable `au_Version`.
[Chocolatey fix notation](https://github.com/chocolatey/choco/wiki/CreatePackages#package-fix-version-notation) changes a version so that current date is added in the _revision_ component of the package version in the format `yyyyMMdd`. More precisely:
- chocolatey _fix version_ always ends up in to the _Revision_ part of the package version;
- existing _fix versions_ are changed to contain the current date;
- if _revision_ part is present in the package version and it is not in the _chocolatey fix notation_ form, AU will keep the existing version but notify about it;
Force can be triggered also from the `au_GetLatest` function. This may be needed if remote version doesn't change but there was nevertheless change on the vendor site. See the [example](https://github.com/majkinetor/au-packages/blob/master/cpu-z.install/update.ps1#L18-L39) on how to update the package when remote version is unchanged but hashsum of the installer changes.
### Global variables
To avoid changing the `./update.ps1` when troubleshooting or experimenting you can set up any **already unset** `update` parameter via global variable. The names of global variables are the same as the names of parameters with the prefix `au_`. As an example, the following code will change the update behavior so that URL is not checked for existence and MIME type and update is forced:
$au_NoCheckUrl = $au_Force = $true
./update.ps1
This is the same as if you added the parameters to `update` function inside the `./update.ps1` script:
update -NoCheckUrl -Force
however, its way easier to setup global variable with manual intervention on multiple packages.
### Reusing the AU updater with metapackages
Metapackages can reuse an AU updater of its dependency by the following way:
- In the dependent updater, instead of calling the `update` directly, use construct:
```
if ($MyInvocation.InvocationName -ne '.') { update ... }
```
- In the metapackage updater dot source the dependent updater and override `au_SearchReplace`.
This is best understood via example - take a look at the [cpu-z](https://github.com/majkinetor/au-packages/blob/master/cpu-z/update.ps1) AU updater which uses the updater from the [cpu-z.install](https://github.com/majkinetor/au-packages/blob/master/cpu-z.install/update.ps1) package on which it depends. It overrides the `au_SearchReplace` function and the `update` call but keeps the `au_GetLatest`.
## Updating all packages
You can update all packages and optionally push them to the Chocolatey repository with a single command. Function `Update-AUPackages` (alias `updateall`) will iterate over `update.ps1` scripts and execute each in a separate thread. If it detects that a package is updated it will optionally try to push it to the Chocolatey repository and may also run configured plugins.
For the push to work, specify your Choocolatey API key in the file `api_key` in the script's directory (or its parent directory) or set the environment variable `$Env:api_key`. If none provided cached nuget key will be used.
The function will search for packages in the current directory. To override that, use global variable `$au_Root`:
PS> $au_root = 'c:\chocolatey_packages`
PS> $Options = @{
Timeout = 10
Threads = 15
Push = $true
}
PS> updateall -Options $Options
Updating 6 automatic packages at 2016-09-16 22:03:33
Push is enabled
copyq is updated to 2.6.1 and pushed
dngrep had errors during update
Can't validate URL 'https://github.com/dnGrep/dnGrep/releases/download/v2.8.16.0/dnGREP.2.8.16.x64.msi'
Exception calling "GetResponse" with "0" argument(s): "The operation has timed out"
eac has no updates
pandoc has no updates
plantuml has no updates
yed had errors during update
Can't validate URL 'https://www.yworks.com'
Invalid content type: text/html
Finished 6 packages after .32 minutes.
1 updated and 1 pushed.
2 errors - 2 update, 0 push.
Use `updateall` parameter `Name` to specify package names via glob, for instance `updateall [a-d]*` would update only packages which names start with the letter 'a' trough 'd'. Add `Push` among options to push successfully built packages to the chocolatey repository.
Take a look at the [real life example](http://tiny.cc/v1u1ey) of the update script. To see all available options for `updateall` type `man updateall -Parameter Options`.
### Plugins
It is possible to specify a custom user logic in `Options` parameter - every key that is of type `[HashTable]` will be considered plugin with the PowerShell script that is named the same as the key. The following code shows how to use 5 integrated plugins:
```powershell
$Options = [ordered]@{
Timeout = 100
Threads = 15
Push = $true
# Save text report in the local file report.txt
Report = @{
Type = 'text'
Path = "$PSScriptRoot\report.txt"
}
# Then save this report as a gist using your api key and gist id
Gist = @{
ApiKey = $Env:github_api_key
Id = $Env:github_gist_id
Path = "$PSScriptRoot\report.txt"
}
# Persist pushed packages to your repository
Git = @{
User = ''
Password = $Env:github_api_key
}
# Then save run info which can be loaded with Import-CliXML and inspected
RunInfo = @{
Path = "$PSScriptRoot\update_info.xml"
}
# Finally, send an email to the user if any error occurs and attach previously created run info
Mail = if ($Env:mail_user) {
@{
To = $Env:mail_user
Server = 'smtp.gmail.com'
UserName = $Env:mail_user
Password = $Env:mail_pass
Port = 587
EnableSsl = $true
Attachment = "$PSScriptRoot\$update_info.xml"
UserMessage = 'Save attachment and load it for detailed inspection: <code>$info = Import-CliXCML update_info.xml</code>'
}
} else {}
}
```
The plugins above - `Report`, `Gist`,`Git`,`RunInfo` and `Mail` - are executed in the given order (hence the `[ordered]` flag) and AU passes them given options and saves the run results.
To add custom plugins, specify additional plugin search path via `$Options.PluginPath`. Plugin is a normal PowerShell script and apart from parameters given in its HashTable the AU will send it one more parameter `$Info` that contains current run info. The name of the script file must be the same as that of the key which value is used to pass the parameters to the plugin. If a key with the value of type `[HashTable]` doesn't point to existing PowerShell script it is not considered to be an AU plugin.
To temporary disable plugins use `updateall` option `NoPlugins` or global variable `$au_NoPlugins`.
To temporary exclude the AU package from `updateall` procedure add `_` prefix to the package directory name.
You can also execute a custom script via ScriptBlock specified via `BeforeEach` and `AfterEach` options. They will receive 2 parameters - package name and Options HashTable which you can use to pass any other parameter.
For more information take a look at the wiki section about [plugins](https://github.com/majkinetor/au/wiki/Plugins).
### Make a script
Its desirable to put everything in a single script `update_all.ps1` so it can be scheduled and called with the given options. Rename `update_all_default.ps1` and uncomment and set the options you need.
To make a local scheduled task, use the following code in the directory where your `update_all.ps1` script is found to install it:
$At = '03:00'
schtasks /create /tn "Update-AUPackages" /tr "powershell -File '$pwd\update_all.ps1'" /sc daily /st $At
Its preferable to run the updater on [AppVeyor](https://github.com/majkinetor/au/wiki/AppVeyor).
### Ignoring specific errors
When errors occur during the update, email will be sent to the owner and report will contain [errors](https://gist.github.com/gep13/bd2eaa76f2a9ab739ca0544c502dca6e/c71d4eb3f6de2848f41c1b92e221737d775f0b6f#errors) section. Some network errors are expectable and you may want to ignore them - package that failed will get updated in one of the subsequent runs anyway. To ignore an error, use try/catch block around update and return 'ignore' word from the `./update.ps1` script:
try {
update
} catch {
$ignore = 'Unable to connect to the remote server'
if ($_ -match $ignore) { Write-Host $ignore; 'ignore' } else { throw $_ }
}
The package will get shown in the report as [ignored](https://gist.github.com/gep13/bd2eaa76f2a9ab739ca0544c502dca6e/db5313020d882945d8fcc3a10f5176263bb837a6#quicktime) and no errors will be shown.
## Other functions
Apart from the functions used in the updating process, there are few suggars for regular maintenance of the package:
- Test-Package
Quickly test install and/or uninstall of the package from the current directory with optional parameters. This function can be used to start testing in [chocolatey-test-environment](https://github.com/majkinetor/chocolatey-test-environment) via `Vagrant` parameter.
- Push-Package
Push the latest package using your API key.
- Get-AuPackages (alias `gau` or `lsau`)
Returns the list of the packages which have `update.ps1` script in its directory and which name doesn't start with '_'.
# Author: Miodrag Milic <[email protected]>
# Last Change: 10-Nov-2016.
<#
.SYNOPSIS
Create update history as markdown report using git commit log.
.DESCRIPTION
Shows one date per line and all of the packages pushed to the Chocolatey community repository during that day.
First letter of the package name links to report (produced by the Report plugin), the rest links to actuall
commit (produced by the Git plugin).
#>
param(
$Info,
# Gist id, leave empty to create a new gist
[string] $Id,
# Github ApiKey, create in Github profile -> Settings -> Personal access tokens -> Generate new token
# Make sure token has 'gist' scope set.
[string] $ApiKey,
# File paths to attach to gist
[string[]] $Path,
# Gist description
[string] $Description = "Update-AUPackages Report #powershell #chocolatey"
)
# Create gist
$gist = @{
description = $Description
public = $true
files = @{}
}
ls $Path | % {
$name = Split-Path $_ -Leaf
$content = gc $_ -Raw
$gist.files[$name] = @{content = "$content"}
}
# request
$uri = 'https://api.github.com/gists'
$params = @{
ContentType = 'application/json'
Method = if ($Id) { "PATCH" } else { "POST" }
Uri = if ($Id) { "$uri/$Id" } else { $uri }
Body = $gist | ConvertTo-Json
UseBasicparsing = $true
}
if ($ApiKey) {
$params.Headers = @{
Authorization = 'Basic ' + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($ApiKey))
}
}
$res = iwr @params
#https://api.github.com/gists/a700c70b8847b29ebb1c918d47ee4eb1/211bac4dbb707c75445533361ad12b904c593491
$id = (($res.Content | ConvertFrom-Json).history[0].url -split '/')[-2,-1] -join '/'
"https://gist.github.com/$id"
# Author: Miodrag Milic <[email protected]>
# Last Change: 09-Nov-2016.
# https://www.appveyor.com/docs/how-to/git-push/
param(
$Info,
# Git username
[string] $User,
# Git password. You can use Github Token here if you omit username.
[string] $Password,
#Force git commit when package is updated but not pushed.
[switch] $Force
)
[array]$packages = if ($Force) { $Info.result.updated } else { $Info.result.pushed }
if ($packages.Length -eq 0) { Write-Host "No package updated, skipping"; return }
$root = Split-Path $packages[0].Path
pushd $root
$origin = git config --get remote.origin.url
$origin -match '(?<=:/+)[^/]+' | Out-Null
$machine = $Matches[0]
if ($User -and $Password) {
Write-Host "Setting credentials for: $machine"
if ( "machine $server" -notmatch (gc ~/_netrc)) {
Write-Host "Credentials already found for machine: $machine"
}
"machine $machine", "login $User", "password $Password" | Out-File -Append ~/_netrc -Encoding ascii
} elseif ($Password) {
Write-Host "Setting oauth token for: $machine"
git config --global credential.helper store
Add-Content "$env:USERPROFILE\.git-credentials" "https://${Password}:[email protected]$machine`n"
}
Write-Host "Executing git pull"
git checkout -q master
git pull -q origin master
Write-Host "Adding updated packages to git repository: $( $packages | % Name)"
$packages | % { git add -u $_.Name }
git status
Write-Host "Commiting"
$message = "AU: $($packages.Length) updated - $($packages | % Name)"
$gist_url = $Info.plugin_results.Gist -split '\n' | select -Last 1
git commit -m "$message`n[skip ci] $gist_url" --allow-empty
Write-Host "Pushing changes"
git push -q
popd
# Author: Miodrag Milic <[email protected]>
# Last Change: 09-Dec-2016.
<#
.SYNOPSIS
Create update history as markdown report
.DESCRIPTION
Shows one date per line and all of the packages pushed to the Chocolatey community
repository during that day. First letter of the package name links to report
(produced by the Report plugin), the rest links to the actuall commit (produced by the Git plugin).
#>
param(
$Info,
#Number of dates to show in the report
$Lines=30,
#Github user repository, used to create commit links
$Github_UserRepo = 'chocolatey/chocolatey-coreteampackages',
#File path where to save the markdown report
$Path = "Update-History.md"
)
Write-Host "Saving history to $Path"
$res=[ordered]@{}
$log = git --no-pager log -q --grep '^AU: ' --date iso | Out-String
$all_commits = $log | sls 'commit(.|\n)+?(?=\ncommit )' -AllMatches
foreach ($commit in $all_commits.Matches.Value) {
$commit = $commit -split '\n'
$id = $commit[0].Replace('commit','').Trim().Substring(0,7)
$date = $commit[2].Replace('Date:','').Trim()
$date = ([datetime]$date).Date.ToString("yyyy-MM-dd")
$report = $commit[5].Replace('[skip ci]','').Trim()
[array] $packages = ($commit[4] -replace '^\s+AU:.+?(-|:) |\[skip ci\]').Trim().ToLower()
$packages_md = $packages -split ' ' | % {
$first = $_.Substring(0,1).ToUpper(); $rest = $_.Substring(1)
if ($report) {
"[$first]($report)[$rest](https://github.com/$Github_UserRepo/commit/$id)"
} else {
"[$_](https://github.com/$Github_UserRepo/commit/$id)"
}
}
if (!$res.Contains($date)) { [email protected]() }
$res.$date += $packages_md
}
$res = $res.Keys | select -First $Lines | % { $r=[ordered]@{} } { $r[$_] = $res[$_] } {$r}
$history = @"
# Update History
Showing maximum $Lines dates.
Click on the first letter of the package name to see its report and on the remaining letters to see its git commit.
---
"@
foreach ($kv in $res.GetEnumerator()) { $history += "`n{0} ({2}) {1}`n" -f "**$($kv.Key)**", "$($kv.Value -join ' – ')", $kv.Value.Length }
$history | Out-File $Path
# Author: Miodrag Milic <[email protected]>
# Last Change: 12-Nov-2016.
param(
$Info,
[string] $To,
[string] $Server,
[string] $UserName,
[string] $Password,
[int] $Port,
[string[]] $Attachment,
[switch] $EnableSsl,
[string] $UserMessage,
# Do not send only on errors
[switch] $SendAlways
)
if (($Info.error_count.total -eq 0) -and !$SendAlways) {
Write-Host 'Mail not sent as there are no errors (override with SendAlways param)'
return
}
$errors_word = if ($Info.error_count.total -eq 1) {'error'} else {'errors' }
# Create mail message
$from = "[email protected]{0}.{1}" -f $Env:UserName, $Env:ComputerName
$msg = New-Object System.Net.Mail.MailMessage $from, $To
$msg.IsBodyHTML = $true
if ($Info.error_count.total -eq 0) {
$msg.Subject = "AU: run was OK"
$msg.Body = $Info.stats | Out-String
}
else {
$context = "with errors "
$msg.Subject = "AU: $($info.error_count.total) $errors_word during update"
$msg.Body = @"
<body><pre>
$($Info.error_count.total) $errors_word during update.
$UserMessage
$($info.error_info | Out-String)
</pre></body>
"@
}
$Attachment | % { if ($_) { $msg.Attachments.Add($_)} }
# Send mail message
$smtp = new-object Net.Mail.SmtpClient($Server)
if ($UserName) { $smtp.Credentials = new-object System.Net.NetworkCredential($UserName, $Password) }
if ($Port) { $smtp.Port = $Port }
$smtp.EnableSsl = $EnableSsl
$smtp.Send($msg)
Write-Host "Mail ${context}sent to $To"
# Author: Miodrag Milic <[email protected]>
# Last Change: 10-Nov-2016.
<#
.SYNOPSIS
Create different types of reports about the current run.
.DESCRIPTION
The plugin saves state of all packages in a file that can be used locally or
uploaded via other plugins to remote (such as Gist or Mail).
#>
param(
$Info,
# Type of the report, currently 'markdown' or 'text'
[string] $Type = 'markdown',
# Path where to save the report
[string] $Path = 'Update-AUPackages.md',
# Report parameters
[HashTable] $Params
)
Write-Host "Saving $Type report: $Path"
$Type = "$PSScriptRoot\Report\$Type.ps1"
if (!(Test-Path $Type )) { throw "Report type not found: '$Type" }
$result = & $Type
$result | Out-File $Path
. $PSScriptRoot\markdown_funcs.ps1
$Github_UserRepo = $Params.Github_UserRepo
$UserMessage = $Params.UserMessage
$NoAppVeyor = $Params.NoAppVeyor
$IconSize = if ($Params.IconSize) { $Params.IconSize } else { 32 }
$NoIcons = $Params.NoIcons
$Title = if ($Params.Title) { $Params.Title } else { 'Update-AUPackages' }
#=======================================================================================
$now = $Info.startTime.ToUniversalTime().ToString('yyyy-MM-dd HH:mm')
$au_version = gmo au -ListAvailable | % Version | select -First 1 | % { "$_" }
$package_no = $Info.result.all.Length
$update_all_url = if ($Github_UserRepo) {"https://github.com/$Github_UserRepo/blob/master/update_all.ps1" } else { "https://github.com/majkinetor/au-packages-template/blob/master/update_all.ps1" }
$icon_ok = 'https://cdn.rawgit.com/majkinetor/au/master/AU/Plugins/Report/r_ok.png'
$icon_er = 'https://cdn.rawgit.com/majkinetor/au/master/AU/Plugins/Report/r_er.png'
"# $Title"
#=== Header ===============================
if (!$NoAppVeyor -and $Github_UserRepo) { "[](https://ci.appveyor.com/project/$Github_UserRepo/build/$Env:APPVEYOR_BUILD_NUMBER)" }
@"
[-red.svg)](#ok)
[-blue.svg)](https://www.powershellgallery.com/packages/AU)
[](#)[](#)
**UTC**: $now [](#) [$Github_UserRepo](https://github.com/$Github_UserRepo)
_This file is automatically generated by the [update_all.ps1]($update_all_url) script using the [AU module](https://github.com/majkinetor/au)._
"@
"`n$UserMessage`n"
#=== Body ===============================
$errors_word = if ($Info.error_count.total -eq 1) {'error'} else {'errors' }
if ($Info.error_count.total) {
"<img src='$icon_er' width='24'> **LAST RUN HAD $($Info.error_count.total) [$($errors_word.ToUpper())](#errors) !!!**" }
else {
"<img src='$icon_ok' width='24'> **Last run was OK**"
}
""
md_fix_newline $Info.stats
$columns = 'Icon', 'Name', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion'
if ($NoIcons) { $columns = $columns[1.10] }
if ($Info.pushed) {
md_title Pushed
md_table $Info.result.pushed -Columns $columns
}
if ($Info.error_count.total) {
md_title Errors
md_table $Info.result.errors -Columns ($columns + 'Error'| ? { ('Updated', 'Pushed') -notcontains $_ } )
$Info.result.errors | % {
md_title $_.Name -Level 3
md_code "$($_.Error)"
}
}
if ($Info.result.ok) {
md_title OK
md_table $Info.result.ok -Columns $columns
$Info.result.ok | % {
md_title $_.Name -Level 3
md_code $_.Result
}
}
function md_fix_newline($Text) {
$Text -replace "\.`n", "\.`n " | Out-String
}
function md_title($Title, $Level=2 ) {
""
"#"*$Level + ' ' + $Title | Out-String
""
}
function md_code($Text) {
"`n" + '```'
($Text -join "`n").Trim()
'```' + "`n"
}
function md_table($result, $Columns, $MaxErrorLength=150) {
if (!$Columns) { $Columns = 'Name', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion', 'Error' }
$res = '|' + ($Columns -join '|') + "|`r`n"
$res += ((1..$Columns.Length | % { '|---' }) -join '') + "|`r`n"
$result | % {
$o = $_ | select `
@{ N='Icon'
E={'<img src="{0}" width="{1}" height="{1}"/>' -f $_.NuspecXml.package.metadata.iconUrl, $IconSize }
},
@{ N='Name'
E={'[{0}](https://chocolatey.org/packages/{0}/{1})' -f $_.Name, $(if ($_.Updated) { $_.RemoteVersion } else {$_.NuspecVersion }) }
},
@{ N='Updated'
E={
$r = "[{0}](#{1})" -f $_.Updated, $_.Name.ToLower()
$r += if ($_.Updated) { ' 🔸' }
$r
}
},
'Pushed',
@{ N='RemoteVersion'
E={"[{0}]({1})" -f $_.RemoteVersion, $_.NuspecXml.package.metadata.projectUrl }
},
@{ N='NuspecVersion'
E={"[{0}]({1})" -f $_.NuspecVersion, $_.NuspecXml.package.metadata.packageSourceUrl }
},
@{ N='Error'
E={
$err = ("$($_.Error)" -replace "`r?`n", '; ').Trim()
if ($err) {
if ($err.Length -gt $MaxErrorLength) { $err = $err.Substring(0,$MaxErrorLength) + ' ...' }
"[{0}](#{1})" -f $err, $_.Name.ToLower()
}
}
}
$res += ((1..$Columns.Length | % { $col = $Columns[$_-1]; '|' + $o.$col }) -join '') + "|`r`n"
}
$res
}
$UserMessage = $Params.UserMessage
$Title = if ($Params.Title) { $Params.Title } else { 'Update-AUPackages' }
#==============================================================================
function title($txt) { "r`n{0}`r`n{1}`r`n" -f $txt,('-'*$txt.Length) }
function indent($txt, $level=4) { $txt -split "`n" | % { ' '*$level + $_ } }
$now = $Info.startTime.ToUniversalTime().ToString('yyyy-MM-dd HH:mm')
$au_version = gmo au -ListAvailable | % Version | select -First 1 | % { "$_" }
$package_no = $Info.result.all.Length
"{0,-15}{1}" -f 'Title:', $Title
"{0,-15}{1}" -f 'Time:', $now
"{0,-15}{1}" -f 'AU version:', $au_version
"{0,-15}{1}" -f 'AU packages:', $package_no
$errors_word = if ($Info.error_count.total -eq 1) {'error'} else {'errors' }
if ($Info.error_count.total) {
"LAST RUN HAD $($Info.error_count.total) $errors_word !!!" }
else {
"Last run was OK"
}
""; $Info.stats
""; $UserMessage; ""
if ($Info.pushed) {
title Pushed
$Info.result.pushed | select 'Name', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion' | ft | Out-String | set r
indent $r 2
$ok | % { $_.Name; indent $_.Result; "" }
}
if ($Info.error_count.total) {
title Errors
$Info.result.errors | select 'Name', 'NuspecVersion', 'Error' | ft | Out-String | set r
indent $r 2
$Info.result.errors | % { $_.Name; ident $_.Error; "" }
}
$ok = $Info.result.ok | ? { !$_.Pushed }
if ($ok) {
title OK
$ok | select 'Name', 'Updated', 'RemoteVersion', 'NuspecVersion' | ft | Out-String | set r
indent $r 2
$ok | % { $_.Name; indent $_.Result; "" }
}
# Author: Miodrag Milic <[email protected]>
# Last Change: 21-Sep-2016.
<#
.SYNOPSIS
Save run info to the file and exclude sensitive information.
.DESCRIPTION
Run this plugin as the last one to save all other info produced during the run.
To load it for inspection use `$info = Import-CliXml update_info.xml`.
#>
param(
$Info,
#Path to XML file to save
[string] $Path = 'update_info.xml',
#Match options with those words to erase
[string[]] $Exclude = @('password', 'apikey')
)
function deep_clone {
param($DeepCopyObject)
$memStream = new-object IO.MemoryStream
$formatter = new-object Runtime.Serialization.Formatters.Binary.BinaryFormatter
$formatter.Serialize($memStream,$DeepCopyObject)
$memStream.Position=0
$formatter.Deserialize($memStream)
}
# Runinfo must save its own run results directly in Info
function result($msg) { $Info.plugin_results.RunInfo += $msg; Write-Host $msg }
$Info.plugin_results.RunInfo = @()
$format = '{0,-15}{1}'
$orig_opts = $Info.Options
$opts = deep_clone $orig_opts
$excluded = ''
foreach ($w in $Exclude) {
foreach ($key in $Info.Options.Keys) {
if ($Info.Options.$key -is [HashTable]) {
foreach ($subkey in $Info.Options.$key.Keys) {
if ($subkey -like "*$w*") {
$excluded += "$key.$subkey "
$opts.$key.$subkey = '*****'
}
}
}
}
}
if ($excluded) { result ($format -f 'Excluded:', $excluded) }
result ($format -f 'File:', $Path)
$Info.Options = $opts
$Info | Export-CliXML $Path
$Info.Options = $orig_opts
class AUPackage {
[string] $Path
[string] $Name
[bool] $Updated
[bool] $Pushed
[string] $RemoteVersion
[string] $NuspecVersion
[string[]] $Result
[string] $Error
[string] $NuspecPath
[xml] $NuspecXml
AUPackage([string] $Path ){
if ([String]::IsNullOrWhiteSpace( $Path )) { throw 'Package path can not be empty' }
$this.Path = $Path
$this.Name = Split-Path -Leaf $Path
$this.NuspecPath = '{0}\{1}.nuspec' -f $this.Path, $this.Name
if (!(gi $this.NuspecPath -ea ignore)) { throw 'No nuspec file found in the package directory' }
$this.NuspecXml = [AUPackage]::LoadNuspecFile( $this.NuspecPath )
$this.NuspecVersion = $this.NuspecXml.package.metadata.version
}
static [xml] LoadNuspecFile( $NuspecPath ) {
$nu = New-Object xml
$nu.PSBase.PreserveWhitespace = $true
$nu.Load($NuspecPath)
return $nu
}
}
# Returns nothing if url is valid, error otherwise
function check_url( [string] $Url, [int]$Timeout, $ExcludeType='text/html' ) {
if (!(is_url $Url)) { return "URL syntax is invalid" }
try
{
$response = request $url $Timeout
if ($response.ContentType -like "*${ExcludeType}*") { return "Bad content type '$ExcludeType'" }
}
catch {
return "Can't validate URL`n$_"
}
}
# Returns [bool]
function is_url([string] $Url ) {
[Uri]::IsWellFormedUriString($URL, [UriKind]::Absolute)
}
# Returns [bool]
function is_version( [string] $Version ) {
$re = '^(\d{1,16})\.(\d{1,16})\.*(\d{1,16})*\.*(\d{1,16})*(-[^.-]+)*$'
if ($Version -notmatch $re) { return $false }
$v = $Version -replace '-.+'
return [version]::TryParse($v, [ref]($__))
}
function request( [string]$Url, [int]$Timeout ) {
if ([string]::IsNullOrWhiteSpace($url)) {throw 'The URL is empty'}
$request = [System.Net.WebRequest]::Create($Url)
if ($Timeout) { $request.Timeout = $Timeout*1000 }
$response = $request.GetResponse()
$response.Close()
$response
}
# Author: Miodrag Milic <[email protected]>
# Last Change: 12-Nov-2016.
<#
.SYNOPSIS
Get AU packages
.DESCRIPTION
Returns list of directories that have update.ps1 script in them and package name
doesn't start with the '_' char (unpublished packages, not considered by Update-AUPackages
function).
Function looks in the directory pointed to by the global variable $au_root or, if not set,
the current directory.
.EXAMPLE
gau p*
Get all automatic packages that start with 'p' in the current directory.
.EXAMPLE
$au_root = 'c:\packages'; lsau 'cpu-z*','p*','copyq'
Get all automatic packages in the directory 'c:\packages' that start with 'cpu-z' or 'p' and package which name is 'copyq'.
#>
function Get-AUPackages( [string[]] $Name ) {
$root = $global:au_root
if (!$root) { $root = $pwd }
ls $root\*\update.ps1 | % {
$packageDir = gi (Split-Path $_)
if ($Name -and $Name.Length -gt 0) {
$m = $Name | ? { $packageDir.Name -like $_ }
if (!$m) { return }
}
if ($packageDir.Name -like '_*') { return }
$packageDir
}
}
Set-Alias gau Get-AuPackages
Set-Alias lsau Get-AuPackages
# Author: Miodrag Milic <[email protected]>
# Last Change: 26-Nov-2016.
<#
.SYNOPSIS
Download file from internet and calculate its checksum
#>
function Get-RemoteChecksum( [string] $Url, $Algorithm='sha256' ) {
$fn = [System.IO.Path]::GetTempFileName()
Invoke-WebRequest $Url -OutFile $fn -UseBasicParsing
$res = Get-FileHash $fn -Algorithm $Algorithm | % Hash
rm $fn -ea ignore
return $res.ToLower()
}
# Author: Miodrag Milic <[email protected]>
# Last Change: 22-Oct-2016.
<#
.SYNOPSIS
Push latest created package to the Chocolatey community repository.
.DESCRIPTION
The function uses they API key from the file api_key in current or parent directory, environment variable
or cached nuget API key.
#>
function Push-Package() {
$api_key = if (Test-Path api_key) { gc api_key }
elseif (Test-Path ..\api_key) { gc ..\api_key }
elseif ($Env:api_key) { $Env:api_key }
$package = ls *.nupkg | sort -Property CreationTime -Descending | select -First 1
if (!$package) { throw 'There is no nupkg file in the directory'}
if ($api_key) {
cpush $package.Name --api-key $api_key
} else {
cpush $package.Name
}
}
# Author: Miodrag Milic <[email protected]>
# Last Change: 15-Nov-2016.
<#
.SYNOPSIS
Test Chocolatey package
.DESCRIPTION
The function can test install, uninistall or both and provide package parameters during test.
It will force install and then remove the Chocolatey package if called without arguments.
It accepts either nupkg or nuspec path. If none specified, current directory will be searched
for any of them.
.EXAMPLE
Test-Package -Install
Test the install of the package from the current directory.
.LINK
https://github.com/chocolatey/choco/wiki/CreatePackages#testing-your-package
#>
function Test-Package {
param(
# If file, path to the .nupkg or .nuspec file for the package.
# If directory, latest .nupkg or .nuspec file wil be looked in it.
# If ommited current directory will be used.
$Nu,
# Test chocolateyInstall.ps1 only.
[switch] $Install,
# Test chocolateyUninstall.ps1 only.
[switch] $Uninstall,
# Package parameters
[string] $Parameters,
# Path to chocolatey-test-environment: https://github.com/majkinetor/chocolatey-test-environment
[string] $Vagrant = $Env:au_Vagrant,
# Open new shell window
[switch] $VagrantOpen,
# Do not remove existing packages from vagrant package directory
[switch] $VagrantNoClear
)
if (!$Install -and !$Uninstall) { $Install = $true }
if (!$Nu) { $dir = gi $pwd }
else {
if (!(Test-Path $Nu)) { throw "Path not found: $Nu" }
$Nu = gi $Nu
$dir = if ($Nu.PSIsContainer) { $Nu; $Nu = $null } else { $Nu.Directory }
}
if (!$Nu) {
$Nu = gi $dir/*.nupkg | sort -Property CreationTime -Descending | select -First 1
if (!$Nu) { $Nu = gi $dir/*.nuspec }
if (!$Nu) { throw "Can't find nupkg or nuspec file in the directory" }
}
if ($Nu.Extension -eq '.nuspec') {
Write-Host "Nuspec file given, running choco pack"
choco pack -r $Nu.FullName --OutputDirectory $Nu.DirectoryName | Write-Host
if ($LASTEXITCODE -ne 0) { throw "choco pack failed with $LastExitCode"}
$Nu = gi "$($Nu.DirectoryName)\*.nupkg" | sort -Property CreationTime -Descending | select -First 1
} elseif ($Nu.Extension -ne '.nupkg') { throw "File is not nupkg or nuspec file" }
#At this point Nu is nupkg file
$package_name = $Nu.Name -replace '(\.\d+)+(-[^-]+)?\.nupkg$'
$package_version = ($Nu.BaseName -replace $package_name).Substring(1)
Write-Host "`nPackage info"
Write-Host " Path:".PadRight(15) $Nu
Write-Host " Name:".PadRight(15) $package_name
Write-Host " Version:".PadRight(15) $package_version
if ($Parameters) { Write-Host " Parameters:".PadRight(15) $Parameters }
if ($Vagrant) { Write-Host " Vagrant: ".PadRight(15) $Vagrant }
if ($Vagrant) {
Write-Host "`nTesting package using vagrant"
if (!$VagrantNoClear) {
Write-Host 'Removing existing vagrant packages'
rm $Vagrant\packages\*.nupkg -ea ignore
rm $Vagrant\packages\*.xml -ea ignore
}
cp $Nu $Vagrant\packages
$options_file = "$package_name.$package_version.xml"
@{ Install = $Install; Uninstall = $Uninstall; Parameters = $Parameters } | Export-CliXML "$Vagrant\packages\$options_file"
if ($VagrantOpen) {
start powershell -Verb Open -ArgumentList "-NoProfile -NoExit -Command `$Env:http_proxy=`$Env:https_proxy=`$Env:ftp_proxy=`$Env:no_proxy=''; cd $Vagrant; vagrant up"
} else {
powershell -NoProfile -Command "`$Env:http_proxy=`$Env:https_proxy=`$Env:ftp_proxy=`$Env:no_proxy=''; cd $Vagrant; vagrant up"
}
return
}
if ($Install) {
Write-Host "`nTesting package install"
choco install -y -r $package_name --version $package_version --source "'$($Nu.DirectoryName);https://chocolatey.org/api/v2/'" --force --packageParameters "'$Parameters'" | Write-Host
if ($LASTEXITCODE -ne 0) { throw "choco install failed with $LastExitCode"}
}
if ($Uninstall) {
Write-Host "`nTesting package uninstall"
choco uninstall -y -r $package_name | Write-Host
if ($LASTEXITCODE -ne 0) { throw "choco uninstall failed with $LastExitCode"}
}
}
# Author: Miodrag Milic <[email protected]>
# Last Change: 02-Dec-2016.
<#
.SYNOPSIS
Update all automatic packages
.DESCRIPTION
Function Update-AUPackages will iterate over update.ps1 scripts and execute each. If it detects
that a package is updated it will push it to the Chocolatey community repository.
The function will look for AU packages in the directory pointed to by the global variable au_root
or in the current directory if mentioned variable is not set.
For the push to work, specify your API key in the file 'api_key' in the script's directory or use
cached nuget API key or set environment variable '$Env:api_key'.
The function accepts many options via ordered HashTable parameter Options.
.EXAMPLE
Update-AUPackages p* @{ Threads = 5; Timeout = 10 }
Update all automatic packages in the current directory that start with letter 'p' using 5 threads
and web timeout of 10 seconds.
.EXAMPLE
$au_root = 'c:\chocolatey'; updateall @{ Force = $true }
Force update of all automatic ackages in the given directory.
.LINK
Update-Package
.OUTPUTS
AUPackage[]
#>
function Update-AUPackages {
[CmdletBinding()]
param(
# Filter package names. Supports globs.
[string[]] $Name,
<#
Hashtable with options:
Threads - Number of background jobs to use, by default 10.
Timeout - WebRequest timeout in seconds, by default 100.
UpdateTimeout - Timeout for background job in seconds, by default 1200 (20 minutes).
Force - Force package update even if no new version is found.
Push - Set to true to push updated packages to Chocolatey community repository.
PluginPath - Additional path to look for user plugins. If not set only module integrated plugins will work
Plugin - Any HashTable key will be treated as plugin with the same name as the option name.
A script with that name will be searched for in the AU module path and user specified path.
If script is found, it will be called with splatted HashTable passed as plugin parameters.
To list default AU plugins run:
ls "$(Split-Path (gmo au -list).Path)\Plugins\*.ps1"
BeforeEach - User ScriptBlock that will be called before each package and accepts 2 arguments: Name & Options.
To pass additional arguments, specify them as Options key/values.
AfterEach - Similar as above.
Script - Script that will be called before and after everything.
#>
[System.Collections.Specialized.OrderedDictionary] [email protected]{},
#Do not run plugins, defaults to global variable `au_NoPlugins`.
[switch] $NoPlugins = $global:au_NoPlugins
)
$startTime = Get-Date
if (!$Options.Threads) { $Options.Threads = 10 }
if (!$Options.Timeout) { $Options.Timeout = 100 }
if (!$Options.UpdateTimeout){ $Options.UpdateTimeout = 1200 }
if (!$Options.Force) { $Options.Force = $false }
if (!$Options.Push) { $Options.Push = $false }
if (!$Options.PluginPath) { $Options.PluginPath = '' }
Remove-Job * -force #remove any previously run jobs
$tmp_dir = "$ENV:Temp\chocolatey\au"
mkdir -ea 0 $tmp_dir | Out-Null
ls $tmp_dir | ? PSIsContainer -eq $false | rm #clear tmp dir files
$aup = Get-AUPackages $Name
Write-Host 'Updating' $aup.Length 'automatic packages at' $($startTime.ToString("s") -replace 'T',' ') $(if ($Options.Force) { "(forced)" } else {})
Write-Host 'Push is' $( if ($Options.Push) { 'enabled' } else { 'disabled' } )
if ($Options.Force) { Write-Host 'FORCE IS ENABLED. All packages will be updated' }
$script_err = 0
if ($Options.Script) { try { & $Options.Script 'START' $aup | Write-Host } catch { Write-Error $_; $script_err += 1 } }
$threads = New-Object object[] $Options.Threads
$result = @()
$j = $p = 0
while( $p -ne $aup.length ) {
# Check for completed jobs
foreach ($job in (Get-Job | ? state -ne 'Running')) {
$p += 1
if ( 'Stopped', 'Failed', 'Completed' -notcontains $job.State) {
Write-Host "Invalid job state for $($job.Name): " + $job.State
}
else {
Write-Verbose ($job.State + ' ' + $job.Name)
$pkg = $null
Receive-Job $job | set pkg
Remove-Job $job
$ignored = $pkg -eq 'ignore'
if ( !$pkg -or $ignored ) {
$pkg = [AUPackage]::new( (Get-AuPackages $($job.Name)) )
if ($ignored) {
$pkg.Result = "ignored`r`n`r`n" + (gc "$tmp_dir\$($pkg.Name)" -Raw -ea 0)
} elseif ($job.State -eq 'Stopped') {
$pkg.Error = "Job termintated due to the $($Options.UpdateTimeout)s UpdateTimeout"
} else {
$pkg.Error = 'Job returned no object, Vector smash ?'
}
}
$message = $pkg.Name + ' '
$message += if ($pkg.Updated) { 'is updated to ' + $pkg.RemoteVersion } else { 'has no updates' }
if ($pkg.Updated -and $Options.Push) {
$message += if (!$pkg.Pushed) { ' but push failed!' } else { ' and pushed'}
}
if ($pkg.Error) {
$message = "$($pkg.Name) ERROR: "
$message += $pkg.Error.ToString() -split "`n" | % { "`n" + ' '*5 + $_ }
}
Write-Host ' ' $message
$result += $pkg
}
}
# Sleep a bit and check for running tasks update timeout
$job_count = Get-Job | measure | % count
if (($job_count -eq $Options.Threads) -or ($j -eq $aup.Length)) {
sleep 1
foreach ($job in $(Get-Job -State Running)) {
$elapsed = ((get-date) - $job.PSBeginTime).TotalSeconds
if ($elapsed -ge $Options.UpdateTimeout) { Stop-Job $job }
}
continue
}
# Start a new thread
$package_path = $aup[$j++]
$package_name = Split-Path $package_path -Leaf
Write-Verbose "Starting $package_name"
Start-Job -Name $package_name { #TODO: fix laxxed variables in job for BE and AE
$Options = $using:Options
cd $using:package_path
$out = "$using:tmp_dir\$using:package_name"
$global:au_Timeout = $Options.Timeout
$global:au_Force = $Options.Force
$global:au_Result = 'pkg'
if ($Options.BeforeEach) {
$s = [Scriptblock]::Create( $Options.BeforeEach )
. $s $using:package_name $Options
}
$pkg = $null #test double report when it fails
try {
$pkg = ./update.ps1 6> $out
} catch {
$pkg.Error = $_
}
if (!$pkg) { throw "'$using:package_name' update script returned nothing" }
if (($pkg -eq 'ignore') -or ($pkg[-1] -eq 'ignore')) { return 'ignore' }
$pkg = $pkg[-1]
$type = $pkg.GetType()
if ( "$type" -ne 'AUPackage') { throw "'$using:package_name' update script didn't return AUPackage but: $type" }
if ($pkg.Updated -and $Options.Push) {
$pkg.Result += $r = Push-Package
if ($LastExitCode -eq 0) {
$pkg.Pushed = $true
} else {
$pkg.Error = "Push ERROR`n" + ($r | select -skip 1)
}
}
if ($Options.AfterEach) {
$s = [Scriptblock]::Create( $Options.AfterEach )
. $s $using:package_name $Options
}
$pkg
} | Out-Null
}
$result = $result | sort Name
$info = get_info
run_plugins
if ($Options.Script) { try { & $Options.Script 'END' $info | Write-Host } catch { Write-Error $_; $script_err += 1 } }
@('') + $info.stats + '' | Write-Host
$result
}
function run_plugins() {
if ($NoPlugins) { return }
rm -Force -Recurse $tmp_dir\plugins -ea Ignore
mkdir -Force $tmp_dir\plugins | Out-Null
foreach ($key in $Options.Keys) {
$params = $Options.$key
if ($params -isnot [HashTable]) { continue }
$plugin_path = "$PSScriptRoot/../Plugins/$key.ps1"
if (!(Test-Path $plugin_path)) {
if([string]::IsNullOrWhiteSpace($Options.PluginPath)) { continue }
$plugin_path = $Options.PluginPath + "/$key.ps1"
if(!(Test-Path $plugin_path)) { continue }
}
try {
Write-Host "`nRunning $key"
& $plugin_path $Info @params *>&1 | tee $tmp_dir\plugins\$key | Write-Host
$info.plugin_results.$key += gc $tmp_dir\plugins\$key -ea ignore
} catch {
$err_lines = $_.ToString() -split "`n"
Write-Host " ERROR: " $(foreach ($line in $err_lines) { "`n" + ' '*4 + $line })
$info.plugin_errors.$key = $_.ToString()
}
}
}
function get_info {
$errors = $result | ? { $_.Error }
$info = [PSCustomObject]@{
result = [PSCustomObject]@{
all = $result
errors = $errors
ok = $result | ? { !$_.Error }
pushed = $result | ? Pushed
updated = $result | ? Updated
}
error_count = [PSCustomObject]@{
update = $errors | ? {!$_.Updated} | measure | % count
push = $errors | ? {$_.Updated -and !$_.Pushed} | measure | % count
total = $errors | measure | % count
}
error_info = ''
packages = $aup
startTime = $startTime
minutes = ((Get-Date) - $startTime).TotalMinutes.ToString('#.##')
pushed = $result | ? Pushed | measure | % count
updated = $result | ? Updated | measure | % count
stats = ''
options = $Options
plugin_results = @{}
plugin_errors = @{}
}
$info.PSObject.TypeNames.Insert(0, 'AUInfo')
$info.stats = get-stats
$info.error_info = $errors | % {
"`nPackage: " + $_.Name + "`n"
$_.Error
}
$info
}
function get-stats {
"Finished {0} packages after {1} minutes. " -f $info.packages.length, $info.minutes
"{0} updated and {1} pushed. " -f $info.updated, $info.pushed
"{0} errors - {1} update, {2} push. " -f $info.error_count.total, $info.error_count.update, $info.error_count.push
}
Set-Alias updateall Update-AuPackages
# Author: Miodrag Milic <[email protected]>
# Last Change: 13-Dec-2016.
<#
.SYNOPSIS
Update automatic package
.DESCRIPTION
This function is used to perform necessary updates to the specified files in the package.
It shouldn't be used on its own but must be part of the script which defines two functions:
- au_SearchReplace
The function should return HashTable where keys are file paths and value is another HashTable
where keys and values are standard search and replace strings
- au_GetLatest
Returns the HashTable where the script specifies information about new Version, new URLs and
any other data. You can refer to this variable as the $Latest in the script.
While Version is used to determine if updates to the package are needed, other arguments can
be used in search and replace patterns or for whatever purpose.
With those 2 functions defined, calling Update-Package will:
- Call your au_GetLatest function to get the remote version and other information.
- If remote version is higher then the nuspec version, function will:
- Check the returned URLs, Versions and Checksums (if defined) for validity (unless NoCheckXXX variables are specified)
- Download files and calculate checksum(s), (unless already defined or ChecksumFor is set to 'none')
- Update the nuspec with the latest version
- Do the necessary file replacements
- Pack the files into the nuget package
You can also define au_BeforeUpdate and au_AfterUpdate functions to integrate your code into the update pipeline.
.EXAMPLE
PS> notepad update.ps1
# The following script is used to update the package from the github releases page.
# After it defines the 2 functions, it calls the Update-Package.
# Checksums are automatically calculated for 32 bit version (the only one in this case)
import-module au
function global:au_SearchReplace {
".\tools\chocolateyInstall.ps1" = @{
"(^[$]url32\s*=\s*)('.*')" = "`$1'$($Latest.URL32)'"
"(^[$]checksum32\s*=\s*)('.*')" = "`$1'$($Latest.Checksum32)'"
"(^[$]checksumType32\s*=\s*)('.*')" = "`$1'$($Latest.ChecksumType32)'"
}
}
function global:au_GetLatest {
$download_page = Invoke-WebRequest -Uri https://github.com/hluk/CopyQ/releases
$re = "copyq-.*-setup.exe"
$url = $download_page.links | ? href -match $re | select -First 1 -expand href
$version = $url -split '-|.exe' | select -Last 1 -Skip 2
return @{ URL32 = $url; Version = $version }
}
Update-Package -ChecksumFor 32
.NOTES
All function parameters accept defaults via global variables with prefix `au_` (example: $global:au_Force = $true).
.OUTPUTS
PSCustomObject with type AUPackage.
.LINK
Update-AUPackages
#>
function Update-Package {
[CmdletBinding()]
param(
#Do not check URL and version for validity.
[switch] $NoCheckUrl,
#Do not check if latest returned version already exists in the Chocolatey community feed.
#Ignored when Force is specified.
[switch] $NoCheckChocoVersion,
#Specify for which architectures to calculate checksum - all, 32 bit, 64 bit or none.
[ValidateSet('all', '32', '64', 'none')]
[string] $ChecksumFor='all',
#Timeout for all web operations, by default 100 seconds.
[int] $Timeout,
#Force package update even if no new version is found.
[switch] $Force,
#Do not show any Write-Host output.
[switch] $NoHostOutput,
#Output variable.
[string] $Result
)
function check_urls() {
"URL check" | result
$Latest.Keys | ? {$_ -like 'url*' } | % {
$url = $Latest[ $_ ]
if ($res = check_url $url) { throw "${res}:$url" } else { " $url" | result }
}
}
function get_checksum()
{
function invoke_installer() {
if (!(Test-Path tools\chocolateyInstall.ps1)) { " aborted, chocolateyInstall not found for this package" | result; return }
Import-Module "$choco_tmp_path\helpers\chocolateyInstaller.psm1" -Force -Scope Global
if ($ChecksumFor -eq 'none') { "Automatic checksum calculation is disabled"; return }
if ($ChecksumFor -eq 'all') { $arch = '32','64' } else { $arch = $ChecksumFor }
$pkg_path = [System.IO.Path]::GetFullPath("$Env:TEMP\chocolatey\$($package.Name)\" + $global:Latest.Version) #https://github.com/majkinetor/au/issues/32
mkdir -Force $pkg_path | Out-Null
$Env:ChocolateyPackageName = "chocolatey\$($package.Name)"
$Env:ChocolateyPackageVersion = $global:Latest.Version
$Env:ChocolateyAllowEmptyChecksums = 'true'
foreach ($a in $arch) {
$Env:chocolateyForceX86 = if ($a -eq '32') { 'true' } else { '' }
try {
#rm -force -recurse -ea ignore $pkg_path
.\tools\chocolateyInstall.ps1 | result
} catch {
if ( "$_" -notlike 'au_break: *') { throw $_ } else {
$filePath = "$_" -replace 'au_break: '
if (!(Test-Path $filePath)) { throw "Can't find file path to checksum" }
$item = gi $filePath
$type = if ($global:Latest.ContainsKey('ChecksumType' + $a)) { $global:Latest.Item('ChecksumType' + $a) } else { 'sha256' }
$hash = (Get-FileHash $item -Algorithm $type | % Hash).ToLowerInvariant()
if (!$global:Latest.ContainsKey('ChecksumType' + $a)) { $global:Latest.Add('ChecksumType' + $a, $type) }
if (!$global:Latest.ContainsKey('Checksum' + $a)) {
$global:Latest.Add('Checksum' + $a, $hash)
"Package downloaded and hash calculated for $a bit version" | result
} else {
$expected = $global:Latest.Item('Checksum' + $a)
if ($hash -ne $expected) { throw "Hash for $a bit version mismatch: actual = '$hash', expected = '$expected'" }
"Package downloaded and hash checked for $a bit version" | result
}
}
}
}
}
function fix_choco {
Sleep -Milliseconds (Get-Random 500) #reduce probability multiple updateall threads entering here at the same time (#29)
# Copy choco modules once a day
if (Test-Path $choco_tmp_path) {
$ct = gi $choco_tmp_path | % creationtime
if (((get-date) - $ct).Days -gt 1) { rm -recurse -force $choco_tmp_path } else { Write-Verbose 'Chocolatey copy is recent, aborting monkey patching'; return }
}
Write-Verbose "Monkey patching chocolatey in: '$choco_tmp_path'"
cp -recurse -force $Env:ChocolateyInstall\helpers $choco_tmp_path\helpers
if (Test-Path $Env:ChocolateyInstall\extensions) { cp -recurse -force $Env:ChocolateyInstall\extensions $choco_tmp_path\extensions }
$fun_path = "$choco_tmp_path\helpers\functions\Get-ChocolateyWebFile.ps1"
(gc $fun_path) -replace '^\s+return \$fileFullPath\s*$', ' throw "au_break: $fileFullPath"' | sc $fun_path -ea ignore
}
"Automatic checksum started" | result
# Copy choco powershell functions to TEMP dir and monkey patch the Get-ChocolateyWebFile function
$choco_tmp_path = "$Env:TEMP\chocolatey\au\chocolatey"
fix_choco
# This will set the new URLs before the files are downloaded but will replace checksums to empty ones so download will not fail
# because checksums are at that moment set for the previous version.
# SkipNuspecFile is passed so that if things fail here, nuspec file isn't updated; otherwise, on next run
# AU will think that package is the most recent.
#
# TODO: This will also leaves other then nuspec files updated which is undesired side effect (should be very rare)
#
$global:Silent = $true
$c32 = $global:Latest.Checksum32; $c64 = $global:Latest.Checksum64 #https://github.com/majkinetor/au/issues/36
$global:Latest.Remove('Checksum32'); $global:Latest.Remove('Checksum64') # -||-
update_files -SkipNuspecFile | out-null
if ($c32) {$global:Latest.Checksum32 = $c32}
if ($c64) {$global:Latest.Checksum64 = $c64} #https://github.com/majkinetor/au/issues/36
$global:Silent = $false
# Invoke installer for each architecture to download files
invoke_installer
}
function set_fix_version() {
$script:is_forced = $true
if ($global:au_Version) {
"Overriding version to: $global:au_Version" | result
$global:Latest.Version = $package.RemoteVersion = $global:au_Version
if (!(is_version $Latest.Version)) { throw "Invalid version: $($Latest.Version)" }
$global:au_Version = $null
return
}
$date_format = 'yyyyMMdd'
$d = (get-date).ToString($date_format)
$v = [version]($package.NuspecVersion -replace '-.+')
$rev = $v.Revision.ToString()
try { $revdate = [DateTime]::ParseExact($rev, $date_format,[System.Globalization.CultureInfo]::InvariantCulture, [System.Globalization.DateTimeStyles]::None) } catch {}
if (($rev -ne -1) -and !$revdate) { return }
$build = if ($v.Build -eq -1) {0} else {$v.Build}
$Latest.Version = $package.RemoteVersion = '{0}.{1}.{2}.{3}' -f $v.Major, $v.Minor, $build, $d
}
function update_files( [switch]$SkipNuspecFile )
{
'Updating files' | result
' $Latest data:' | result; ($global:Latest.keys | sort | % { " {0,-15} ({1}) {2}" -f $_, $global:Latest[$_].GetType().Name, $global:Latest[$_] }) | result; '' | result
if (!$SkipNuspecFile) {
" $(Split-Path $package.NuspecPath -Leaf)" | result
" setting id: $($global:Latest.PackageName)" | result
$package.NuspecXml.package.metadata.id = $package.Name = $global:Latest.PackageName.ToString()
$msg ="updating version: {0} -> {1}" -f $package.NuspecVersion, $package.RemoteVersion
if ($script:is_forced) {
if ($package.RemoteVersion -eq $package.NuspecVersion) {
$msg = " version not changed as it already uses 'revision': {0}" -f $package.NuspecVersion
} else {
$msg = " using Chocolatey fix notation: {0} -> {1}" -f $package.NuspecVersion, $package.RemoteVersion
}
}
$msg | result
$package.NuspecXml.package.metadata.version = $package.RemoteVersion.ToString()
$package.NuspecXml.Save($package.NuspecPath)
}
$sr = au_SearchReplace
$sr.Keys | % {
$fileName = $_
" $fileName" | result
$fileContent = gc $fileName -Encoding UTF8
$sr[ $fileName ].GetEnumerator() | % {
(' {0} = {1} ' -f $_.name, $_.value) | result
if (!($fileContent -match $_.name)) { throw "Search pattern not found: '$($_.name)'" }
$fileContent = $fileContent -replace $_.name, $_.value
}
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
[System.IO.File]::WriteAllLines((gi $fileName).FullName, $fileContent, $Utf8NoBomEncoding)
}
}
function is_updated() {
$remote_l = $package.RemoteVersion -replace '-.+'
$nuspec_l = $package.NuspecVersion -replace '-.+'
$remote_r = $package.RemoteVersion.Replace($remote_l,'')
$nuspec_r = $package.NuspecVersion.Replace($nuspec_l,'')
if ([version]$remote_l -eq [version] $nuspec_l) {
if (!$remote_r -and $nuspec_r) { return $true }
if ($remote_r -and !$nuspec_r) { return $false }
return ($remote_r -gt $nuspec_r)
}
[version]$remote_l -gt [version] $nuspec_l
}
function result() {
if ($global:Silent) { return }
$input | % {
$package.Result += $_
if (!$NoHostOutput) { Write-Host $_ }
}
}
if ($PSCmdlet.MyInvocation.ScriptName -eq '') {
Write-Verbose 'Running outside of the script'
if (!(Test-Path update.ps1)) { return "Current directory doesn't contain ./update.ps1 script" } else { return ./update.ps1 }
} else { Write-Verbose 'Running inside the script' }
# Assign parameters from global variables with the prefix `au_` if they are bound
(gcm $PSCmdlet.MyInvocation.InvocationName).Parameters.Keys | % {
if ($PSBoundParameters.Keys -contains $_) { return }
$value = gv "au_$_" -Scope Global -ea Ignore | % Value
if ($value -ne $null) {
sv $_ $value
Write-Verbose "Parameter $_ set from global variable au_${_}: $value"
}
}
$package = [AUPackage]::new( $pwd )
if ($Result) { sv -Scope Global -Name $Result -Value $package }
$global:Latest = @{PackageName = $package.Name}
$global:Latest.NuspecVersion = $package.NuspecVersion
if (!(is_version $package.NuspecVersion)) {
Write-Warning "Invalid nuspec file Version '$($package.NuspecVersion)' - using 0.0"
$global:Latest.NuspecVersion = $package.NuspecVersion = '0.0'
}
$module = $MyInvocation.MyCommand.ScriptBlock.Module
"{0} - checking updates using {1} version {2}" -f $package.Name, $module.Name, $module.Version | result
try {
$res = au_GetLatest | select -Last 1
if ($res -eq $null) { throw 'au_GetLatest returned nothing' }
$res_type = $res.GetType()
if ($res_type -ne [HashTable]) { throw "au_GetLatest doesn't return a HashTable result but $res_type" }
$res.Keys | % { $global:Latest.Remove($_) }
$global:Latest += $res
if ($global:au_Force) { $Force = $true }
} catch {
throw "au_GetLatest failed`n$_"
}
if (!(is_version $Latest.Version)) { throw "Invalid version: $($Latest.Version)" }
$package.RemoteVersion = $Latest.Version
if (!$NoCheckUrl) { check_urls }
"nuspec version: " + $package.NuspecVersion | result
"remote version: " + $package.RemoteVersion | result
if (is_updated) {
if (!($NoCheckChocoVersion -or $Force)) {
$choco_url = "https://chocolatey.org/packages/{0}/{1}" -f $package.Name, $package.RemoteVersion
try {
request $choco_url $Timeout | out-null
"New version is available but it already exists in the Chocolatey community feed (disable using `$NoCheckChocoVersion`):`n $choco_url" | result
return $package
} catch { }
}
} else {
if (!$Force) {
'No new version found' | result
return $package
}
else { 'No new version found, but update is forced' | result; set_fix_version }
}
'New version is available' | result
$match_url = ($Latest.Keys | ? { $_ -match '^URL*' } | select -First 1 | % { $Latest[$_] } | split-Path -Leaf) -match '(?<=\.)[^.]+$'
if ($match_url -and !$Latest.FileType) { $Latest.FileType = $Matches[0] }
if ($ChecksumFor -ne 'none') { get_checksum } else { 'Automatic checksum skipped' | result }
if (Test-Path Function:\au_BeforeUpdate) { 'Running au_BeforeUpdate' | result; au_BeforeUpdate | result }
update_files
if (Test-Path Function:\au_AfterUpdate) { 'Running au_AfterUpdate' | result; au_AfterUpdate | result }
choco pack --limit-output | result
if ($LastExitCode -ne 0) { throw "Choco pack failed with exit code $LastExitCode" }
'Package updated' | result
$package.Updated = $true
return $package
}
Set-Alias update Update-Package
$ErrorActionPreference = 'Stop'
$toolsPath = Split-Path $MyInvocation.MyCommand.Definition
& "$toolsPath/install.ps1"
$ErrorActionPreference = 'Stop'
$toolsPath = Split-Path $MyInvocation.MyCommand.Definition
& "$toolsPath/install.ps1" -Remove
#requires -version 2
<#
.SYNOPSIS
AU install script
.NOTES
Always install AU versionless in Program Files to support older PowerShell versions ( v < 5 )
Multiple AU versions can be installed using Install-Module if needed (on Posh 5+).
#>
param(
#If given it is path to the module to be installed.
#If not given, use first build directory and if doesn't exist, try scripts folder.
[string] $module_path,
#Remove module from the system.
[switch] $Remove
)
$ErrorActionPreference = 'Stop'
$module_name = 'AU'
$module_dst = "$Env:ProgramFiles\WindowsPowerShell\Modules"
rm -Force -Recurse "$module_dst\$module_name" -ErrorAction ignore
if ($Remove) { remove-module $module_name -ea ignore; Write-Host "Module $module_name removed"; return }
Write-Host "`n==| Starting $module_name installation`n"
if (!$module_path) {
if (Test-Path $PSScriptRoot\_build\*) {
$module_path = (ls $PSScriptRoot\_build\* -ea ignore | sort CreationDate -desc | select -First 1 -Expand FullName) + '/' + $module_name
} else {
$module_path = "$PSScriptRoot\$module_name"
if (!(Test-Path $module_path)) { throw "module_path not specified and scripts directory doesn't contain the module" }
}
}
$module_path = Resolve-Path $module_path
if (!(Test-Path $module_path)) { throw "Module path invalid: '$module_path'" }
Write-Host "Module path: '$module_path'"
cp -Recurse -Force $module_path $module_dst
$res = Get-Module $module_name -ListAvailable | ? { (Split-Path $_.ModuleBase) -eq $module_dst }
if (!$res) { throw 'Module installation failed' }
Write-Host "`n$($res.Name) version $($res.Version) installed successfully at '$module_dst\$module_name'"
$functions = $res.ExportedFunctions.Keys
import-module $module_dst\$module_name -force
$aliases = get-alias | ? { $_.Source -eq $module_name }
if ($functions.Length) {
$functions | % {
[PSCustomObject]@{ Function = $_; Alias = $aliases | ? Definition -eq $_ }
} | % { Write-Host ("`n {0,-20} {1}`n -------- -----" -f 'Function', 'Alias') } {
Write-Host (" {0,-20} {1}" -f $_.Function, "$($_.Alias)")
}
}
remove-module $module_name
Write-Host "`nTo learn more about ${module_name}: man about_${module_name}"
Write-Host "See help for any function: man updateall`n"
Log in or click on link to see number of positives.
- au.2016.12.17.nupkg (ef80eaf45efb) - ## / 55
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.
Miodrag Milić
-
- powershell (≥ 5.0)
Ground Rules:
- This discussion is only about Chocolatey Automatic Package Updater Module and the Chocolatey Automatic Package Updater Module 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 Chocolatey Automatic Package Updater Module, 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.