# v1.6.1

+ Fix typo bug in the SSH client preventing connection

# v1.6

A small release with a few features and fixes. Future development will utilise smaller, more regular releases to avoid long gaps waiting on feature X to be complete.

This release also changes the git branching model to use `current` for anything non-breaking, and the `next` branch now targets the next _major_ version. This should avoid unncessary confusion for the wonderful contributors to `pyinfra`.

Operations:

+ Make it possible to load relative (to CWD) templates (includes/bases/etc) (@themanifold)
+ Add `apt.dist_update` operation (@bauen1)
+ Fix `files.Link` fact & `files.link` operation where path pre-exists and is not a link

Connectors:

+ Support setting `shell_executable=None` to pass raw commands to the target (@KuxaBeast)
+ Fix handling of SSH proxy jump config
+ Only load SSH host keys once
+ Make it possible to specify a SSH config file via `host.data.ssh_config_file`


# v1.5

This release includes a huge number of improvements, major highlights:

**Automatic sudo password prompting** - at last! pyinfra can now detect when a sudo password is required and will prompt the user.

**Global config object** - there is now a `pyinfra.config` object that should be used to set config variables:

```py
from pyinfra import config
config.SUDO = True
```

This replaces the old style of setting `SUDO = True` at the top of files which was extracted via the AST. This new object means config variables can be set to anything (including the results of functions) and work across multiple deploy files.

Operation & fact updates:

+ Add `pkgin.packages` & `pkgin.upgrade` operations (@lun-4)
+ Add `pkgin.PkginPackages` fact (@lun-4)
+ Add `selinux.FileContext` & `selinux.SEBoolean` facts (@benridley)
+ Add `openrc.service` operation
+ Add `openrc.OpenrcStatus` & `openrc.OpenrcEnabled` facts
+ Add last login time to `server.Users` fact (@sysadmin75)
+ Fetch held deb package versions in `deb.DebPackages` fact (@GerardoGR)
+ Add `force`, `force_backup` and `force_backup_dir` arguments to `files.files`, `files.directory` & `files.link` operations
+ Add resource and SSL arguments to `mysql.user` operation
+ Add `with_grant_option` argument to `mysql.privileges` operation
+ Add `available` argument to `apk.packages` operation (@lun-4)

Connector updates:

+ Transfer ownership of files uploaded with su/sudo (@benridley)
+ Add `ssh_forward_agent` group data variable overriding SSH config

Other bits:

+ Add `doas` & `doas_user` global arugments
+ Use host data for global arguments (`host.data.sudo`, etc)
+ Add `--data key=value` CLI flag
+ Propagate return value from `@deploy` decorator (@karlicoss)
+ Large expansion of tested idempotent operations
+ Loosen distro requirement


# v1.4.19

+ Use `uname -m` in `server.Arch` fact (@weakish)
+ Fix user check in `server.user` operation (@glassbeads)
+ Fix setting user primary group in `server.user` operation (@glassbeads)
+ Always add CWD to `sys.path` (@glassbeads)
+ Fix issues with regex parsing for `deb.DebPackage` & `deb.DebPackages` facts
+ Fix parsing apt repository lines with `[]` characters

# v1.4.18

+ Fix exception collecting `Docker.*` facts on objects that don't exist
+ Support variable interpolation in `files.FindInFile` fact
+ Add `debug-inventory` example to the help doc
+ Show a warning when a `--limit` option doesn't match any hosts
+ Warn only if SSH keys fail to load
+ Include actual error when we encounter authentication errors
+ 
# v1.4.17

+ Fix excluding multiple directories in `files.sync` operation (@gchazot)
+ Cleanup filesystem mocking in operation tests (@gchazot)
+ Fix bug in command generation when config sudo user is set
+ Stop removing sudo/su arguments in the Docker connector

# v1.4.16

+ Fix loading of system SSH host keys
+ Fix/show warning when no SSH host key present on connect

# v1.4.15

+ Don't fail if `dest` in `files.put` is a directory (@oz123)
+ Improve internal unix path joining

# v1.4.14

+ Add `quote_path=True` argument to `files.[FindFiles|FindLinks|FindDirectories]` facts
+ Fix enable/disable service in `sysvinit.service` operation using un-quoted path
+ Fix path join handling in certain cases in `files.sync` operation
+ Always normalise paths in `files.[file|link|directory]` operations

# NOTE: there was an accidental release of a v1.14.14 here, which is identical to v1.4.14.

# v1.4.13

+ Fix `exclude_dir` in `files.sync` operation (@gchazot)
+ Fix multiple nested imports by properly resetting current exec filename
+ Improve error when there are no Vagrant instances and a name is provided

# v1.4.12

+ Support tag names in `git.GitBranch` fact (@stevenkaras)
+ Fix `cache_time` test in `files.download` operation (@stevenkaras)
+ Fix parsing of `server.LinuxDistribution` fact for Archlinux (@TypicalFence)
+ Correctly return `None` when no major version in `server.LinuxDistribution` fact

# v1.4.11

+ Fix removal of askpass file in `server.reboot` operation

# v1.4.10

+ Ensure services in `/usr/local/etc/rc.d` are handled in `bsdinit.service` operation
+ Check status of services in `/usr/local/etc/rd.d` in `bsdinit.RcdStatus` fact
+ Fix status checking in `bsdinit.RcdStatus` fact (for non-OpenBSD)
+ Expand BSD test boxes to include NetBsd & HardenedBSD

# v1.4.9

+ Fix connection w/`use_remote_sudo` in `ssh.upload` operation (@GerardoGR)
+ Fix `mysql.MysqlUserGrants` fact regex for `*.*` grant lines
+ Remove any askpass file before issuing reboots in `server.reboot` operation

# v1.4.8

+ Remove broken "will add user" detection in facts, just pass if user is missing
+ Quite non-string elements in `StringCommand` before passing to `shlex.quote`
+ Ignore `use_sudo_password` in the `@docker` connector
+ Loosen `jinja2` requirement to allow v3 (compatible)

# v1.4.7

+ Fix for passing `Path` objects as arguments to `files.*` operations & facts
+ Futher improvements to the updated facts docs

# v1.4.6

+ Properly handle shell quoting of filenames in all `files.*` facts
+ Update `files.*` operations to use explicit fact imports
+ Update the docs to show explicit fact import style

# v1.4.5

+ Fix missing mysql connection arguments updating privileges `mysql.database` operation (@sfermigier)
+ Fix parallel upload of askpass files
+ Properly handle shell quoting of filenames, fixes filenames with shell characters/etc for all `files.*` operations

# v1.4.4

+ Fix brew casks fact for non-mac platforms

# v1.4.3

+ Fix user fact comments with spaces by refactoring the fact (@sysadmin75)
+ Fix parsing of tab delimited crontab files with special times (@hazayan)
+ Fix incorrect lowercasing of yum & dnf package names
+ Fix/enable passing `to_ports` as an integer in `iptables.rule` operation
+ Migrate iptables facts & operations to use explicit fact imports
+ Fix/implement idempotency in iptables operations

# v1.4.2

+ Fix/implement WinRM env support (@mfrg)
+ Fix/handle Brew 2.6+ new cask CLI (@morrison12)
+ Fix parsing of tab delimited crontab files (@hazayan)

# v1.4.1

+ Improve deploy directory detection to handle nested directories
+ Copy existing file/directory permissions in `files.sync` operation
+ Treat `exited` systemd services as running in `systemd.SystemdStatus` fact
+ Fix handling of `cache_time` in `apt.update` operation
+ Fix invalid `name` arguments in `windows.service`, `windows.file` & `windows.directory` operations
+ Only show invalid auth argument warnings when not the defaults
+ Test operation global argument clashes

# v1.4

Three major themes to this release:

**Explicit fact imports** - this replaces the magic `host.fact.X` variables with explicitly imported facts, for example:

```py
# previously: host.fact.apt_sources
from pyinfra.facts.apt import AptSources
host.get_fact(AptSources)

# previously: host.fact.file('/path/to/file')
from pyinfra.facts.files import File
host.get_fact(File, path='/path/to/file')

# also now possible (previously impossible):
host.get_fact(File, path='/path/to/file', sudo=True)
```

And the CLI changes accordingly:

```sh
# previously: pyinfra INVENTORY fact apt_sources
pyinfra INVENTORY fact apt.AptSources

# previously: pyinfra INVENTORY fact file:/path/to/file directory:/path/to/directory
pyinfra INVENTORY fact files.File path=/path/to/file files.Directory path=/path/to/directory
```

This is not yet standard across the project and will be updated in subsequent releases. This also finally enables using third party facts in a sensible and explict manner. Overall, this is a dramatic improvement to the `pyinfra` fact mechanism.

**Windows operations expansion** - massive thank you to @mfrg for implementing these, huge expansion of Windows facts & operations, making it possible to really use `pyinfra` with Windows targets (additions listed below).

**Idempotency testing** - verification of operation idempotency (calling the same op twice outputs no commands/changes the second time) through testing and a large expansion in verified idempotency. Operations can now specify themselves as non-idempotent when expected (for example, `server.shell`).

Operation & fact updates:

+ Add `server.packages` operation - generic package management using the default OS package manager
+ Add `pip.venv` operation - shortcut for `pip.virtualenv(venv=True, ...)`
+ Add `server.Path` fact
+ Add `rpm.RpmPackageProvides` fact & support package aliases for `yum.packages` & `dnf.packages` operations
+ Add `windows_files.download`, `windows_files.put` & `windows_files.link` operations (@mfrg)
+ Add `windows_files.WindowsLink`, `windows_files.WindowsSha1File`, `windows_files.WindowsSha256File` & `windows_files.WindowsMd5File` facts (@mfrg)

CLI updates:

+ New style fact gathering CLI arguments
+ Prefix SSH auth flags (`--user` becomes `--ssh-user`), deprecate old versions
+ Deprecate `--facts` & `--operations` CLI flags
+ Deprecate `all-facts` command
+ Hide deprecated options from `--help`

Other bits:

+ Show warnings when using invalid auth argument combinations (`sudo_user` without `sudo`, etc)
+ Bump minimum Paramiko version to `2.7`


# v1.3.12

+ Fix & test loading non-RSA SSH keys with passwords (@Yakulu)

# v1.3.11

+ Fix custom SSH config parsing to support latest Paramiko features (`Match` directives)
+ Fix error loading SSH keys with passwords (try all key formats before failing)

# v1.3.10

+ Properly escape postgresql role/database/owner operation commands (@RobWouters)
+ Add support for additional winrm transport types & options (@mfrg)
+ Fix for `Git*` facts where the target repo doesn't exist
+ Git branches update: `master` renamed to `current` and new `next` branch tracking next minor release
+ Contributing documentation page updated to include branch description

# v1.3.9

+ Use `StringCommand` to implement fact requires commands, fixes `mysql_*` facts with passwords
+ Improve error for invalid private key files, including message for old paramiko versions
+ Fix `files.line`/`files.replace`/`server.crontab` replacements containing quotes
+ Fix `@winrm` connector command execution
+ Improve `files.template` docstring (@Gaming4LifeDE)

# v1.3.8

+ Add Debian to prettified names in `LinuxDistribution` fact (@blarghmatey)
+ Fix logging non-string args (@morrison12)
+ Tidy up new issue templates (@Gaming4LifeDE)
+ Use `export` instead of `env` so variables pass into sub-commands as expected
+ pass any `env` into fact execution within operations
+ Fix splitting of inventory filename into group name
+ Improve package name parsing in `BrewPackages` fact
+ Only append blank line before new cron entries if some already exist
+ Remove any leftover askpass files when using `use_sudo_password`

# v1.3.7

+ Support reading custom user operations in CLI mode (@tsnoam)
+ Allow adding users with duplicate UIDs in `server.user` operation (@tsnoam)
+ Add user UID/GID to `users` fact output (@tsnoam)
+ Fix uninstall command in `apk.packages` operation (@Gaming4LifeDE)
+ Fix support for `add_deploy` in API mode
+ Rename (deprecate) facts `server.Os` -> `server.Kernel` & `server.OsVersion` -> `server.KernelVersion`
+ Add `server.MacosVersion` fact
+ Add an empty line before writing in named crontab entries
+ Fix check for command change with named crontab entries
+ Properly quote package names (fix Python version specifiers with shell characters in `pip.packages` operation)

# v1.3.6

+ Ignore errors when `crontab` fails (ie, when there's no crontab)
+ Update `crontab` fact in `server.crontab` operation
+ Update `sysctl` fact in `server.sysctl` operation

# v1.3.5

+ Add support for relative includes: `local.include('./relative_file.py')`
+ Fix parsing of special times in `server.Crontab` fact
+ Fix editing `special_time` in `server.crontab` operation
+ Fix printing of imported modules in group data files when using `debug-inventory`
+ Use/respect `__all__` if defined in group data files

# v1.3.4

+ Improve matching of user hostname in `mysql_user_grants` fact

# v1.3.3

+ Fix support for package names in `deb_package` fact (@s-vx)
+ Fix check for match any vs. all in ensure packages util (fixes Pacman package groups)
+ Fix/support passing keyword functions into facts
+ Fix parsing of `mysql_user_grants` fact output
+ Fix idempotency of `mysql.privileges` operation

# v1.3.2

+ Add `pacman_unpack_group` fact (@unai-ndz)
+ Support Pacman package groups properly in `packman.packages` operation (@unai-ndz)
+ Fix only load git config if the repo directory exists in `git.config` operation
+ Fix global git config loading when files don't exist in `git_config` fact
+ Fix deploys doc example operation (@makom)
+ Fix (add quoting) download URLs containing shell characters in `files.download` operation
+ Fix checking for rsync in `@local` connector

# v1.3.1

+ Add `git_tracking_branch` fact and rework `git.worktree` operation (@remybar)
+ Add `user_mode` arg to `systemd.daemon_reload` operation (@smdnv)
+ Add `comment` arg/support to `server.user` operation (@sprat)
+ Use `StrictUndefined` when rendering templates (@relaxdiego)
+ Allow numbers in `pacman_packages` fact
+ Remove restriction on group data types
+ Improve support for `Path` objects as operation arguments (@relaxdiego)
+ Improve error output when failing to start SFTP sessions (@relaxdiego)
+ Fix readme doc link (@mrshu)
+ Fix Docker tests and separate from main tests, don't run on PRs

# v1.3

Theme of this release is improving error handling and end user experience. Highlights:

+ Make most global arguments dynamic - support different `chdir`, `sudo`, etc for different hosts within the same operation call
+ Rework line number ordering to support any nested function calls and/or imports
+ Improve error handling for unexpected internal (pyinfra) and external (user code) errors
+ Detect and error when an operation calls another using global arguments
+ Properly fail when fact commands don't execute correctly vs. a given command not being present on the host, using `requires_command` fact attribute

Operation & fact updates:

+ Add `git.worktree` operation (@remybar)
+ Add `git.bare_repo` operation (@stchris)
+ Add `user_mode` argument to `systemd.service` operation (@jprltsnz)
+ Use `hostnamectl` where available for `server.hostname` operation
+ Use `uname -a` for `hostname` fact
+ Add `user` fact

Other bits:

+ Enable using `use_sudo_password` without `sudo=True`
+ Move testing & documentation processes to GitHub actions
+ Run tests on Windows & MacOS


# v1.2.1

+ Add `pip3_packages` fact
+ Improve/fix handling of `reboot` exit code in `server.reboot` operation
+ Restore `__eq__` functionality of pseudo modules
+ Add tests for the pseudo modules

# v1.2

Lots of smaller bits in this release and massive improvement to the documentation.

Operation & fact updates:

+ **Deprecate** `init.*` operations, renamed to: `systemd.service`, `upstart.service`, `launchd.service`, `bsdinit.service`, `sysvinit.service`, `sysvinit.enable`, `server.service`
+ Add `systemd.daemon_reload` operation
+ Add `files.rsync` operation
+ Add `port` and `user` arguments to all `ssh.*` operations
+ Add `apt_keys` fact and use in `apt.key` operation
+ Add GPG facts: `gkg_key`, `gpg_keys` and `gpg_secret_keys`
+ Add `additional_ips` in `network_devices` fact
+ Add `ipv4_addrs` and `ipv6_addrs` facts to replace `ipv[46]_addresses`
+ Add `linux_gui` & `has_gui` facts

Other bits:

+ Add global `chdir`, `preserve_su_env` and `su_shell` arguments
+ Add `Config.REQUIRE_PACKAGES` to check requirements befor execution
+ Add `host_before_connect` and `host_connect_error` state callback methods
+ Support multiple `--limit` CLI arguments
+ Allow passing an integer in `files.replace` replacement lines (@vindarel)
+ Use `curl` if `wget` not present in `apt.key` operation
+ Completely remove use of `use_default_on_error` in facts
+ Many updates/tweaks to documentation + theme
+ Allow functions in/as group/host data (CLI)
+ Implement/use Angolia docsearch on documentation


# v1.1.2

+ Add `port=22` argument to the `ssh.keyscan` operation
+ Add `extra_install_args` argument to the `pip.packages` operation
+ Support uninstalling a requirements file in the `pip.packages` operation
+ Use state in `files.replace` operation, enabling noop support where appropriate
+ Add a warning when using `use_su_login`
+ Fix parsing stat output when groups contain spaces (`file`, `directory`, `link` facts)
+ Fix minimum gevent version (@alexandervdm)

# v1.1.1

+ Don't fail for user error facts when the user will be added earlier in the deploy
+ Support `shasum` command in `files.download` operation
+ Consider waiting systemd units to be running (@i-do-cpp)
+ Improve regex for systemd units (support ones with `.`) (@i-do-cpp)
+ Fix sudo passwords with special characters (@sysadmin75)
+ Fix typo in host arg warning (@weakish)

# v1.1

This is a big release with some major additions & improvements on `v1`.

Highlights:

+ Start **modifying facts during fact gathering phase**, resolving common issues with interdependent operations, expand documentation on this ([docs](https://docs.pyinfra.com/page/deploy_process.html#interdependent-operations))
+ Implement **state callback classes** dramatically improving the API experience (see `examples/api_deploy.py`)
+ Add `@dockerssh` connector that enables pyinfra to **build Docker containers on remote machines over SSH** (@charles-l)
+ Add global `precondition` and `postcondition` operation arguments
+ Fix using `su_user` on BSD/MacOS systems
+ Rework verbosity flags and **add noop logging** (ie package X is already installed) ([docs](https://docs.pyinfra.com/page/cli.html#verbosity))

Notable change:

The `yum.packages` and `dnf.packages` operations have _changed_ their "version join" string value - both package managers use `-` to join name + version while allowing `-` in the name. This leads to ambiguous behaviour for packages containing dashes, as such the version join value has been changed to `=` - meaning it can now actually be used! This means to specify a specific version of a yum/dnf package you should use `<name>=<version>` rather than `<name>-<version>`.

Smaller bits:

+ Add `REQUIRE_PYINFRA_VERSION` config option (& deprecate `MIN_PYINFRA_VERSION`)
+ Validate existing files in `file.download` with checksum arguments (@sysadmin75)
+ Stop stripping fact output (fixes `command` fact, @sysadmin75)
+ Add `extra_install_args` and `extra_uninstall_args` kwargs to `apt.packages` operation
+ Add `--use-sudo-password` CLI argument
+ Normalise `server.sysctl` handling of string/int values
+ Improve autocomplete/intellisense handling of pseudo modules `pyinfra.[host|state|inventory]`
+ Fix using sudo password with a SSH user that doesn't have access to `/tmp`
+ Fix `python.call` docstring (@leahneukirchen)
+ Fix `--serial` and `--no-wait` executing operations twice
+ Fix `server.sysctl` usage with multiple values


# v1.0.4

+ Add `selinux` fact (@FooBarQuaxx)
+ Improve/fix `rpm_packages` fact parsing (@FooBarQuaxx)
+ Stop showing arguments on operations with names

# v1.0.3

+ Reimplement `file`/`directory`/`link` facts using `stat`
    * No breaking changes
    * Adds `ctime` and `atime` to the output dictionary
+ Add `backup` argument to the `files.line` and `files.replace` operations
+ Add `SimpleNamespace` to the list of allowed data types
+ Don't fail when the destination directory is a symlink in the `files.sync` operation
+ Fix running the same fact in CLI w/different arguments
+ Add local integration tests that check idempotency (of files operations only for now)

# v1.0.2

+ Further improve fact output when errors are encountered
    * Will now output stdout + stderr when a fact command fails unexpectedly
    * This brings the same instant debugging feel to facts that operations have
+ Fix `wget` failure handling in `files.download` operation (@artizirk)
+ Improve files facts handling when file/directory/link does not exist

# v1.0.1

+ Log host fact errors/warnings
+ Switch to `distro` package for `linux_distribution` fact (@FooBarQuaxx)
+ Expand support for `os.PathLike` path variables (@FooBarQuaxx)
+ Improve checking state/host presence when calling operations (@FooBarQuaxx)
+ Don't error in `sha1_file` fact when no file exists

# v1.0

The first `1.x` release!

This release deprecates a lot of old/legacy `pyinfra` code and brings fourth a new, stable API. So long as you see no warnings when executing `pyinfra`, upgrading should require no chanages.

What's new:

+ Add new global `name` argument to name operations (deprecate `set` as the first argument)
+ Improve unexpected fact error handling, bad exit codes will be treated as errors unless the fact explicitly expects this could happen (system package managers for example)
+ [CLI] write progress/user info/logs to `stderr` only
+ [API] Consistent ordering when `add_op` and `add_deploy` functions
+ [API] Return a dictionary of `host` -> `OperationMeta` when using `add_op`
+ Enable passing a list of modules to `server.modprobe` (@FooBarQuaxx)
+ Support `Path` objects in `files.[file|directory|link]` operations
+ Support `shasum` (MacOS) in `sha1_file` fact

Breaking changes:

+ Deprecate using `set` as the first/name argument for operations
+ Rename `files.*` arguments (`name` -> `path`, `destination` -> `dest`)
+ Rename `server.*` arguments (`name` -> `user|group|cron_name|key|path`, `filename` -> `src`)
+ Rename `mysql.*` + `postgresql.*` arguments (`name` -> `user|database|role`)
+ Rename `init.*` arguments (`name` -> `service`)
+ Rename `lxd.container` argument `name` -> `id`
+ Rename `git.repo` argumenets `source` -> `src` & `target` -> `dest`
+ Rename `iptables.chain` argument `name` -> `chain`
+ Rename `python.call` argument `func` -> `function`
+ Rename `size` -> `mask_bits` inside `network_devices` fact
+ Change default of `interpolate_variables` from `True` -> `False`
+ Remove deprecated`hosts`/`when`/`op` global operation arguments
+ Rename reprecated `Config.TIMEOUT` -> `Config.CONNECT_TIMEOUT`
+ Remove deprecated `use_ssh_user` argument from `git.repo` operation
+ Remove deprecated `python.execute` operation
+ Remove deprecated `Inventory.<__getitem__>` & `Inventory.<__getattr__>` methods
+ Remove deprecated `add_limited_op` function
+ Remove deprecated legacy CLI suppot

# v0.x

[See this file in the `0.x` branch](https://github.com/Fizzadar/pyinfra/blob/0.x/CHANGELOG.md).
