DNF4-PRE-TRANSACTION-ACTIONS(8)

πŸ’… DNF4-PRE-TRANSACTION-ACTIONS(8) β€” the dnf4-pre-transaction-actions page, bestie edition πŸŽ€

okay so this is a page from dnf-plugins-core, and it's all about the DNF pre transaction actions Plugin. no cap, it's lowkey one of the most useful little plugins ever. let's get into it πŸ¦‹


✨ NAME ✨

dnf4-pre-transaction-actions β€” the DNF pre transaction actions Plugin. that's the whole name, she's iconic like that πŸ‘‘


🌸 DESCRIPTION 🌸

so here's the vibe: this plugin lets you define actions that get executed the moment an RPM transaction starts. like, right when it kicks off. main character energy ✨

each action can define a glob-like filtering rule β€” either on the package NEVRA or on the package files β€” and it also gets to say whether it cares about the package being installed or removed. and where do you define these actions? in action files, obviously πŸ’…


πŸŽ€ CONFIGURATION πŸŽ€

the plugin config lives at /etc/dnf/plugins/pre-transaction-actions.conf. and heads up β€” all the configuration options go in the [main] section. that's the only section. periodt.

  • enabled β€” whether the plugin is enabled. default value is True. (yes bestie, she's on by default, go off πŸ‘‘)
  • actiondir β€” path to the directory with action files. important: action files must have the .action extension. default value is "/etc/dnf/plugins/pre-transaction-actions.d/". don't forget the trailing slash, she's picky about that πŸ“

🧚 ACTION FILE FORMAT 🧚

okay so the rules of the action file, listen up:

empty lines? ignored. lines that start with a # character? also ignored. those are comments, we love a comment πŸ’–

every other non-comment line defines one action, and it consists of three items separated by colons:

package_filter:transaction_state:command

and here's what each of those three is giving:

πŸ¦‹ package_filter

a glob-like filtering rule applied on the package NEVRA (also in the shortened forms) or on package files. so it matches on either one, iykyk.

🌈 transaction_state

this one filters packages according to their state in the transaction. three options, all valid:

  • in β€” packages that will appeared on the system. the listed states are: downgrade, install, obsolete, reinstall, upgrade.
  • out β€” packages that will disappeared from the system. the listed states are: downgraded, obsoleted, remove, upgraded.
  • any β€” all packages. she does not discriminate πŸ’…

πŸ’œ command

any shell command. like, literally any shell command. and the following variables in the command will be substituted:

  • ${name}, $name β€” package name
  • ${arch}, $arch β€” package arch
  • ${ver}, $ver β€” package version
  • ${rel}, $rel β€” package release
  • ${epoch}, $epoch β€” package epoch
  • ${repoid}, $repoid β€” package repository id
  • ${state}, $state β€” the change of package state in the transaction. the values are: "downgrade", "downgraded", "install", "obsolete", "obsoleted", "reinstall", "reinstalled", "remove", "upgrade", "upgraded"

⭐ the execution rules (important, don't skip) ⭐

so the shell command gets evaluated for each package that matched the package_filter and the transaction_state. cute, right?

but here's the twist πŸ‘€ β€” after variable substitution, any duplicate commands will be removed, and each command will only be executed once per transaction. so if ten packages match and they all produce the same command string, it runs one time. slay, no wasted work.

the order of execution of the commands follows the order in the action files, but it may differ from the order of packages in the transaction. in other words (the original literally says "in other words" so I'm keeping that):

when you define several action lines for the same package_filter these lines will be executed in the order they were defined in the action file when the package_filter matches a package during the trasaction_state state. However, the order of when a particular package_filter is invoked depends on the position of the corresponding package in the transaction.

(and yes, trasaction_state is spelled like that in the original β€” I'm not fixing her, she's perfect πŸ™ˆ)


πŸ’– An example action file πŸ’–

look at this gorgeous example, study it, love it:

# log all packages (state, nevra, repo) in transaction into a file.
*:any:echo '${state} ${name}-${epoch}:${ver}-${rel}.${arch} repo ${repoid}' >>/tmp/pre-trans-actions-trans.log

# The same shell command (after variables substitution) is executed only once per transaction.
*:any:echo '${repoid}' >>/tmp/pre-trans-actions-repos
# will write each repo only once to /tmp/pre-trans-actions-repos, even if multiple packages from
# the same repo were matched

see what she did there? that second one is the deduplication flex 😭πŸ”₯


πŸ‘‘ AUTHOR πŸ‘‘

See AUTHORS in your Core DNF Plugins distribution. (go find them, they're lovely, give them a follow fr fr 🫢)


2014, Red Hat, Licensed under GPLv2+. we stan open source πŸ’œ


and that's the whole page, bestie! 🌈 this was version 4.10.1, dated Mar 28, 2025 β€” so drink some water, go run your transactions, and remember: the pre transaction actions plugin is always there for you at the start line πŸ§šβœ¨πŸ’…

πŸ“¦ where this page comes from