Draft Builds

Draft builds allow for a workflow of building the name rpm NVR multiple times and then choosing one of those builds to promote.

The draft build feature was added in version 1.34.0

What is a draft build?

In the simplest terms, draft builds are builds with the draft flag set to True. This flag has multiple implications:

  1. Koji adds a draft suffix to the release value for draft builds. The format of this suffix is ,draft{build_id}. This ensures that the NVR of draft builds is unique, even if the base NVR (without the suffix) is not.

  2. The NVRA values for rpms included in a draft build are not required to be unique.

  3. System policy (notably the tag policy) may set different rules for draft builds.

Draft builds should not be confused with scratch builds. Scratch builds are simply stored as files and cannot be tagged in Koji. Draft builds, on the other hand, are actual builds. They can be tagged (subject to policy) and hence potentially used in buildroots. They can be promoted to become normal builds.

Building a draft build

A draft build is triggered simply by passing the --draft option to the build command. The resulting build will be a imported as a draft build. Otherwise the build process is identical.

At the moment, this feature is only relevant for rpm builds, but it may be extended in the future.

Promoting a draft build

Draft builds can be “promoted” to non-draft using the promote-build cli command.

When a draft build is promoted, it is renamed to remove the draft suffix. The build directory is moved to its new location, and the original path (the one that is includes the draft suffix) is replaced with a symlink to the new location.

Build promotion is a one-time transition, i.e. builds cannot be “unpromoted”. Only one draft build for a given NVR can be promoted, and once Koji has a non-draft build for a given NVR, further draft builds for that NVR are blocked.

An Example

You could trigger a draft build with a command like the following:

$ koji build --draft f39-candidate mypackage-1.1-35.src.rpm

Once the build completes, you would have a build named something like:

mypackage-1.1-35,draft_51515

The number in the draft suffix will be the same as the build id. This makes draft builds stand out. However, note that the component rpms do not have the draft suffix added.

$ koji buildinfo 51515
BUILD: mypackage-1.1-35,draft_51515 [51515]
Draft: YES
State: COMPLETE
Built by: kojiuser
Source: mypackage-1.1-35.src.rpm
Volume: DEFAULT
Task: 12082 build (f39-candidate, mypackage-1.1-35.src.rpm)
Finished: Thu, 04 Jan 2024 20:02:18 EST
Tags: f39-candidate
Extra: {'source': {'original_url': 'mypackage-1.1-35.src.rpm'}}
RPMs:
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-1.1-35.noarch.rpm
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-devel-1.1-35.noarch.rpm
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-1.1-35.src.rpm

You can build the same NVR as a draft multiple times.

$ koji build --draft f39-candidate mypackage-1.1-35.src.rpm
$ koji buildinfo 51516
BUILD: mypackage-1.1-35,draft_51516 [51516]
Draft: YES
State: COMPLETE
...

Once you have a build that is satisfactory, you can promote it.

$ koji promote-build mypackage-1.1-35,draft_51516
mypackage-1.1-35,draft_51516 has been promoted to mypackage-1.1-35
$ koji buildinfo mypackage-1.1-35
BUILD: mypackage-1.1-35 [51516]
State: COMPLETE
Built by: kojiuser
Source: mypackage-1.1-35.src.rpm
Volume: DEFAULT
Task: 12082 build (f39-candidate, mypackage-1.1-35.src.rpm)
Finished: Thu, 04 Jan 2024 20:02:18 EST
Promoted by: kojiuser
Promoted at: Tue, 09 Jan 2024 14:13:48 EST
Tags: f39-candidate
Extra: {'source': {'original_url': 'mypackage-1.1-35.src.rpm'}}
RPMs:
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-1.1-35.noarch.rpm
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-devel-1.1-35.noarch.rpm
/mnt/koji/packages/mypackage/1.1/35,draft_51515/noarch/mypackage-1.1-35.src.rpm

Dealing with duplicate NVRAs

The NVRAs for all non-draft rpms in Koji are required to be unique. This is enforced by a database constraint. However, this constraint does not apply to draft builds. So, it is possible to have rpms of the same name in Koji if draft builds are used.

When Koji is asked to look up an rpm by name, it will report the non-draft rpm if it exists. Otherwise, it will chose the matching draft rpm with the highest id.

Because of this, the safest way to specify an rpm is to use its rpm id.

Policies for draft builds

The is_draft policy test returns True if the build in question is a draft and False otherwise. This is primarily useful in the tag policy to limit where draft builds can go.

Note that Koji’s default policies do not include special rules for draft builds, so by default draft builds can be used anywhere a regular build can. Koji administrators can adjust their policies to match their own workflows.

For example, you could use the tag policy to restrict draft builds to only certain tags. E.g.

[policy]
tag =
    is_draft && operation move tag :: {
        tag *-draft *-draft-* !! deny draft builds are only allowed in draft tags
    }
    ...

For further information on Koji policies, see the policy documentation