From 7c7964bb3bde9d49d2bc9c887d09c017da0c79a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl=20H=C3=B6rberg?= Date: Sat, 26 Nov 2022 10:22:17 +0100 Subject: [PATCH] Build RPM packages --- .github/workflows/rpm.yml | 100 ++++++++++++++++++++++++++++++++++++++ Dockerfile.rpm | 29 +++++++++++ Makefile | 62 +++++++++++++++++++++++ amqproxy.spec | 46 ++++++++++++++++++ 4 files changed, 237 insertions(+) create mode 100644 .github/workflows/rpm.yml create mode 100644 Dockerfile.rpm create mode 100644 Makefile create mode 100644 amqproxy.spec diff --git a/.github/workflows/rpm.yml b/.github/workflows/rpm.yml new file mode 100644 index 0000000..9f103e5 --- /dev/null +++ b/.github/workflows/rpm.yml @@ -0,0 +1,100 @@ +name: RPM +on: + pull_request: + paths: + - .github/workflows/rpm.yml + - Dockerfile.rpm + - amqproxy.spec + - shard.lock + - src/** + push: + branches: + - main + tags: + - v* + paths: + - .github/workflows/rpm.yml + - Dockerfile.rpm + - amqproxy.spec + - shard.lock + - src/** +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + build_rpm: + name: Build RPM + strategy: + matrix: + os: ['fedora-37'] + runs-on: ubuntu-latest + concurrency: ${{ github.workflow }}-depot + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Generate version string + run: | + last_tag=$(git describe --tags --abbrev=0) + version=$(cut -d- -f1 <<< ${last_tag:1}) + pre_release=$(cut -d- -f2 <<< $last_tag) + if [ -n "$pre_release" ] + then version=$version~${pre_release//./} + fi + git_describe=$(git describe --tags) + post_release=${git_describe//$last_tag/} + post_release=${post_release:1} + post_release=${post_release//-/.} + if [ -n "$post_release" ] + then version=$version^${post_release} + fi + echo "version=$version" >> $GITHUB_ENV + + # The depot CLI still needs to be available in your workflow + - uses: depot/setup-action@v1 + - uses: depot/build-push-action@v1 + with: + file: Dockerfile.rpm + platforms: linux/amd64,linux/arm64 + build-args: | + build_image=84codes/crystal:1.6.2-${{ matrix.os }} + version=${{ env.version }} + outputs: RPMS + + - uses: actions/upload-artifact@v3 + name: Upload artifact + with: + name: rpm-packages + path: RPMS + + - name: Upload to Packagecloud + run: | + set -eux + curl -fsSO -u "${{ secrets.packagecloud_token }}:" https://packagecloud.io/api/v1/distributions.json + ID=$(echo "${{ matrix.os }}" | cut -d- -f1) + VERSION_ID=$(echo "${{ matrix.os }}" | cut -d- -f2) + DIST_ID=$(jq ".rpm[] | select(.index_name == \"${ID}\").versions[] | select(.index_name == \"${VERSION_ID}\").id" distributions.json) + for PKG_FILE in $(find RPMS -name "*.rpm" | sort -u -t/ -k3) + do curl -fsS -u "${{ secrets.packagecloud_token }}:" -XPOST \ + -F "package[distro_version_id]=${DIST_ID}" \ + -F "package[package_file]=@${PKG_FILE}" \ + https://packagecloud.io/api/v1/repos/${{ github.repository }}/packages.json + done + if: startsWith(github.ref, 'refs/tags/v') + + - name: Upload to Packagecloud head repo + run: | + set -eux + curl -fsSO -u "${{ secrets.packagecloud_token }}:" https://packagecloud.io/api/v1/distributions.json + ID=$(echo "${{ matrix.os }}" | cut -d- -f1) + VERSION_ID=$(echo "${{ matrix.os }}" | cut -d- -f2) + DIST_ID=$(jq ".rpm[] | select(.index_name == \"${ID}\").versions[] | select(.index_name == \"${VERSION_ID}\").id" distributions.json) + for PKG_FILE in $(find RPMS -name "*.rpm" | sort -u -t/ -k3) + do curl -fsS -u "${{ secrets.packagecloud_token }}:" -XPOST \ + -F "package[distro_version_id]=${DIST_ID}" \ + -F "package[package_file]=@${PKG_FILE}" \ + https://packagecloud.io/api/v1/repos/${{ github.repository }}-head/packages.json + done + if: github.event_name != 'pull_request' diff --git a/Dockerfile.rpm b/Dockerfile.rpm new file mode 100644 index 0000000..0db2a48 --- /dev/null +++ b/Dockerfile.rpm @@ -0,0 +1,29 @@ +ARG build_image=84codes/crystal:latest-fedora-37 + +FROM $build_image AS builder +RUN dnf install -y --nodocs --setopt=install_weak_deps=False --repo=fedora,updates \ + rpmdevtools rpmlint systemd-rpm-macros npm make help2man +RUN rpmdev-setuptree +COPY amqproxy.spec /root/rpmbuild/SPECS/ +ARG version +RUN sed -i -E "s/^(Version:).*/\1 $version/" /root/rpmbuild/SPECS/amqproxy.spec +RUN rpmlint /root/rpmbuild/SPECS/amqproxy.spec +WORKDIR /usr/src/amqproxy +COPY Makefile README.md LICENSE CHANGELOG.md shard.yml shard.lock ./ +COPY extras/ extras/ +COPY config/ config/ +COPY src/ src/ +RUN sed -i -E "s/(VERSION =) .*/\1 \"$version\"/" src/amqproxy/version.cr +RUN tar -czf /root/rpmbuild/SOURCES/amqproxy.tar.gz -C /usr/src amqproxy +ARG MAKEFLAGS +RUN rpmbuild -ba /root/rpmbuild/SPECS/amqproxy.spec +RUN rpmlint /root/rpmbuild/RPMS/* || true + +FROM fedora:37 AS test +COPY --from=builder /root/rpmbuild/RPMS /tmp/RPMS +RUN find /tmp/RPMS -type f -exec dnf install -y {} \; +RUN amqproxy --version + +# Copy the deb package to a scratch image, that then can be exported +FROM scratch +COPY --from=builder /root/rpmbuild/RPMS /root/rpmbuild/SRPMS . diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4f383ed --- /dev/null +++ b/Makefile @@ -0,0 +1,62 @@ +SOURCES := $(shell find src/amqproxy -name '*.cr' 2> /dev/null) +CRYSTAL_FLAGS := --release +override CRYSTAL_FLAGS += --debug --error-on-warnings --link-flags=-pie + +.PHONY: all +all: bin/amqproxy + +bin/%: src/%.cr $(SOURCES) lib | bin + crystal build $< -o $(basename $@) $(CRYSTAL_FLAGS) + +lib: shard.yml shard.lock + shards install --production + +bin man1: + mkdir -p $@ + +man1/amqproxy.1: bin/amqproxy | man1 + help2man -Nn "connection pool for AMQP connections" $< -o $@ + +.PHONY: deps +deps: lib + +.PHONY: lint +lint: lib + lib/ameba/bin/ameba src/ + +.PHONY: test +test: lib + crystal spec + +.PHONY: format +format: + crystal tool format --check + +DESTDIR := +PREFIX := /usr +BINDIR := $(PREFIX)/bin +DOCDIR := $(PREFIX)/share/doc +MANDIR := $(PREFIX)/share/man +SYSCONFDIR := /etc +UNITDIR := /lib/systemd/system + +.PHONY: install +install: bin/amqproxy man1/amqproxy.1 config/example.ini extras/amqproxy.service README.md CHANGELOG.md + install -D -m 0755 -t $(DESTDIR)$(BINDIR) bin/amqproxy + install -D -m 0644 -t $(DESTDIR)$(MANDIR)/man1 man1/amqproxy.1 + install -D -m 0644 -t $(DESTDIR)$(UNITDIR) extras/amqproxy.service + install -D -m 0644 -t $(DESTDIR)$(DOCDIR)/amqproxy README.md + install -D -m 0644 config/example.ini $(DESTDIR)$(SYSCONFDIR)/amqproxy.ini + install -D -m 0644 CHANGELOG.md $(DESTDIR)$(DOCDIR)/amqproxy/changelog + +.PHONY: uninstall +uninstall: + $(RM) $(DESTDIR)$(BINDIR)/amqproxy + $(RM) $(DESTDIR)$(MANDIR)/man1/amqproxy.1 + $(RM) $(DESTDIR)$(SYSCONFDIR)/amqproxy/amqproxy.ini + $(RM) $(DESTDIR)$(UNITDIR)/amqproxy.service + $(RM) $(DESTDIR)$(DOCDIR)/{README.md,changelog} + +.PHONY: clean +clean: + rm -rf bin diff --git a/amqproxy.spec b/amqproxy.spec new file mode 100644 index 0000000..14b7d12 --- /dev/null +++ b/amqproxy.spec @@ -0,0 +1,46 @@ +Name: amqproxy +Summary: Connection and channel pool for AMQP connections +Version: 1.0.0 +Release: 1%{?dist} + +License: ASL 2.0 +BuildRequires: systemd-rpm-macros crystal help2man +Requires(pre): shadow-utils +URL: https://github.com/cloudamqp/amqproxy +Source: amqproxy.tar.gz + +%description +An AMQP proxy that reuses upstream connections and channels + +%prep +%setup -qn amqproxy + +%check + +%build +make + +%install +make install DESTDIR=%{buildroot} UNITDIR=%{_unitdir} + +%post +%systemd_post %{name}.service + +%preun +%systemd_preun %{name}.service + +%postun +%systemd_postun_with_restart %{name}.service + +%files +%{_bindir}/%{name} +%{_unitdir}/%{name}.service +%{_mandir}/man1/* +%config(noreplace) %{_sysconfdir}/%{name}.ini +%doc README.md +%doc %{_docdir}/%{name}/changelog +%license LICENSE + +%changelog +* Thu Nov 24 2022 CloudAMQP +- Initial version of the package