diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e056762..2a0473d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -10,6 +10,7 @@ "settings": {}, "extensions": [ "davidanson.vscode-markdownlint", + "github.vscode-github-actions", "ms-azuretools.vscode-docker", "ms-vscode.cpptools-extension-pack", "ms-vscode.makefile-tools", @@ -20,6 +21,7 @@ "settings": {}, "extensions": [ "davidanson.vscode-markdownlint", + "github.vscode-github-actions", "ms-azuretools.vscode-docker", "ms-vscode.cpptools-extension-pack", "ms-vscode.makefile-tools", @@ -27,6 +29,11 @@ ] } }, + // Bind mounting ~/.netrc allows use of the GitHub CLI (`gh`) by running + // `export GH_TOKEN=$(awk '{print $6}' ~/.netrc)` within the dev container. + "mounts": [ + "type=bind,source=${localEnv:HOME}/.netrc,target=/home/vscode/.netrc,readonly" + ], "containerUser": "vscode", "updateRemoteUserUID": true } diff --git a/.dockerignore b/.dockerignore index b2fa676..fb78a7b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,7 +5,6 @@ .git/ .gitignore .vscode/ -LATEST_RPM README.md VERSION cache/ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..2f58e0b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,95 @@ +name: Build everything +on: + - push +env: + REGISTRY: ghcr.io +defaults: + run: + shell: bash + # specifying `bash` here ensures `set -eo pipefail` is active +jobs: + build-everything: + runs-on: ubuntu-latest + permissions: + # contents:write allows creating a GitHub Release. + # packages:write allows publishing an image to GitHub Packages. + contents: write + packages: write + steps: + - name: Check out repository code + uses: actions/checkout@v4 + with: + # autotag requires a reasonably complete git history. + fetch-depth: 0 + - name: Build fusedav-dev image + run: docker build --progress plain --target dev -t fusedav-dev . + - name: Install autotag + run: | + curl -fsSL https://github.com/pantheon-systems/autotag/releases/latest/download/autotag_linux_amd64 \ + -o /usr/local/bin/autotag + chmod 0755 /usr/local/bin/autotag + - name: Generate new version strings and tag(s) + env: + IMAGE_NAME: ${{ github.repository }} + run: | + echo "new-version.sh:" + scripts/compute-version.sh | tee new-version.sh + - name: Build/tag fusedav image + run: | + echo START build target extract + docker build --progress plain --target extract . --output extract + echo DONE build target extract + echo + echo START build final image + . new-version.sh + # Use older "maintainer" label instead of "org.opencontainers.image.maintainer" + # to overwrite the docker.io/library/fedora:28 value. + docker build --progress plain --target compile \ + --label "maintainer=nobody@pantheon.io" \ + --label "org.opencontainers.image.description=FUSE-based DAV client with extensions for performance" \ + --label "org.opencontainers.image.licenses=GPLv2" \ + --label "org.opencontainers.image.source=https://github.com/pantheon-systems/fusedav" \ + --label "org.opencontainers.image.vendor=Pantheon Systems, Inc." \ + --label "org.opencontainers.image.version=${SEMVER}" \ + -t fusedav . + echo DONE build final image + for tag in ${IMAGE_TAGS[@]}; do + echo "tag image as ${tag}" + docker tag fusedav $tag + done + - name: Log in to GitHub Container Registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Push final image/tag(s) to container registry + run: | + . new-version.sh + for tag in ${IMAGE_TAGS[@]}; do + echo "push ${tag}" + docker push $tag + done + - name: Create (pre-release) GitHub release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + . new-version.sh + # If NOT master, create a pre-release. + # Note that GitHub converts the tilde (`~`) which indicates a pre-release + # RPM version to a period (`.`) in the filename. This should not affect + # RPM version comparison operations. + echo "Create pre-release release:" + gh release create $GITHUB_RELEASE_NAME -p --generate-notes + . scripts/upload-gh-assets.sh + if: github.ref != 'refs/heads/master' + - name: Create GitHub release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + . new-version.sh + # Iff master, create a regular release. + echo "Create regular release:" + gh release create $GITHUB_RELEASE_NAME --generate-notes + . scripts/upload-gh-assets.sh + if: github.ref == 'refs/heads/master' diff --git a/.gitignore b/.gitignore index 1815439..3652209 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,6 @@ /tests/readwhatwaswritten /tests/rename /tests/trunc -LATEST_RPM Makefile.in VERSION _trial_temp* diff --git a/Dockerfile b/Dockerfile index 770f218..e5ec20b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,12 +14,6 @@ # # runtime is the final runtime image. # -# To build image locally: -# docker build --progress plain --build-arg CIRCLE_SHA1=$(git rev-parse --short HEAD) -t fusedav . -# -# To compile/build and extract the RPM into the `extract` directory: -# docker build --progress plain --build-arg GITHUB_SHA=$(git rev-parse --short HEAD) --target extract -t fusedav-extract . --output=extract -# FROM docker.io/library/fedora:28 AS base SHELL ["/bin/bash", "-euo", "pipefail", "-c"] @@ -50,6 +44,7 @@ FROM base AS dev RUN \ dnf install -y \ + 'dnf-command(config-manager)' \ autoconf \ automake \ bind-utils \ @@ -71,6 +66,8 @@ RUN \ tcpdump \ uriparser-devel \ zlib-devel \ + && dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo \ + && dnf install -y gh \ && dnf clean all \ && rm -rf /var/cache/dnf \ && curl -fsSL https://github.com/pantheon-systems/autotag/releases/latest/download/autotag_linux_amd64 \ @@ -80,34 +77,19 @@ RUN \ # Installing autotag above makes it available within a dev container. # When building via CI/CD, autotag is installed/called elsewhere. +# Installing gh above makes it available within a dev container. +# When building via GitHub Actions, gh is installed/called elsewhere. + USER vscode ######################################## FROM dev AS compile +# new-version.sh MUST be created before we get here COPY . /build WORKDIR /build -ARG CIRCLE_BRANCH="unknown" -ARG CIRCLE_BUILD_NUM="" -ARG CIRCLE_SHA1=0000000 - -# CHANNEL is always `release` now. -# Historically, CHANNEL could be: dev, stage, yolo, release -ARG CHANNEL=release - -# Set PACKAGECLOUD_REPO to `internal` or `internal-staging` to publish RPM. -ARG PACKAGECLOUD_REPO="" - -# RPM_VERSION is set here for local/direct `docker build` use; CircleCI builds -# will set their own value. -ARG RPM_VERSION="0.0.0+0" - -# SEMVER is set here for local/direct `docker build` use; CircleCI builds -# will set their own value. -ARG SEMVER="0.0.0-local" - # Using explicit USER instructions instead of sudo to satisfy Guardrails. USER root @@ -117,27 +99,28 @@ RUN \ USER vscode RUN \ - echo "${RPM_VERSION}" > VERSION \ - && scripts/build-rpm.sh "${CHANNEL}" \ - && if [ -n "${PACKAGECLOUD_REPO}" ] ; then \ - echo SKIPPING scripts/push_packagecloud.sh ; \ - else \ - echo "NOT pushing RPM to Packagecloud as this is a pre-release build" ; \ - fi + scripts/build-rpm.sh ######################################## FROM scratch AS extract -COPY --from=compile /build/pkg pkg +COPY --from=compile /home/vscode/rpmbuild/RPMS RPMS +COPY --from=compile /home/vscode/rpmbuild/SRPMS SRPMS +COPY --from=compile /build/LATEST-RPM-VER-REL LATEST-RPM-VER-REL ######################################## FROM base AS runtime -ARG CHANNEL=release +COPY --from=compile \ + /build/LATEST-RPM-VER-REL \ + /home/vscode/rpmbuild/RPMS/x86_64/fusedav-*.rpm \ + /tmp/ -COPY --from=compile /build/src/fusedav "/opt/pantheon/fusedav-${CHANNEL}/fusedav-${CHANNEL}" -COPY scripts/exec_wrapper/mount.fusedav_chan "/usr/sbin/mount.fusedav-${CHANNEL}" +# BEWARE: `.fc28` is the RPM release suffix normally added by rpmbuild. +RUN \ + LATEST=$(cat /tmp/LATEST-RPM-VER-REL) \ + && rpm -i "/tmp/fusedav-${LATEST}.fc28.x86_64.rpm" USER fusedav diff --git a/README.md b/README.md index ad0c79d..c89984e 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,101 @@ -Fusedav -======= +# Fusedav [![Unsupported](https://img.shields.io/badge/Pantheon-Unsupported-yellow?logo=pantheon&color=FFDC28)](https://pantheon.io/docs/oss-support-levels#unsupported) -Fusedav Client --------------- +## Fusedav Client This is a fuse-based DAV client with extensions for performance. This will run against any standard DAV implementation, i.e. `pywebdav` (see tests). -Installation ------------- +## Production (CI/CD) Build -1. ```git clone git://github.com/pantheon-systems/fusedav.git``` -2. ```git clean -f -x -d && ./autogen.sh && ./configure && make``` +Merging anything to the `master` branch will trigger GitHub Actions to build +a production release. -Usage ------ +The RPM(s) are published as a [Release](https://github.com/pantheon-systems/fusedav/releases). -Use the ```-V``` flag to see libraries. +Container image(s) are published as [Packages](https://github.com/pantheon-systems/fusedav/pkgs/container/fusedav). +Images are generally accessed as `ghcr.io/pantheon-systems/fusedav:0.0.0`, where +`0.0.0` is the desired version. + +### RPM Retrieval / Installation + +Note that, while the RPM version is removed from the filename entirely, the +RPM release `.fc28` suffix is retained. This is being done to allow for use +of other base images/distributions in the future. + +```sh +# Install latest release +curl -fsSL https://github.com/pantheon-systems/fusedav/releases/latest/download/fusedav.fc28.x86_64.rpm \ + -o fusedav.x86_64.rpm \ + && dnf install -y fusedav.x86_64.rpm + +# Install specific release +RELEASE_NAME=v0.0.0-branch.1 +curl -fsSL "https://github.com/pantheon-systems/fusedav/releases/download/${RELEASE_NAME}/fusedav.fc28.x86_64.rpm" \ + -o fusedav.x86_64.rpm \ + && dnf install -y fusedav.x86_64.rpm + +# Install specific release, alternate method +RELEASE_NAME=v0.0.0-branch.1 +curl -fsSL "https://api.github.com/repos/pantheon-systems/fusedav/releases/tags/${RELEASE_NAME}" \ + | jq ".assets[] | select(.name==\"fusedav.fc28.x86_64.rpm\") | .browser_download_url" \ + | xargs curl -o fusedav.x86_64.rpm -fsSL \ + && dnf install -y fusedav.x86_64.rpm +``` + +## Development Build + +### Development Image Build + +Building a local container image requires only: + +1) a local Docker (or Podman) installation, and +1) [autotag](https://github.com/pantheon-systems/autotag) in the PATH. +PATH. + +```sh +scripts/compute-version.sh | tee new-version.sh +docker build --progress plain -t fusedav . ``` + +### Development RPM Build + +Building a set of RPMs within a containerized environment requires only: + +1) a local Docker (or Podman) installation, and +1) [autotag](https://github.com/pantheon-systems/autotag) in the PATH. + +The generated RPMs will be written to the `extract` directory. + +```sh +scripts/compute-version.sh | tee new-version.sh +docker build --progress plain --target extract . --output=extract +``` + +### Development Code Build + +1. Clone the git repository. + - You may have done this already. + - `git clone git://github.com/pantheon-systems/fusedav.git` +1. Install build dependencies. + - See `BuildRequires` in [fusedav-template.spec](fusedav-template.spec) + for required Fedora Linux 28 packages. + - You may have done this already. + - ALTERNATIVELY, open this git repository in Visual Studio Code with + the [ms-vscode-remote.remote-containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) + extension active and work within the `fedora28` (default) dev + container. +1. Compile the code. + - `git clean -f -x -d && ./autogen.sh && ./configure && make` + - The executable will be written to `src/fusedav`. + +## Usage + +Use the `-V` flag to see libraries. + +```text $ src/fusedav -V fusedav version 2.0.42-bccf93b LevelDB version 1.20 @@ -28,25 +103,16 @@ libcurl/7.59.0 OpenSSL/1.1.0i zlib/1.2.11 libidn2/2.0.5 libpsl/0.20.2 (+libidn2/ FUSE library version: 2.9.7 ``` -Debug/Develop ------ -Running this docker script in debug mode will build a fedora-22 container with the local source mounted inside it suitable to build fusedav. -``` -BUILD_VERSIONS=22 BUILD_DEBUG=1 ./scripts/docker-outer.sh -``` - -libcurl and OpenSSL -------------------- +## libcurl and OpenSSL FuseDAV requires libcurl linked with OpenSSL. On Fedora versions before 27 the provided libcurl is linked against NSS and you need to provide your own libcurl linked against OpenSSL. -Contributing ------------- +## Contributing 1. Fork it. -2. Create a branch (`git checkout -b my_new_features`) -3. Commit your changes (`git commit -am "Adding a nice new feature"`) -4. Push to the branch (`git push origin my_new_feature`) -5. Open a Pull Request with relevant information +2. Create a branch (`git checkout -b my_new_features`). +3. Commit your changes (`git commit -am "Adding a nice new feature"`). +4. Push to the branch (`git push origin my_new_feature`). +5. Open a Pull Request with relevant information. diff --git a/configure.ac b/configure.ac index ee47438..7bc994c 100644 --- a/configure.ac +++ b/configure.ac @@ -19,10 +19,7 @@ AC_PREREQ([2.68]) -define([gitcommit], esyscmd([sh -c "git rev-parse --short HEAD|tr -d '\n'"]))dnl - -AC_DEFINE(GIT_COMMIT, "gitcommit", [Git Commit]) -AC_INIT([fusedav],m4_esyscmd([tr -d '\n' < VERSION])-[gitcommit],[david@davidstrauss.net]) +AC_INIT([fusedav],m4_esyscmd([tr -d '\n' < VERSION]),[david@davidstrauss.net]) AC_CONFIG_SRCDIR([src/fusedav.c]) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE([foreign 1.11 -Wall]) diff --git a/fusedav-template.spec b/fusedav-template.spec new file mode 100644 index 0000000..395b35c --- /dev/null +++ b/fusedav-template.spec @@ -0,0 +1,70 @@ +Name: fusedav +Version: RPM_VERSION +Release: RPM_RELEASE%{?dist} +License: GPLv2 +URL: https://github.com/pantheon-systems/fusedav +Vendor: Pantheon +Summary: Fusedav: Pantheon fuse-based DAV client +Source: fusedav-RPM_VERSION.tar.gz + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: curl-devel +BuildRequires: expat-devel +BuildRequires: fuse-devel +BuildRequires: gcc +BuildRequires: glib2-devel +BuildRequires: jemalloc-devel +BuildRequires: leveldb-devel +BuildRequires: make +BuildRequires: systemd-devel +BuildRequires: uriparser-devel +BuildRequires: zlib-devel + +Requires: fuse +Requires: fuse-libs +Requires: jemalloc +Requires: leveldb +Requires: uriparser + +%description +fusedav is a fuse-based DAV client with extensions for performance. + +%prep +%setup + +%build +./autogen.sh +echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT +CURL_LIBS="-lcurl" ./configure --prefix="${RPM_BUILD_ROOT}" \ + --bindir="/opt/pantheon/fusedav-release" +make + +%install +%make_install + +# HACK: rename binary +mv "${RPM_BUILD_ROOT}/opt/pantheon/fusedav-release/fusedav" \ + "${RPM_BUILD_ROOT}/opt/pantheon/fusedav-release/fusedav-release" + +mkdir -p "${RPM_BUILD_ROOT}/usr/sbin" +install -m 0755 scripts/exec_wrapper/mount.fusedav_chan \ + "${RPM_BUILD_ROOT}/usr/sbin/mount.fusedav-release" + +%check + +# test that fusedav at least runs +echo "TEST OUTPUT: fusedav -V" +set +e +"${RPM_BUILD_ROOT}/opt/pantheon/fusedav-release/fusedav-release" -V +if [ "$?" != "0" ] ; then + echo + echo "fusedav binary seems broken, aborting" + exit 1 +fi +set -e + +%files +%defattr(0644, root, root, 0755) +%attr(0755, root, root) /opt/pantheon/fusedav-release/fusedav-release +%attr(0755, root, root) /usr/sbin/mount.fusedav-release diff --git a/scripts/build-rpm.sh b/scripts/build-rpm.sh index 1c52170..3e88021 100755 --- a/scripts/build-rpm.sh +++ b/scripts/build-rpm.sh @@ -5,119 +5,55 @@ # # It should be started from the root of the repo. # -# Upon success, the fusedav RPM will be written to the pkg/28/fusedav -# directory. -# -# RPM version string creation is a bit weird. The VERSION file is expected to -# contain something like `0.0.1+3`, where 0.0.1 is the proper version and 3 -# is the build number (which should be populated from CIRCLE_BUILD_NUM -# upstream). -# -# `iteration` is the timestamp (in seconds since the epoch) followed by a -# period and the 7-character git commit hash. -# -# All together, the RPM version/iteration string ends up looking like -# `0.0.1+3-1698000000.abc1234`. -# -# Note that the RPM version and iteration strings are SEPARATE from the -# SemVer string embedded within the fusedav binary. -# set -euo pipefail -if [ "$#" -ne 1 ]; then - echo "specify a channel" +if [ ! -r new-version.sh ] ; then + echo "new-version.sh is missing, try: \"scripts/compute-version.sh | tee new-version.sh\"" exit 1 fi -if [ ! -r VERSION ] ; then - echo "VERSION file is missing; cannot continue" -fi - -# fusedav_channel may be: dev, stage, yolo, release -fusedav_channel=$1 - -# build vars from environment -fedora_release=$(rpm -q --queryformat '%{VERSION}\n' fedora-release) -name="fusedav-${fusedav_channel}" -version=$(cat VERSION) - -arch=$(uname -m) # typically x86_64 -url="https://github.com/pantheon-systems/${name}" -vendor='Pantheon' -description='Fusedav: Pantheon fuse-based DAV client' - -# Note that the ".fc28" RPM release/iteration suffix is arbitrarily -# added here. Provision should be made for using a different string -# if/when building on other distributions/versions. -if [ -n "${CIRCLE_SHA1:-}" ]; then - iteration="$(date +%s).$(echo $CIRCLE_SHA1 | cut -c -7).fc28" -else - iteration="$(date +%s).$(git rev-parse --short HEAD).fc28" -# if [ -n "$(git status --porcelain)" ] ; then -# iteration="${iteration}-dirty" -# fi -fi +eval $(cat new-version.sh) -# rpm_build_root is used by `make install` to write fusedav. -rpm_build_root="${HOME}/fusedav_build_root" +# Capture latest RPM version/release to simplify later RPM extraction. +# +# Note this does NOT include the `%{?dist}` suffix that rpmbuild appends +# to its release. +echo "${RPM_VERSION}-${RPM_RELEASE}" > LATEST-RPM-VER-REL -# install_prefix is the final home of the fusedav binary, relative to rpm_build_root. -install_prefix="opt/pantheon/${name}" +# Create VERSION for autoconf. +echo "${SEMVER}" > VERSION -# start the build -./autogen.sh -mkdir -p $rpm_build_root -CURL_LIBS="-lcurl" ./configure --prefix="${rpm_build_root}" -make -make install +mkdir -p "${HOME}/rpmbuild/SOURCES" "${HOME}/rpmbuild/SPECS" -# test that fusedav at least runs -set +e -fusedav_bin="${rpm_build_root}/bin/fusedav" -echo -echo "TEST OUTPUT: fusedav -V" -"${fusedav_bin}" -V -echo -echo "TEST OUTPUT: fusedav --help" -"${fusedav_bin}" --help -if [ "$?" != "1" ] ; then - echo - echo "fusedav binary at ${fusedav_bin} seems broken, aborting" +spec_path="${HOME}/rpmbuild/SPECS/fusedav.spec" +if [ -e $spec_path ] ; then + echo "Cowardly refusing to overwrite ${spec_path}" exit 1 fi -echo -set -e -mkdir -p "${rpm_build_root}/${install_prefix}" -mv $fusedav_bin "${rpm_build_root}/${install_prefix}" - -mkdir -p "${rpm_build_root}/usr/sbin" -install -m 0755 scripts/exec_wrapper/mount.fusedav_chan "${rpm_build_root}/usr/sbin/mount.${name}" +# build vars from environment +fedora_release=$(rpm -q --queryformat '%{VERSION}\n' fedora-release) -# fpm will not clobber, so ensure file is not present -#rpm_version=$(echo $version | sed -e 's/-/_/g') -#rpm_iteration=$(echo $iteration | sed -e 's/-/_/g') -rpm_target="${name}-${version}-${iteration}.${arch}.rpm" -rm -f $rpm_target +echo "CREATE SOURCE ARCHIVE" +tar czf "${HOME}/rpmbuild/SOURCES/fusedav-${RPM_VERSION}.tar.gz" \ + --transform "s,^,fusedav-${RPM_VERSION}/," \ + LICENSE \ + Makefile.am \ + VERSION \ + autogen.sh \ + configure.ac \ + scripts/exec_wrapper/mount.fusedav_chan \ + src/*.c \ + src/*.h \ + src/Makefile.am + +sed -e "s/RPM_VERSION/${RPM_VERSION}/" \ + -e "s/RPM_RELEASE/${RPM_RELEASE}/" \ + fusedav-template.spec \ + > $spec_path echo "BUILD RPM" -fpm -s dir -t rpm \ - --name "${name}" \ - --version "${version}" \ - --iteration "${iteration}" \ - --architecture "${arch}" \ - --url "${url}" \ - --vendor "${vendor}" \ - --description "${description}" \ - --depends uriparser \ - --depends fuse-libs \ - --depends leveldb \ - --log=info \ - --chdir=$rpm_build_root \ - $install_prefix \ - "usr/sbin/mount.${name}" - -mkdir -p "pkg/${fedora_release}/fusedav" -mv $rpm_target "pkg/${fedora_release}/fusedav/" -echo "${rpm_target}" > LATEST_RPM -echo "fusedav RPM written to pkg/${fedora_release}/fusedav/${rpm_target}" +echo "SEMVER=${SEMVER}" +echo "RPM_VERSION=${RPM_VERSION}" +echo "RPM_RELEASE=${RPM_RELEASE}" +rpmbuild -ba $spec_path diff --git a/scripts/compute-version.sh b/scripts/compute-version.sh new file mode 100755 index 0000000..a9ab266 --- /dev/null +++ b/scripts/compute-version.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# +# compute-version.sh generates version strings and image tags. +# +# See end of this file for format specifics, including examples. +# +# When run from GitHub Actions, the GITHUB_* variables will be used. +# +# When run locally (perhaps within a dev container), the GITHUB_* variables +# are not available, but `.git/` should exist so we can get the necessary +# information ourselves. +# +set -eou pipefail + +if [ -n "${REGISTRY:-}" ] ; then + IMAGE_REPOSITORY="${REGISTRY}/${IMAGE_NAME:-fusedav}" +else + # if no REGISTRY, build image for local use + IMAGE_REPOSITORY="${IMAGE_NAME:-fusedav}" +fi + +# Ensure we have autotag. +if ! command -v autotag > /dev/null ; then + echo "autotag is not available; aborting" > /dev/stderr + exit 1 +fi + +# Ensure we have build_num. +build_num=${GITHUB_RUN_NUMBER:-} +if [ -z "$build_num" ] ; then + echo "GITHUB_RUN_NUMBER not set, assuming '1'" > /dev/stderr + build_num=1 +fi + +# Ensure we have branch name. +raw_branch=${GITHUB_REF_NAME:-} +if [ -z "${raw_branch}" ] ; then + echo "GITHUB_REF_NAME not set, extracting from git directly" > /dev/stderr + raw_branch=$(git rev-parse --abbrev-ref HEAD) +fi + +# Sanitize branch name. +# +# Yes, this is overly restrictive. The git rules for naming branches are +# quite complex. +# https://git-scm.com/docs/git-check-ref-format +safe_branch=$(sed -e 's/[^0-9A-Za-z-]/-/g' <<<$raw_branch) + +# Ensure we have git commit hash. +if [ -n "${GITHUB_SHA:-}" ]; then + git_commit="$(echo $GITHUB_SHA | cut -c -7)" +else + echo "GITHUB_SHA not set, extracting from git directly" > /dev/stderr + git_commit="$(git rev-parse --short HEAD)" + if [ -n "$(git status --porcelain)" ] ; then + git_commit="${git_commit}-dirty" + fi +fi + +# Compute new SemVer string and image tag(s). +# +# $raw_branch is being directly appended in some places to avoid shell +# interpolation issues. +# (Example: Consider a branch name which contains a single quote, double +# quote, and/or semicolon.) +IMAGE_TAGS=( "${IMAGE_REPOSITORY}:${build_num}-"$safe_branch ) +if [ "${safe_branch}" == "main" -o "${safe_branch}" == "master" ] ; then + full_semver="$(autotag -n -m "${build_num}.${git_commit}" -b $raw_branch)" + + # Originally, the actual `vN.N.N` git release tag was created by this + # invocation of autotag. However, `gh` appears to do that on its own + # when creating a release, so we now include `-n` here to suppress + # the generation of a potentially confusing/conflicting git tag. + bare_ver="$(autotag -n -b $raw_branch)" + + GITHUB_RELEASE_NAME="v${bare_ver}" + rpm_ver=$bare_ver + + # When main/master, also create SemVer tag. + IMAGE_TAGS+=( "${IMAGE_REPOSITORY}:${bare_ver}" ) +else + full_semver="$(autotag -n -p "${safe_branch}.${build_num}" -m $git_commit -b $raw_branch)" + bare_ver=$(autotag -n -b $raw_branch) + GITHUB_RELEASE_NAME="v$(autotag -n -p "${safe_branch}.${build_num}" -b $raw_branch)" + rpm_ver="${bare_ver}~${safe_branch}" +fi + +# In the examples below: +# - latest tag on the git repo is v0.0.1. +# - GITHUB_REF_NAME is fix-bug. +# - GITHUB_RUN_NUMBER is 3. +# - GITHUB_SHA is abc1234fffff. + +# iff main/master: v0.0.2 +# else: v0.0.2-fix-bug.3 +echo "export GITHUB_RELEASE_NAME=${GITHUB_RELEASE_NAME}" + +# image tag(s) to be pushed to registry/repository +# - always: ...:3-fix-bug +# - iff main/master: also ...:0.0.2 +echo "export IMAGE_TAGS=( ${IMAGE_TAGS[@]} )" # keep args separate + +# iff main/master: 0.0.2+3.abc1234 +# else: 0.0.2-fix-bug.3+abc1234 +echo "export SEMVER=${full_semver}" + +# iff main/master: RPM_VERSION=0.0.2 RPM_RELEASE=1 +# else: RPM_VERSION=0.0.2~fix_bug RPM_RELEASE=1 +# +# Originally, we set RPM_RELEASE to $build_num; it is unclear if this is +# useful or merely distracting. +echo "export RPM_VERSION=${rpm_ver//-/_}" +echo "export RPM_RELEASE=1" diff --git a/scripts/upload-gh-assets.sh b/scripts/upload-gh-assets.sh new file mode 100644 index 0000000..6bdb278 --- /dev/null +++ b/scripts/upload-gh-assets.sh @@ -0,0 +1,25 @@ +#!/bin/sh +set -eou pipefail + +# upload-gh-assets.sh is meant to be called automatically by Github Actions. +# Before calling this script, new-version.sh MUST already be loaded into our +# env. + +T=$(mktemp -d) + +# Upload artifacts with static/fixed names for ease of consumption. +for F in extract/RPMS/x86_64/*.rpm ; do + n=$(echo $F | sed -e "s,.*/\([0-9A-Za-z-]*\)-${RPM_VERSION}-${RPM_RELEASE}\(.[0-9A-Za-z]*.x86_64.rpm\),\1\2,") + echo "include ${F} as ${n}" + cp $F "${T}/${n}" +done +for F in extract/SRPMS/*.rpm ; do + n=$(echo $F | sed -e "s,.*/\([0-9A-Za-z-]*\)-${RPM_VERSION}-${RPM_RELEASE}\(.[0-9A-Za-z]*.src.rpm\),\1\2,") + echo "include ${F} as ${n}" + cp $F "${T}/${n}" +done + +gh release upload $GITHUB_RELEASE_NAME ${T}/*.rpm +echo Done uploading release artifacts + +rm -rf $T