Browse Source

Add au folder

Rob Reynolds 7 years ago
parent
commit
8aa80423d3
11 changed files with 417 additions and 5 deletions
  1. 4 1
      .gitignore
  2. 71 0
      appveyor.yml
  3. 57 0
      au/New-Package.ps1
  4. 5 0
      au/README.md
  5. 55 0
      au/gist.md.ps1
  6. 82 0
      au/git/Save-Gist.ps1
  7. 16 0
      au/git/Save-Git.ps1
  8. 9 0
      au/git/Save-RunInfo.ps1
  9. 47 0
      au/update_all.ps1
  10. 29 3
      setup/README.md
  11. 42 1
      setup/setup.ps1

+ 4 - 1
.gitignore

@@ -22,4 +22,7 @@ New Text Document*.txt
 obj
 */working
 ketarin/soluto.xml
-*.stackdump
+*.stackdump
+update_vars.ps1
+gist.md
+update_info.xml

+ 71 - 0
appveyor.yml

@@ -0,0 +1,71 @@
+version: '{build}'
+max_jobs: 1
+image: WMF 5
+clone_depth: 5
+branches:
+  only:
+  - master
+#build:
+#  verbosity: minimal
+
+environment:
+  # Github credentials - used to save result to gist and to commit pushed packages to the git repository
+  github_user: YOUR_USER_NAME_HERE
+  github_pass:
+    secure: YOUR_PASSWORD_OR_2FA_AUTH_TOKEN_HERE_ENCRYPTED_STRING #https://ci.appveyor.com/tools/encrypt
+  github_user_repo: 'YOUR_REPO_USERNAME/YOUR_REPO_REPOSITORY_NAME' #https://github.com/chocolatey/chocolatey-packages-template is 'chocolatey/chocolatey-packages-template'
+
+  # Email credentials - for error notifications
+  mail_user: YOUR_EMAIL_ACCOUNT
+  mail_pass:
+    secure: YOUR_EMAIL_PASSWORD_HERE_ENCRYPTED_STRING #https://ci.appveyor.com/tools/encrypt
+  mail_server: smtp.gmail.com
+  mail_port: 587
+  mail_enablessl: true
+
+  # ID of the gist used to save run results
+  gist_id: YOUR_GIST_ID_CREATE_GIST_SAVE_ID_HERE
+
+  # Chocolatey API key - to push updated packages
+  api_key:
+    secure: YOUR_CHOCO_API_KEY_HERE_ENCRYPTED_STRING # https://ci.appveyor.com/tools/encrypt
+
+init:
+- git config --global user.email "chocolatey@realdimensions.net"
+- git config --global user.name "Chocolatey"
+
+install:
+- ps: 'Get-CimInstance win32_operatingsystem -Property Caption, OSArchitecture, Version | fl Caption, OSArchitecture, Version'
+- ps: $PSVersionTable
+- SET PATH=C:\Ruby21-x64\bin;%PATH%
+- ruby -v
+- gem install gist --no-ri --no-rdoc
+- "ruby -e \"require 'gist'; Gist.login! username: ENV['github_user'], password: ENV['github_pass'] if ENV['github_user'] \""
+- ps: |
+    "machine github.com", "login $Env:github_user", "password $Env:github_pass" | Out-File ~/_netrc -Encoding ascii
+    Install-PackageProvider -Name NuGet -Force
+    Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
+    Install-Module au -Scope CurrentUser
+    Get-Module au -ListAvailable | select Name, Version
+
+build_script:
+- ps: |
+    if ($Env:APPVEYOR_REPO_COMMIT_AUTHOR -eq 'Chocolatey') {
+        "Build triggered by appveyor commit, aborting"
+    } else {
+        .\ops\update_all.ps1
+    }
+
+#on_finish:
+#- ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
+
+artifacts:
+- path: update_info.xml
+- path: gist.md
+
+notifications:
+- provider: Email
+  to: $(mail_user)
+  on_build_success: false
+  on_build_failure: true
+  on_build_status_changed: true

+ 57 - 0
au/New-Package.ps1

@@ -0,0 +1,57 @@
+param($Name, $Type)
+
+<#
+.SYNOPSIS
+    Create a new package from the template
+
+.DESCRIPTION
+    This function creates a new package by using the directory _template which contains desired package basic settings.
+#>
+function New-Package{
+    [CmdletBinding()]
+    param(
+        #Package name
+        [string] $Name,
+
+        #Type of the package
+        [ValidateSet('Portable', 'Installer')]
+        [string] $Type='Installer',
+
+        #Github repository in the form username/repository
+        [string] $GithubRepository
+    )
+
+    if ($Name -eq $null) { throw "Name can't be empty" }
+    if (Test-Path $Name) { throw "Package with that name already exists" }
+    if (!(Test-Path _template)) { throw "Template for the packages not found" }
+    cp _template $Name -Recurse
+
+    $nuspec = gc "$Name\template.nuspec"
+    rm "$Name\template.nuspec"
+
+    Write-Verbose 'Fixing nuspec'
+    $nuspec = $nuspec -replace '<id>.+',               "<id>$Name</id>"
+    $nuspec = $nuspec -replace '<iconUrl>.+',          "<iconUrl>https://cdn.rawgit.com/$GithubRepository/master/$Name/icon.png</iconUrl>"
+    $nuspec = $nuspec -replace '<packageSourceUrl>.+', "<packageSourceUrl>https://github.com/$GithubRepository/tree/master/$Name</packageSourceUrl>"
+    $nuspec | Out-File -Encoding UTF8 "$Name\$Name.nuspec"
+
+    switch ($Type)
+    {
+        'Installer' {
+            Write-Verbose 'Using installer template'
+            rm "$Name\tools\chocolateyInstallZip.ps1"
+            mv "$Name\tools\chocolateyInstallExe.ps1" "$Name\tools\chocolateyInstall.ps1"
+        }
+        'Portable' {
+            Write-Verbose 'Using portable template'
+            rm "$Name\tools\chocolateyInstallExe.ps1"
+            mv "$Name\tools\chocolateyInstallZip.ps1" "$Name\tools\chocolateyInstall.ps1"
+        }
+    }
+
+    Write-Verbose 'Fixing chocolateyInstall.ps1'
+    $installer = gc "$Name\tools\chocolateyInstall.ps1"
+    $installer -replace "(^[$]packageName\s*=\s*)('.*')", "`$1'$($Name)'" | sc "$Name\tools\chocolateyInstall.ps1"
+}
+
+New-Package $Name $Type -GithubRepository majkinetor/chocolatey -Verbose

+ 5 - 0
au/README.md

@@ -0,0 +1,5 @@
+## Automatic Updater
+
+* Ensure you perform the steps in `setup/README.md`.
+
+Most everything here is good to go.

+ 55 - 0
au/gist.md.ps1

@@ -0,0 +1,55 @@
+# Update-AUPackages
+$(
+    $au   = gmo au -ListAvailable | % Version | select -First 1 | % { "$_"}
+    $pno  = $Info.result.all.Length
+    $GitHubUserRepo = $env:github_user_repo
+)
+
+[![](https://ci.appveyor.com/api/projects/status/9ipva7kgjigug2rn?svg=true)](https://ci.appveyor.com/project/$GitHubUserRepo/build/$Env:APPVEYOR_BUILD_NUMBER)
+[![$pno](https://img.shields.io/badge/AU%20packages-$($pno)-red.svg)](#ok)
+[![$au](https://img.shields.io/badge/AU-$($au)-blue.svg)](https://www.powershellgallery.com/packages/AU)
+
+_This file is automatically generated by the [update_all.ps1](https://github.com/$GitHubUserRepo/blob/master/ops/update_all.ps1) script using the [AU module](https://github.com/majkinetor/au) ( [view source](https://github.com/$GitHubUserRepo/blob/master/ops/gist.md.ps1) )._
+
+|||
+|---               | --- |
+**Time (UTC)**     | $($Info.startTime.ToUniversalTime().ToString('yyyy-MM-dd HH:mm'))
+**Git repository** | https://github.com/$GitHubUserRepo
+
+$(
+    $OFS="`r`n"
+
+    $icon_ok = 'https://cdn0.iconfinder.com/data/icons/shift-free/32/Complete_Symbol-128.png'
+    $icon_er = 'https://cdn0.iconfinder.com/data/icons/shift-free/32/Error-128.png'
+
+    if ($Info.error_count.total) {
+        "<img src='$icon_er' width='48'> **LAST RUN HAD $($Info.error_count.total) [ERRORS](#errors) !!!**" }
+    else {
+        "<img src='$icon_ok' width='48'> Last run was OK"
+    }
+
+    md_code $Info.stats
+
+    if ($Info.pushed) {
+        md_title Pushed
+        md_table $Info.result.pushed -Columns 'PackageName', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion'
+    }
+
+    if ($Info.error_count.total) {
+        md_title Errors
+        md_table $Info.result.errors -Columns 'PackageName', 'NuspecVersion', 'Error'
+        $Info.result.errors | % {
+            md_title $_.PackageName -Level 3
+            md_code "$($_.Error)"
+        }
+    }
+
+    if ($Info.result.ok) {
+        md_title OK
+        md_table $Info.result.ok -Columns 'PackageName', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion'
+        $Info.result.ok | % {
+            md_title $_.PackageName -Level 3
+            md_code $_.Result
+        }
+    }
+)

+ 82 - 0
au/git/Save-Gist.ps1

@@ -0,0 +1,82 @@
+function Save-Gist {
+    function Expand-PoshString() {
+        [CmdletBinding()]
+        param ( [parameter(ValueFromPipeline = $true)] [string] $str)
+        "@`"`n$str`n`"@" | iex
+    }
+
+    function max_version($p) {
+        try {
+            $n = [version]$p.NuspecVersion
+            $r = [version]$p.RemoteVersion
+            if ($n -gt $r) { "$n" } else { "$r" }
+        } catch {}
+    }
+
+    function diff_version($p) {
+        try {
+            $n = [version]$p.NuspecVersion
+            $r = [version]$p.RemoteVersion
+            return ($n -ne $r)
+        } catch { return $false }
+    }
+
+    function md_title($Title, $Level=2 ) {
+        ""
+        "#"*$Level + $Title
+    }
+
+    function md_code($Text) {
+        "`n" + '```'
+        ($Text -join "`n").Trim()
+        '```' + "`n"
+    }
+
+    function md_table($result, $Columns, $MaxErrorLength=150)
+    {
+        if (!$Columns) { $Columns = 'PackageName', 'Updated', 'Pushed', 'RemoteVersion', 'NuspecVersion', 'Error' }
+        $res = '|' + ($Columns -join '|') + "|`r`n"
+        $res += ((1..$Columns.Length | % { '|---' }) -join '') + "|`r`n"
+
+        $result | % {
+            $o = $_ | select `
+                    @{ N='PackageName'
+                       E={'[{0}](https://chocolatey.org/packages/{0}/{1})' -f $_.PackageName, (max_version $_) }
+                    },
+                    @{ N='Updated'
+                       E={
+                            $r  = "[{0}](#{1})" -f $_.Updated, $_.PackageName.ToLower()
+                            $r += if (diff_version $_) { ' &#x1F538;' }
+                            $r
+                        }
+                    },
+                    'Pushed', 'RemoteVersion', 'NuspecVersion',
+                    @{ 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, $_.PackageName.ToLower()
+                         }
+                       }
+                    }
+
+            $res += ((1..$Columns.Length | % { $col = $Columns[$_-1]; '|' + $o.$col }) -join '') + "|`r`n"
+        }
+
+        $res
+    }
+
+    "Saving results to gist"
+    if (!(gcm gist.bat -ea 0)) { "ERROR: No gist.bat found. Install it using:  'gem install gist'"; return }
+
+    $log = gc gist.md.ps1 -Raw | Expand-PoshString
+    $log | Out-File gist.md
+
+    $params = @( "--filename 'Update-AUPackages.md'")
+    $params += if ($Info.Options.Gist_ID) { "--update " + $Info.Options.Gist_ID } else { '--anonymous' }
+
+    iex -Command "`$log | gist.bat $params"
+    if ($LastExitCode) { "ERROR: Gist update failed with exit code: '$LastExitCode'" }
+}
+

+ 16 - 0
au/git/Save-Git.ps1

@@ -0,0 +1,16 @@
+function Save-Git() {
+    $pushed = $Info.result.pushed
+    if (!$Info.pushed) { "Git: no package is pushed to chocolatey, skipping"; return }
+
+    ""
+    "Executing git pull"
+    git checkout master
+    git pull
+
+    "Commiting updated packages to git repository"
+    $pushed | % { git add $_.PackageName }
+    git commit -m "UPDATE BOT: $($Info.pushed) packages updated"
+
+    "Pushing git changes"
+    git push
+}

+ 9 - 0
au/git/Save-RunInfo.ps1

@@ -0,0 +1,9 @@
+function Save-RunInfo {
+    "Saving run info"
+    try { $p = $Info.Options.Mail.Password } catch {}
+    if ($p) { $Info.Options.Mail.Password='' }
+
+    $Info | Export-CliXML update_info.xml
+
+    if ($p) { $Info.Options.Mail.Password = $p }
+}

+ 47 - 0
au/update_all.ps1

@@ -0,0 +1,47 @@
+param($Name = $null)
+cd $PSScriptRoot
+
+ls au\*.ps1 | % { . $_ }
+
+# used when running locally
+if (Test-Path update_vars.ps1) { . ./update_vars.ps1 }
+
+$options = @{
+    Timeout = 100
+    Push    = $true
+    Threads = 10
+
+    Mail = if ($env:mail_user) {
+            @{
+                To        = $env:mail_user
+                Server    = $env:mail_server
+                UserName  = $env:mail_user
+                Password  = $env:mail_pass
+                Port      = $env:mail_port
+                EnableSsl = $true
+            }
+
+            if ($env:mail_enablessl -eq 'false') {
+                Mail.EnableSsl = $false
+            }
+
+           } else {}
+
+    Gist_ID = $Env:Gist_ID
+
+    Script = {
+        param($Phase, $Info)
+
+        if ($Phase -ne 'END') { return }
+
+        Save-RunInfo
+        Save-Gist
+        Save-Git
+    }
+}
+
+updateall -Name $Name -Options $options | ft
+$global:updateall = Import-CliXML $PSScriptRoot\update_info.xml
+
+#Uncomment to fail the build on AppVeyor on any package error
+#if ($updateall.error_count.total) { throw 'Errors during update' }

+ 29 - 3
setup/README.md

@@ -2,9 +2,35 @@
 
 ### Ketarin/ChocolateyPackageUpdater Automatic Packaging
 
-* Run setup.ps1 (review the file first to ensure the folder being created)
-* Open ketarin after installing it, open the settings and import KetarinSettings.xml.
+* Review `setup.ps1` to ensure all items are set appropriately. Uncomment/change anything you need to now.
+* Run `setup.ps1`
+* Open ketarin after installing it, open the settings and import `KetarinSettings.xml`.
 
 ### Automatic Updater (AU)
 
-* Set up an appveyor job.
+#### Set up AppVeyor for packaging
+* Go to AppVeyor and sign up/sign in. https://ci.appveyor.com/
+* Set up an appveyor job - https://ci.appveyor.com/projects/new
+* Select your repository to create a new job.
+* Go to settings ensure the following items are set (these items cannot be configured in the yaml):
+  * In Build Schedule, we want to run this three times a day - set it like this: `5 */6 * * * *`. This ensures it runs at 06:05, 12:05, and 18:05.
+  * "Ensure Skip branches without `appveyor.yml`" is checked.
+  * "Enable secure variables in Pull Requests from the same repository only" is checked.
+  * Click Save.
+
+* Get encrypted values for - https://ci.appveyor.com/tools/encrypt (requires login first)
+   * github password (or auth token for 2FA)
+   * email password
+   * Chocolatey API key
+* Edit the appveyor.yml to add those values in.
+* Edit the appveyor.yml with the other configuration related items.
+
+#### Setup Local Runs
+* Edit `au/update_vars.ps1` and set the same variables there.
+* You may also want to install `gist` gem: `cinst ruby; gem install gist` and to make sure `git push` doesn't require credentials.
+
+#### Notes
+
+* If you use Google mail for error notifications on a build server such as AppVeyor, Google may block authentication from unknown device. To receive those emails enable less secure apps - see [Allowing less secure apps to access your account](https://support.google.com/accounts/answer/6010255?hl=en). In any case, do not use your private email for this but create a new Google account and redirect its messages to your private one. This wont affect you if you run the scripts from your own machine from which you usually access the email.
+* If you are using AppVeyor you should schedule your build under the _General_ options using [Cron](http://www.nncron.ru/help/EN/working/cron-format.htm) syntax, for example `0 22 * * * *` runs the updater every night at 22h. `5 * * * * *` runs the updater every hour at five past the hour.
+* For gist to work the over proxy you need to set console proxy environment variable. See [Update-CLIProxy](https://github.com/majkinetor/posh/blob/master/MM_Network/Update-CLIProxy.ps1) function.

+ 42 - 1
setup/setup.ps1

@@ -2,8 +2,49 @@
 # The name will also be saveDir
 $saveDir = "c:\chocolatey-auto-save"
 
-
 Write-Host "Ensuring that the Ketarin auto save folder is set appropriately."
 if (!(Test-Path($saveDir))) {
   mkdir $saveDir
 }
+
+@"
+## Update Variables - AU
+#
+# This file is not checked in. It exists only locally.
+# These same settings should be verified with appveyor.yml
+
+# Github credentials - used to save result to gist and to commit pushed packages to the git repository
+`$env:github_user     = 'YOUR_USER_NAME_HERE'
+`$env:github_pass     = 'YOUR_PASSWORD_OR_2FA_AUTH_TOKEN_HERE'
+`$env:github_user_repo= 'username/repository'  #https://github.com/chocolatey/chocolatey-packages-template is 'chocolatey/chocolatey-packages-template'
+
+# Email credentials - for error notifications
+`$env:mail_user       = 'YOUR_EMAIL_ACCOUNT'
+`$env:mail_pass       = 'YOUR_EMAIL_PASSWORD_HERE'
+`$env:mail_server     = 'smtp.gmail.com'
+`$env:mail_port       = '587'
+`$env:mail_enablessl  = 'true'
+
+# Chocolatey API key - to push updated packages
+`$env:api_key         = 'YOUR_CHOCO_API_KEY_HERE'
+
+# ID of the gist used to save run results
+`$env:gist_id         = 'YOUR_GIST_ID_CREATE_GIST_SAVE_ID_HERE'
+"@ | Out-File $PSScriptRoot\..\au\update_vars.ps1 -NoClobber
+
+# Uncomment these next lines if you are using AU
+# and have WMF3+ installed.
+# Otherwise you need to find a way to install PowerShell PackageManagement
+
+# WMF3/4 only
+#choco upgrade dotnet4.5.1 -y
+#choco upgrade powershell-packagemanagement --ignore-dependencies -y
+#refreshenv # You need the Chocolatey profile installed for this to work properly (Choco v0.9.10.0+).
+
+#choco install ruby -y
+#gem install gist
+
+#Install-PackageProvider -Name NuGet -Force
+#Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
+#Install-Module au -Scope CurrentUser
+#Get-Module au -ListAvailable | select Name, Version