Skip to content

Commit

Permalink
Move OSTree commit into build directory
Browse files Browse the repository at this point in the history
Rather than keeping OSTree data separately in the toplevel `repo/`, make
it part of the build directory. This solves a bunch of issues and makes
things conceptually clearer.

See discussions in:
#159
  • Loading branch information
jlebon committed May 8, 2019
1 parent 8026aab commit 9e7f2a0
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 38 deletions.
57 changes: 44 additions & 13 deletions src/cmd-build
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,27 @@ if [ -L "${workdir}"/builds/latest ]; then
fi

previous_commit=
if [ -n "${ref:-}" ]; then
previous_commit=$(ostree --repo="${workdir}"/repo rev-parse "${ref}" 2>/dev/null || true)
fi
# If the ref was unset or missing, look at the previous build
if [ -z "${previous_commit}" ] && [ -n "${previous_build}" ]; then
if [ -n "${previous_build}" ]; then
previous_commit=$(jq -r '.["ostree-commit"]' < "${previous_builddir}/meta.json")
fi
echo "Previous commit: ${previous_commit:-none}"

if [ -n "${previous_commit}" ]; then
# always make sure we have the previous commit object, so that `db diff` works
obj=${previous_builddir}/ostree-commit # look for ostree-commit first for backcompat
if [ ! -f "${obj}" ]; then
obj=${obj}-object
fi
mkdir -p "${tmprepo}/objects/${previous_commit::2}"
cp "${obj}" "${tmprepo}/objects/${previous_commit::2}/${previous_commit:2}.commit"
touch "${tmprepo}/state/${previous_commit}.commitpartial"

# and point the ref to it if there isn't one already (in which case it might be newer, but e.g. Anaconda failed)
if [ ! -f "${tmprepo}/refs/heads/${ref}" ]; then
ostree refs --repo="${tmprepo}" --create "${ref}" "${previous_commit}"
fi
fi

# Calculate image input checksum now and gather previous image build variables if any
ks_path="${configdir}"/image.ks
if [ -f "${ks_path}" ]; then
Expand Down Expand Up @@ -125,8 +137,6 @@ composejson=${PWD}/tmp/compose.json
# --cache-only is here since `fetch` is a separate verb.
runcompose --cache-only ${FORCE} --add-metadata-from-json "${commitmeta_input_json}" \
--write-composejson-to "${composejson}"
# Always update the summary, since we used to do so
ostree --repo="${workdir}/repo" summary -u
# Very special handling for --write-composejson-to as rpm-ostree doesn't
# write it if the commit didn't change.
if [ -f "${changed_stamp}" ]; then
Expand All @@ -136,7 +146,10 @@ if [ -f "${changed_stamp}" ]; then
# Save this in case the image build fails
cp -a --reflink=auto "${composejson}" "${workdir}"/tmp/compose-"${commit}".json
else
commit=${previous_commit}
# Pick up from tmprepo; that's what rpm-ostree is comparing against. It may
# be the same as previous_commit, or newer if a previous build failed image
# creation.
commit=$(ostree rev-parse --repo="${tmprepo}" "${ref}")
image_input_checksum=$( (echo "${commit}" && echo "${image_config_checksum}") | sha256sum_str)
# Note we may not actually have a previous build in the case of
# successfully composing an ostree but failing the image on the
Expand All @@ -148,7 +161,7 @@ else

# Grab the previous treecompose JSON (local developer case: treecompose succeeded but
# image build failed) if possible, otherwise grab the previous build
cached_previous_composejson="${workdir}"/tmp/compose-"${previous_commit}".json
cached_previous_composejson="${workdir}/tmp/compose-${commit}.json"
if [ -f "${cached_previous_composejson}" ]; then
echo "Resuming partial build from: ${commit}"
cp -a --reflink=auto "${cached_previous_composejson}" "${composejson}"
Expand All @@ -167,12 +180,12 @@ else
fi

if [ -n "${previous_build}" ]; then
rpm-ostree --repo="${workdir}"/repo db diff "${previous_commit}" "${commit}"
rpm-ostree --repo="${tmprepo}" db diff "${previous_commit}" "${commit}"
fi

image_input_checksum=$( (echo "${commit}" && echo "${image_config_checksum}") | sha256sum_str)
echo "New image input checksum: ${image_input_checksum}"
version=$(ostree --repo="${workdir}"/repo show --print-metadata-key=version "${commit}" | sed -e "s,',,g")
version=$(ostree --repo="${tmprepo}" show --print-metadata-key=version "${commit}" | sed -e "s,',,g")
if [ "${previous_commit}" = "${commit}" ] && [ -n "${previous_image_genver:-}" ]; then
image_genver=$((previous_image_genver + 1))
buildid="${version}"-"${image_genver}"
Expand All @@ -195,7 +208,7 @@ img_qemu=${imageprefix}-qemu.qcow2
run_virtinstall "${ref:-${commit}}" "${PWD}"/"${img_base}" --variant=cloud
/usr/lib/coreos-assembler/gf-platformid "$(pwd)"/"${img_base}" "$(pwd)"/"${img_qemu}" qemu

"${dn}"/write-commit-object "${workdir}/repo" "${commit}" "$(pwd)"
"${dn}"/write-commit-object "${tmprepo}" "${commit}" "$(pwd)"

build_timestamp=$(date -u +$RFC3339)
vm_iso_checksum=$(awk '/SHA256.*iso/{print$NF}' "${checksum_location}")
Expand Down Expand Up @@ -263,12 +276,30 @@ fi

# And add the commit metadata itself, which includes notably the rpmdb pkglist
# in a format that'd be easy to generate diffs out of for higher level tools
"${dn}"/commitmeta_to_json "${workdir}/repo" "${commit}" > commitmeta.json
"${dn}"/commitmeta_to_json "${tmprepo}" "${commit}" > commitmeta.json

# And create a tarball of an ostree repo containing the commit
if [ "${commit}" == "${previous_commit}" ]; then
cp -a --reflink=auto "${previous_builddir}/ostree-commit.tar" .
else
ostree init --repo=repo --mode=archive
ostree pull-local --repo=repo "${tmprepo}" "${ref}"
if [ -n "${ref_is_temp}" ]; then
ostree refs --repo=repo --delete "${ref}"
fi
# Don't compress; archive repos are already compressed individually and we'd
# gain ~20M at best. We could probably have better gains if we compress the
# whole repo in bare/bare-user mode, but that's a different story...
tar -cf ostree-commit.tar -C repo .
rm -rf repo
fi

# Clean up our temporary data
saved_build_tmpdir="${workdir}/tmp/last-build-tmp"
rm -rf "${saved_build_tmpdir}"
mv -T tmp "${saved_build_tmpdir}"
# Prune our tmprepo
ostree prune --repo="${tmprepo}" --refs-only --depth=0
# Back to the toplevel build directory, so we can rename this one
cd "${workdir}"/builds
# We create a .build-commit file to note that we're in the
Expand Down
1 change: 0 additions & 1 deletion src/cmd-init
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,3 @@ mkdir -p cache
mkdir -p builds
mkdir -p tmp
mkdir -p overrides/rpm
ostree --repo=repo init --mode=archive
24 changes: 17 additions & 7 deletions src/cmdlib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ preflight() {

prepare_build() {
preflight
if ! [ -d repo ]; then
fatal "No $(pwd)/repo found; did you run coreos-assembler init?"
if ! [ -d builds ]; then
fatal "No $(pwd)/builds found; did you run coreos-assembler init?"
elif ! has_privileges; then
if [ ! -f cache/cache.qcow2 ]; then
qemu-img create -f qcow2 cache/cache.qcow2 10G
Expand All @@ -135,14 +135,24 @@ prepare_build() {

echo "Using manifest: ${manifest}"

tmprepo=${workdir}/tmp/repo
if [ ! -d "${tmprepo}" ]; then
# backcompat: just move the toplevel repo/
if [ -d "${workdir}/repo" ]; then
mv -T "${workdir}/repo" "${tmprepo}"
else
ostree init --repo="${tmprepo}" --mode=archive
fi
fi

configdir_gitrepo=${configdir}
if [ -e "${workdir}/src/config-git" ]; then
configdir_gitrepo="${workdir}/src/config-git"
fi
export configdir_gitrepo

manifest_tmp_json=${workdir}/tmp/manifest.json
rpm-ostree compose tree --repo=repo --print-only "${manifest}" > "${manifest_tmp_json}"
rpm-ostree compose tree --repo="${tmprepo}" --print-only "${manifest}" > "${manifest_tmp_json}"

# Abuse the rojig/name as the name of the VM images
# Also grab rojig summary for image upload descriptions
Expand Down Expand Up @@ -230,16 +240,16 @@ EOF
rm -f "${changed_stamp}"

# shellcheck disable=SC2086
set - ${COSA_RPMOSTREE_GDB:-} rpm-ostree compose tree --repo="${workdir}"/repo \
set - ${COSA_RPMOSTREE_GDB:-} rpm-ostree compose tree --repo="${tmprepo}" \
--cachedir="${workdir}"/cache --touch-if-changed "${changed_stamp}" \
--unified-core "${manifest}" ${COSA_RPMOSTREE_ARGS:-} "$@"
--unified-core --no-parent "${manifest}" ${COSA_RPMOSTREE_ARGS:-} "$@"

echo "Running: $*"

# this is the heart of the privs vs no privs dual path
if has_privileges; then
sudo -E "$@"
sudo chown -R -h "${USER}":"${USER}" "${workdir}"/repo
sudo chown -R -h "${USER}":"${USER}" "${tmprepo}"
else
runvm "$@"
fi
Expand Down Expand Up @@ -498,6 +508,6 @@ run_virtinstall() {
--ostree-ref="${ostree_rev}" \
--location "${iso_location}" \
--configdir="${configdir}" \
--ostree-repo="${workdir}"/repo "$@"
--ostree-repo="${tmprepo}" "$@"
mv "${tmpdest}" "${dest}"
}
17 changes: 0 additions & 17 deletions src/prune_builds
Original file line number Diff line number Diff line change
Expand Up @@ -174,20 +174,3 @@ if skip_pruning:
for build in builds_to_delete:
print(f"Pruning build {build.id}")
shutil.rmtree(os.path.join(builds_dir, build.id))

# and finally prune OSTree repos
print(f"Pruning repo")
repo = os.path.join(args.workdir, 'repo')

# For now, we just use the --keep-younger-than CLI here. Doing this more
# accurately would require enhancing the `prune` CLI (or just use the API
# directly?). Or we could also manually figure out the depth of the oldest
# build and then use that as the arg to `--depth`.
oldest_ostree_t = new_builds[-1].ostree_timestamp
# In a quick test, it seems like --keep-younger-than=x actually keeps commits
# with timestamps exactly equal to x, but the name is a bit tricky so let's
# be safe and just pick a time 1h before that so we're doubly sure. It might
# keep a few other older commits, but meh...
younger_than = rfc3339_time(oldest_ostree_t - timedelta(hours=1))
subprocess.run(["ostree", "prune", "--repo", repo, "--refs-only",
f"--keep-younger-than={younger_than}"], check=True)

0 comments on commit 9e7f2a0

Please sign in to comment.