Делаем пакет для Chocolatey

Совсем недавно я распробовал пакетный менеджер Chocolatey 🔗 для Windows, поддерживаемый сообществом. Я проникся и стал ставить через него почти что весь софт, которым пользуюсь. Можно просто запускать раз в неделю командлет choco update -y all и получить на выходе весь софт обновлённым, без служб обновлений и тем более без ручных обнов.

Когда я узнал о моде Slayer's Testament 🔗, в котором на Quake Engine 🔗 пытаются портировать Doom: Eternal, мне стало интересно его пощупать, но оказалось, что ни один из десятков портов этого движка на современные системы не представлен в Chocolatey и, я окунулся в незнакомый для меня мир создания пакетов для него.

Разумеется, я делал пакет по методу культа карго 🔗 и совершил множество ошибок, но прямо сейчас, то, что получилось, работает и выглядит даже не совсем ужасно.

Я собрал 🔗 пакет 🔗 для vkQuake 🔗 - реализацию Quake Engine на Vulkan API 🔗. Во-первых, мне нравится API Vulkan по религиозным соображения, во-вторых, именно этот движок рекомендуют авторы мода Slayer's Testament, а в-третьих, он выложен на гитхабе и активно обновляется.

Состав

Для минималистичной сборки пакета нужны три файла (все файлы можно посмотреть в репозитории 🔗):

vkQuake.nuspec

XML-файл с описанием пакета, автором приложения, версией, короче, разнообразная мета, которая нужна для построения страницы пакета в официальном 🔗 или личном репозитории.

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>vkQuake</id>
    <version>1.05.2</version>
    <title>vkQuake (Install)</title>
    <authors>Novum</authors>
    <owners>nett00n</owners>
    <licenseUrl>https://github.com/Novum/vkQuake/blob/master/LICENSE.txt</licenseUrl>
    <projectUrl>https://github.com/Novum/vkQuake</projectUrl>
    <iconUrl>https://rawcdn.githack.com/nett00n/vkQuake_chocolatey/b5016b97892e64a240198a0bd16690b42ed441a1/quake-vulkan.png</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Vulkan Quake port based on QuakeSpasm </description>
    <summary>vkQuake is a Quake 1 port using Vulkan instead of OpenGL for rendering. It is based on the popular QuakeSpasm port and runs all mods compatible with it like Arcane Dimensions.</summary>
    <releaseNotes>https://github.com/Novum/vkQuake/releases</releaseNotes>
    <copyright>Novum</copyright>
    <tags>quake engine game idtech portable</tags>
    <projectSourceUrl>https://github.com/Novum/vkQuake</projectSourceUrl>
    <packageSourceUrl>https://github.com/nett00n/vkQuake_chocolatey</packageSourceUrl>
    <bugTrackerUrl>https://github.com/Novum/vkQuake/issues</bugTrackerUrl>
  </metadata>
  <files>
    <file src="tools\*.ps1" target="tools"/>
  </files>
</package>

Блок files указывает какие папки и файлы включать в пакет.

⚠ Иконка вашего приложения должна находиться на CDN 🔗, наиболее популярными решениями являются jsDelivr 🔗, Statically 🔗 или Githack 🔗. Я использовал последний.

chocolateyinstall.ps1

Скрипт, устанавливающий нужный вам пакет. Пишется на PowerShell с рядом синтаксического сахара специфичного для Chocolatey.

VkQuake поставляется в виде zip-архива для 32-разрядных и 64-разрядных систем.

Сначала я сделал пакет, который ставит x64, предполагая, что для x32 я сделаю отдельный, но потом я разобрался, посмотрев на примеры кода и понял, что надо делать единый пакет - это будет и проще в поддержании и нагляднее.

На мой взгляд лучше всего держать все переменные в начале файла - их так проще изменять, да и дёргать переменные удобнее, чем хардкодить их в код:

$packageName = 'vkQuake'
$url64       = 'https://github.com/Novum/vkQuake/releases/download/1.05.2/vkquake-1.05.2_win64.zip'
$checksum64  = 'b7e5ed30a6369a3c2c31ce04dd74ebab064a0038db709cfcc661f70e8a1cb7a9'
$url32       = 'https://github.com/Novum/vkQuake/releases/download/1.05.2/vkquake-1.05.2_win32.zip'
$checksum32  = '06920832fcd726e74274bd2c4d48e507879fc1ac7ae23cd4eacbbfcd3f9d9a21'

$toolsPath   = Split-Path $MyInvocation.MyCommand.Definition
$vkQuake_folder = "$(Get-ToolsLocation)\vkQuake"

Тут я собрал ссылки на релизы, и их sha256. Можно использовать другие хэшсуммы (md5 не рекомендуется), или не использовать их вовсе, но, на мой взгляд, отсутствие хэшсуммы - это плохая практика. Если бы я выбрал какое-нибудь менее экстравагантное приложение, то переменная $vkQuake_folder мне бы не понадобилась, но мсье знает толк в извращениях, позже расскажу, зачем нужен этот путь.

  • $toolsPath же тут - это получение сервисной директории chocolatey. По-дефолту это
  • C:\ProgramData\chocolatey\lib, туда помещаются все устанавливаемые пакеты, чтоб в дальнейшем их можно было переустановить или удалить.

Насколько я понимаю конструкция try-catch это вообще хорошая практика в современном кодстайле для обработки исключений. Что это и зачем - я пока не понимаю, но скопируем, оставшуюся кодовую базу будем писать внутри.

⚠ На самом деле, не нужно, потому что все ошибки chocolatey проверяет самостоятельно

try {
  ...
  Write-ChocolateySuccess $packageName
} catch {
  Write-ChocolateyFailure $packageName "$($_.Exception.Message)"
  throw
}

Определим архитектуру установленной системы

$processor = Get-WmiObject Win32_Processor
$is64bit = $processor.AddressWidth -eq 64
$is32bit = $processor.AddressWidth -eq 32

И в зависимости от архитектуры ставим нужный нам пакет

⚠ На самом деле тоже не нужно, так как Install-ChocolateyZipPackage прекрасно себе с этим справляется самостоятельно, нужно просто передать url и url64 и checksum с checksum64:

$packageArgs = @{
  packageName    = $packageName
  url            = "https://github.com/Novum/vkQuake/releases/download/1.05.2/vkquake-1.05.2_win64.zip"
  checksum       = "b7e5ed30a6369a3c2c31ce04dd74ebab064a0038db709cfcc661f70e8a1cb7a9"
  url64          = "https://github.com/Novum/vkQuake/releases/download/1.05.2/vkquake-1.05.2_win32.zip"
  checksum64     = "06920832fcd726e74274bd2c4d48e507879fc1ac7ae23cd4eacbbfcd3f9d9a21"
  checksumType   = 'sha256'
  unzipLocation  = $toolsPath
}
Install-ChocolateyZipPackage @packageArgs

Почему дальше у меня начинаются костыли?

Потому что одного только Quake Engine недостаточно для того, чтоб играть в Quake, нужны ещё ресурсы. Id в лице Джона Кармака нужно высказать отдельные благодарности за то, что он выкладывает в открытый доступ исходный код своих движков, однако уровни, текстуры и звуки всё ещё собственность компании. Изначально Quake поставлялся по лицензии shareware, в которой доступна только часть контента, а остальные уровни нужно было покупать. Сейчас Shareware-версию ресурсов нельзя скачать на официальном сайте id, но легко можно нагуглить. Если у вас есть дисковая, или например steam-копия игры, то можно взять ресурсы из них. Кроме оригинально игры, можно скачать свободные ресурсы LibreQuake 🔗, а также любой пакет уровней, да хоть тот же Slayer's Testament, с которого у меня и начался этот движ.

Канонично, файлы ресурсов должны лежать в папке id1 внутри папки с игрой. Но есть нюанс - при установке другой версии пакета, всё содержимое $toolsPath будет затёрто. А значит и ресурсы тоже.

Я посмотрел на реализацию пакета 🔗 с эмулятором Cemu 🔗 У Chocolatey есть внешняя папка tools, адрес которой находится в переменной $(Get-ToolsLocation). Отсюда берётся наша переменная $vkQuake_folder.

Находим новую версия в C:\ProgramData\chocolatey\lib\vkQuake\, Переносим всё содержимое с перезаписью в c:\tools\vkQuake\ и убираем за собой

$vkQuake_latest = (Get-ChildItem $toolsPath -Recurse -ErrorAction SilentlyContinue | Where-Object {$_.Name -like 'vkquake-*'} | sort-Object {$_.CreationTime} | select-Object -First 1).FullName
Robocopy "$vkQuake_latest" "$vkQuake_folder" /R:0 /W:0 /E /XO
Remove-Item "$vkQuake_latest" -Recurse -Force -ErrorAction SilentlyContinue

И создаём ярлык для запуска в "Пуске"

Install-ChocolateyShortcut -shortcutFilePath "$env:ALLUSERSPROFILE\Microsoft\Windows\Start Menu\Programs\vkQuake.lnk" "$vkQuake_folder\vkQuake.exe" -WorkingDirectory "$vkQuake_folder"

chocolateyuninstall.ps1

Скрипт, удаляющий пакет. Тут всё просто: задаём путь до ярлыка в пуске, до папки с установленной игрой и удаляем их:

$icon_name = (Get-ChildItem "$env:ALLUSERSPROFILE\Microsoft\Windows\Start Menu\Programs" -Filter "vkQuake.lnk" -ErrorAction SilentlyContinue).FullName
$vkQuake_folder = "$(Get-ToolsLocation)\vkQuake"
Remove-Item $icon_name -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $vkQuake_folder

Сборка, проверка, доставка

Сборка

choco pack

Устанвавливаем его локально и проверяем, что всё встало

chocolatey install vkQuake -s . -y

Удаляем и проверяем, что мы за собой всё прибрали

chocolatey uninstall vkQuake -s . -y

Настраиваем пуш

choco apikey --key XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX --source "https://push.chocolatey.org/"

Сам ключ смотрим в профиле 🔗

Пушим в репо

choco push ".\vkQuake.1.05.2.nupkg" --source "https://push.chocolatey.org/"

После этого на сайте проходит верификация пакета, а также ручная модерация. Если всё в порядке, пакет появляется в общем доступе.