In Packit, release synchronization is the process of landing an upstream release in a dist-git repo. Let's take a look at how the process works under the hood and how you can customize it.
First, let me define some terms:
propose_downstream- release sync job triggered by an upstream release, configured upstreampull_from_upstream- release sync job triggered by a release-monitoring.org event, configured in dist-git- action - list of commands that can replace the default Packit implementation of a certain step of the process
- hook - action that does nothing by default
- source - source defined in the spec file, either as a
Source/SourceNtag or as a%sourcelistentry - remote source - source defined as a URL
propose_downstream and pull_from_upstream share most of the implementation. One notable
difference is that pull_from_upstream always uses the downstream spec file as a base for
the update, even if there is an upstream spec file.
Cloning
As the first step, Packit clones git repositories, both upstream and dist-git. If you are
running pull_from_upstream with no
upstream_project_url then there is no upstream
repository and only dist-git is cloned. Environment variables PACKIT_UPSTREAM_REPO and
PACKIT_DOWNSTREAM_REPO, which are available to you in actions, contain paths to the
respective local clones, PACKIT_UPSTREAM_REPO also being the working directory in
the actions. If there is no upstream repository, PACKIT_UPSTREAM_REPO is not set and
the working directory for actions (exposed as PACKIT_PWD) is an empty temporary directory.
At this point, proposed version and release tag are determined. Proposed version, available
to you in actions as PACKIT_PROJECT_VERSION, comes from an upstream release
(propose_downstream), a release-monitoring.org event
(pull_from_upstream), or it can be provided as a CLI argument. Release tag is derived from
the proposed version using
upstream_tag_template.
After cloning, the upstream repository, if any, is checked out at the release tag. The dist-git repository is switched to the branch for which the current job runs.
If the proposed version is lower than the version already in the downstream spec file, the synchronization is aborted.
post-upstream-clone hook
This is the first hook that is being run. As it is a hook, Packit does nothing by default, but you can use it to modify files in the upstream or downstream repository before the synchronization begins. For example, you could generate a spec file, modify sources, or run a build system command that produces files needed later.
Version check and commit signature verification
The proposed version and the version in the upstream spec file are both matched against
version_update_mask (if configured) and the
synchronization is aborted if the matches differ. Note that this check only applies to
branched Fedora and EPEL, not Rawhide. Similarly, if
version_update_specifiers is configured,
the proposed version is checked against it and the update is aborted if it doesn't match.
The head commit in the dist-git repo is then verified against
allowed_gpg_keys (if configured). If the commit
is not signed by one of the allowed keys, the synchronization is aborted.
pre-sync hook
This hook runs after the version and signature checks but before any files are modified. This is your last chance to make changes before the actual synchronization begins.
Dist-git preparation
When create_pr is enabled (the default),
Packit creates a new branch in the dist-git repo from the current branch, resets the working
directory and rebases onto the target branch. All changes will be made on this branch and
submitted as a pull request.
commit-message action
Before starting the actual file synchronization, Packit evaluates the commit-message
action. If you have defined this action, the stdout of your commands is captured and parsed
as the commit message. Everything after PACKIT_DEBUG_DIVIDER is used (so you can print
debug output before it). The first paragraph becomes the commit title, the rest becomes the
commit description.
If you haven't defined this action, Packit uses a default commit message:
Update to {version} upstream release
- Resolves: {bug} # for each resolved Bugzilla bug, if any
Upstream tag: {tag} # omitted if there is no upstream git repo
Upstream commit: {commit} # omitted if there is no upstream git repo
Commit authored by Packit automation (https://packit.dev/)
Note that this action is evaluated before prepare-files, so the commit message is
determined early in the process. However, it has access to all the version and tag
information it needs. See the
documentation for available environment
variables.
prepare-files action
This is the most important action in the sync release process. It controls how the spec file is updated.
Default behavior
When not overridden, Packit does the following:
If sync_changelog is set to true, the spec file is
synced as-is from upstream, including its %changelog section. No special changelog handling
is done. Otherwise, Packit copies the upstream spec file content to the downstream spec file
but preserves the downstream %changelog section. It then:
- Updates the
Versiontag to the new version. - Determines and sets a new
Releasevalue (typically resetting it to1for a new version). - Adds a new changelog entry (unless the spec file uses
%autochangelog, in which case no manual entry is needed). - Removes the upstream spec file from the list of files to sync, so that the rsync step that follows doesn't overwrite the carefully constructed downstream spec file.
The changelog entry text comes from the changelog-entry action (see below) or defaults to
"- Update to version {version}". If there are resolved Bugzilla bugs and no custom
changelog-entry action, "- Resolves: {bug}" lines are appended. The entry can also be
overridden by
copy_upstream_release_description
(see changelog-entry below).
When overridden
If you define a custom prepare-files action, all of the default behavior described above
is skipped. For propose_downstream, keep in mind that the upstream spec file will still be
synced by the rsync step that follows, so avoid modifications to the downstream spec file
until after the synchronization. This is generally not a concern for pull_from_upstream,
unless upstream_project_url is configured and
the upstream repository contains a file at the same path as
specfile_path — in that case, rsync would overwrite
the downstream spec file as well.
changelog-entry action
This action only runs if prepare-files is not overridden,
sync_changelog is not set to true and the
downstream spec file doesn't use %autochangelog.
When defined, the stdout of your commands is used as the changelog entry text. When not
defined, the default entry "- Update to version {version}" is used.
If copy_upstream_release_description
is set to true and there is an accessible upstream git forge, the release description from
the upstream release is used as the changelog entry instead, regardless of whether a default
or custom entry was produced (but not if %autochangelog is used).
See the documentation for available environment variables.
Files synchronization
After prepare-files completes, the files listed in
files_to_sync are copied from the upstream repository
to the dist-git repository using rsync. By default,
files_to_sync includes the spec file and the Packit
configuration file. If you configure
files_to_sync explicitly, only the files you specify
are synced.
As mentioned above, when the default prepare-files behavior runs (and
sync_changelog is not set to true), the spec file
is removed from this list. When
sync_changelog is true or when prepare-files is
overridden, the spec file remains in the list and is synced as-is.
Download of remote sources
After files are synced, Packit downloads source archives. This includes:
- Sources defined in the
sourcesconfiguration option in Packit config - Sources from the lookaside cache (listed in the
sourcesfile in dist-git) - All remote sources and patches (URLs) defined in the spec file
post-modifications hook
This hook runs after sources are downloaded but before uploading anything to the lookaside cache. It does nothing by default.
This is useful if you need to modify any files after all the spec file updates and source downloads are complete. For example, you could patch a source archive or generate additional files.
Upload to lookaside cache
After the post-modifications hook, Packit determines what source archives defined in the
downstream spec file need to be uploaded to the lookaside cache. Archives tracked by git in
the dist-git repository are filtered out. Of the rest, any archive missing from the cache or
from the sources file in dist-git is included. If there is anything to upload, Packit
initializes a Kerberos ticket and runs the equivalent of fedpkg new-sources.
If upload_sources is set to false in the Packit
configuration, the upload runs in offline mode — the sources file is updated locally but
nothing is actually uploaded to the cache. This can be useful for testing.
Commit
Packit stages all changes with git add -A and creates a commit with the message determined
by the commit-message action (or the default message).
Pull request
If create_pr is enabled (the default), Packit
pushes the branch to a fork of the dist-git repository and creates a pull request (or
updates an existing one if a PR from the same branch already exists).
The PR description includes links to the upstream tag, commit and release monitoring project, as well as any resolved Bugzilla bugs.
If fast_forward_merge_into
is configured, Packit also creates pull requests for those branches, pointing to the same
commit. The same version checks
(version_update_mask,
version_update_specifiers) are applied to
each fast-forward branch individually.
If create_pr is false, Packit pushes the
changes directly to the dist-git branch.
Summary
The release synchronization process has several customization points. Actions
(prepare-files, commit-message, changelog-entry) replace default behavior entirely
when overridden. Hooks (post-upstream-clone, pre-sync, post-modifications) let you run
additional commands at specific stages without replacing anything. For a full reference of
available configuration options and environment variables, see the
documentation.
