Changelog
All notable changes to NAPT (Not a Pkg Tool) will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
Fixed
- Fixed crash when an MSIX manifest's
<PublisherDisplayName/>element is present but contains no text. Publisher now defaults to an empty string in that case instead of triggering a downstreamTypeError.
0.5.0 - 2026-04-05
Added
- Automatic recipe validation in pipeline commands -
napt discover,napt build, andnapt uploadnow validate the merged configuration before proceeding. Invalid recipes produce clear error messages instead of failing with unexpected errors mid-pipeline - Configuration provenance in
napt validate --debug- Shows which config layer (code default, org.yaml, vendor defaults, or recipe) set each value. Helps debug unexpected configuration by tracing the full merge history - MSIX installer support - NAPT now supports
.msixinstallers alongside MSI and EXE. Metadata (display name, version, architecture, package identity) is extracted fromAppxManifest.xmlinside the package. Detection and requirements scripts query the AppX package database; install and uninstall commands are auto-generated from manifest metadata unless overridden withpsadt.override_msix_commands: true. Install scope is controlled byintune.run_as_account:"system"(default) uses provisioned cmdlets (Add-AppxProvisionedPackage/Remove-AppxProvisionedPackage);"user"uses per-user cmdlets (Add-AppxPackage/Remove-AppxPackage). Detection and requirements scripts automatically query the correct store based on the same setting.psadt.app_vars.RequireAdmindefaults tofalsewhen scope is"user" intunewin.releaseconfig key - PinIntuneWinAppUtil.exeto a specific release for reproducible builds (e.g.,release: "1.8.6"). Defaults to"latest", which resolves the current release via GitHub API. Each version is cached independently undercache/tools/{version}/logging:top-level section - New optional section for per-recipe logging configuration. Supportslog_format(cmtrace,text),log_level(verbose,debug), andlog_rotation_mb- New
intune:fields - Expanded metadata and upload behavior fields, all configurable at org, vendor, or recipe level:developer,owner,notes,logo_path,minimum_supported_windows_release,install_command,uninstall_command,is_featured(Company Portal featured app, defaults tofalse),allow_available_uninstall,device_restart_behavior,max_run_time_minutes,enforce_signature_check, andrun_as_32_bit - Sample recipe:
recipes/Microsoft/vscode.yaml- New example recipe for Visual Studio Code using theapi_jsonstrategy
Changed
- Build script module restructured - Detection and requirements script
generation consolidated into
registry_scriptsmodule (registry-based MSI/EXE) and newmsix_scriptsmodule (AppX-based MSIX). Shared PowerShell logging functions split from registry-specific helpers for cleaner template reuse - BREAKING: Recipe schema flattened - The
app:wrapper is removed. Fieldsname,id,discovery:,psadt:,intune:, andlogging:are now top-level. Update all recipes by moving fields out ofapp: - BREAKING:
source:renamed todiscovery:- All discovery configuration must move fromsource:todiscovery:. Affects all four strategies:api_github,api_json,url_download,web_scrape - BREAKING:
win32.installed_checkreplaced byintune.detection- Detection configuration moves fromwin32.installed_check.*tointune.detection.*. Fields are unchanged (display_name,architecture,exact_match,override_msi_display_name) - BREAKING: Directory config keys renamed -
defaults.discover.output_dir,defaults.build.output_dir, anddefaults.package.output_dirare nowdirectories.discover,directories.build, anddirectories.package. Updatedefaults/org.yamlif you set these keys
Fixed
- Cached installer filename now survives re-runs - NAPT stores the actual
downloaded filename in state after each download. On subsequent runs,
cache hits use the stored path instead of re-deriving from the recipe URL.
Previously, if the server returned a
Content-Dispositionheader or the download URL redirected to a different path, the cached file could not be found and the run would fail - Incomplete or stale cache no longer requires
--stateless- If the cache is missing fields or the cached file was deleted, NAPT automatically forces a fresh download instead of failing with a confusing error message intune.device_restart_behaviordefault corrected to"basedOnReturnCode"- Previously an inline fallback used"allow"instead of the value defined inDEFAULT_CONFIGnapt uploadnow creates two Intune Win32 app entries whenbuild_typesis"both"- Previously only one entry was created regardless ofbuild_types. The install entry (detection script only, base app name) and the update entry (detection + requirements scripts, prefixed withupdate_name_prefix) are now each created, uploaded, and committed in sequence. Single-entry behavior for"app_only"and"update_only"is unchanged- Version cache uses semantic comparison - Versions with a
vprefix (e.g.,v1.2.3vs1.2.3) are now correctly recognized as matching and won't re-download unnecessarily
0.4.0 - 2026-03-08
Added
napt upload <recipe>- New command uploads.intunewinpackages directly to Microsoft Intune via the Graph API. Authentication tries service principal (AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_TENANT_ID), then managed identity, then device code (requiresAZURE_CLIENT_ID+AZURE_TENANT_IDset and a TTY)napt package --version VERSION- New flag to target a specific build version instead of the most recent (e.g.,napt package recipes/Google/chrome.yaml --version 130.0.6723.116)- Configurable directory defaults and new CLI flags - All pipeline directory
flags now read from
defaults/org.yamlwhen not set on the CLI, and new flags are available on each command:napt discover --output-dir DIR- where to save downloaded installersnapt build --downloads-dir DIR- where to find the installernapt build --output-dir DIR- where to save buildsnapt package --builds-dir DIR- where to find the buildnapt package --output-dir DIR- where to save packages Three new config keys control the defaults:defaults.discover.output_dir(downloads),defaults.build.output_dir(builds), anddefaults.package.output_dir(packages). Each key is shared between the command that produces and the command that consumes the directory
- Code-Based Defaults - NAPT now ships with complete built-in defaults, making
pip install naptwork out of the box without requiring any configuration files. Organization defaults (defaults/org.yaml) and vendor defaults are now optional overrides rather than requirements napt initCommand - New command to scaffold NAPT project structure. Createsrecipes/,defaults/vendors/, and a commenteddefaults/org.yamltemplate. Safely skips existing files; use--forceto overwrite with automatic backup
Changed
napt packagenow takes<recipe>instead of<build_dir>- All commands now take a recipe path for consistent CLI usage. The build directory is inferred automatically from the recipe's app ID by scanning the builds output directory for the most recent completed buildnapt packageoutputs to versioned paths - Package output is nowpackages/{app_id}/{version}/Invoke-AppDeployToolkit.intunewin. Only one version is kept per app — the previous version directory is removed automatically when a new one is packaged (single-slot). Detection and requirements scripts are copied alongside the.intunewinfile sonapt uploadis self-contained and does not need the builds directory- Four-Layer Configuration - Configuration system now has four layers: code defaults (baseline) -> org.yaml (optional) -> vendor.yaml (optional) -> recipe (required). Old configs continue to work; new fields automatically get code defaults
0.3.1 - 2026-02-03
Changed
- PyPI Package Name - Package renamed from
notapkgtooltonaptfor simpler installation (pip install napt) - Automated PyPI Publishing - Releases now automatically publish to PyPI via GitHub Actions using Trusted Publisher (OIDC)
0.3.0 - 2026-02-02
Added
- Win32 Configuration Validation - Recipe validation now checks
win32configuration fields for correct types and values, with typo detection suggesting similar field names (e.g., "Did you mean 'display_name'?") - Detection Script Generation - Automatic PowerShell detection script generation for Intune Win32 app deployments during build process. Scripts check Windows uninstall registry keys, support exact or minimum version matching, and include CMTrace-formatted logging
- Requirements Script Generation - Automatic PowerShell requirements script generation for Intune Update app entries. Scripts check if an older version is installed and output "Required" when applicable
- Installer Type Filtering - Detection and requirements scripts now filter registry entries based on installer type. MSI builds strictly match MSI registry entries only; EXE builds permissively match any entry to handle EXE installers that run embedded MSIs internally
- Architecture-Aware Detection - Detection and requirements scripts now use explicit registry views based on target architecture, preventing false positives when x86 and x64 versions coexist. MSI architecture is auto-detected from Template property; non-MSI installers require
win32.installed_check.architectureconfiguration (x86, x64, arm64, or any) - MSI Display Name Override - New
override_msi_display_nameflag allows using customdisplay_nameinstead of MSI ProductName for registry lookups, solving edge cases where ProductName contains version numbers (e.g., "7-Zip 25.01"). Supports wildcards (*,?) for flexible matching
Changed
- BREAKING: Non-MSI Architecture Required -
win32.installed_check.architectureis now required for non-MSI installers (EXE, etc.). Allowed values:x86,x64,arm64,any - Discovery Performance Optimization - Version-first strategies (web_scrape, api_github, api_json) now check versions before downloading, enabling ~100-300ms update checks when unchanged instead of full downloads
- State file now saves actual download URLs for all strategies
- url_download Strategy Simplification - Removed
version.typeconfiguration requirement. MSI files are now auto-detected by file extension (.msi) for version extraction - BREAKING: Uniform Strategy Naming - Discovery strategies renamed to follow consistent
<source>_<method>pattern for better discoverability and scalability:http_static→url_download(fixed URL with file extraction)url_regex→web_scrape(web scraping for vendor download pages)http_json→api_json(generic JSON API queries)github_release→api_github(GitHub releases API)
- BREAKING: Simplified Version Types - Version type names shortened for clarity:
msi_product_version_from_file→msi- Removed nested
version.typeforweb_scrape(simplified tosource.link_selectorandsource.version_pattern)
- BREAKING: Recipe Format Change - Changed recipe format from
apps:array toapp:single object. Recipes now define a single application per file instead of an array. This simplifies the schema and matches actual usage (only one app was ever processed per recipe). - Documentation Rendering - Fixed module docstrings to follow Google-style format with proper indentation for mkdocstrings
Fixed
- Fixed ETag preservation bug causing alternating download/cached behavior in url_download strategy
- Fixed docstring formatting issues across multiple modules (missing blank lines, incorrect Args sections)
0.2.0 - 2025-11-07
Added
- PSADT Package Generation with
napt buildcommand - Creates complete PSADT v4 deployment packages with custom branding support - .intunewin Package Creation with
napt packagecommand - Generates Intune-ready packages using Microsoft's IntuneWinAppUtil.exe - GitHub Release Strategy (
api_github) - Discovers versions from GitHub releases with asset pattern filtering - HTTP JSON Strategy (
api_json) - Extracts versions and download URLs from JSON API endpoints using JSONPath - URL Regex Strategy (
url_pattern) - Extracts versions directly from URLs using regex patterns - Roadmap Management (
docs/roadmap.md) - Structured feature tracking with status categories and workspace automation - MkDocs Documentation Site - User guide and auto-generated API reference
Changed
- State File Schema v2 - Convention-based file paths, improved metadata tracking, per-app isolation (Breaking: old state files need regeneration)
- CLI Commands - Renamed
checktovalidatefor clarity - Recipe Format - PSADT
install/uninstallblocks now generate PSAppDeployToolkit v4 scripts - Console Output - Replaced Unicode symbols with ASCII for Windows compatibility (
✓→[OK], etc.)
Fixed
- PSADT Template Handling - Correctly identifies and copies PSAppDeployToolkit_Template_v4.zip files
- ETag Preservation - Fixed bug causing alternating download/cached behavior in url_download strategy
- Branding Application - Fixed Assets/ directory path resolution for custom icons and banners
- Version Extraction - Corrected regex escape sequences causing SyntaxWarnings
0.1.0 - 2025-10-23
Initial internal release.
Added
- Recipe Validation with
napt checkcommand - Validates recipe syntax and configuration without network calls - HTTP Static Discovery - Downloads installers from static URLs with ETag caching for efficiency
- Three-Layer Configuration - Organization defaults, vendor overrides, and recipe-specific settings with deep merging
- Version Comparison - Supports semantic versioning, MSI/EXE numeric versions, and Chrome-style multi-part versions
- MSI Version Extraction - Cross-platform support (Windows via msilib/PowerShell, Linux/macOS via msitools)
- Robust Downloads - Retry logic, atomic writes, SHA-256 verification, and conditional requests