diff --git a/maint/Makefile.am b/maint/Makefile.am index a08de40c9a..788dd46d62 100644 --- a/maint/Makefile.am +++ b/maint/Makefile.am @@ -1,92 +1,107 @@ # # Copyright 2019-2022 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # Define release-related variables include $(abs_srcdir)/../mk/release.mk noinst_SCRIPTS = bumplibs EXTRA_DIST = README # # Change log generation # # Count changes in these directories CHANGELOG_DIRS = ../include ../lib ../daemons ../tools ../xml +.PHONY: require_last_release +require_last_release: + @if [ -z "$(CHECKOUT)" ]; then \ + echo "This target must be run from a git checkout"; \ + exit 1; \ + elif ! git rev-parse $(LAST_RELEASE) >/dev/null 2>&1; then \ + echo "LAST_RELEASE must be set to a valid git tag"; \ + exit 1; \ + fi + .PHONY: summary -summary: - @printf "\n* `date +"%a %b %d %Y"` `git config user.name` <`git config user.email`> $(NEXT_RELEASE)" - @printf "\n- Changesets: `git log --pretty=oneline --no-merges $(LAST_RELEASE)..HEAD | wc -l`" - @printf "\n- Diff:`git diff $(LAST_RELEASE)..HEAD --shortstat $(CHANGELOG_DIRS)`\n" +summary: require_last_release + @printf "* %s %s <%s> %s\n" "$$(date +'%a %b %d %Y')" \ + "$$(git config user.name)" "$$(git config user.email)" \ + "$(NEXT_RELEASE)" + @printf "\055 %d commits with%s\n" \ + "$$(git log --pretty=oneline --no-merges \ + $(LAST_RELEASE)..HEAD | wc -l)" \ + "$$(git diff $(LAST_RELEASE)..HEAD --shortstat \ + $(CHANGELOG_DIRS))" .PHONY: changes changes: summary @printf "\n- Features added since $(LAST_RELEASE)\n" - @git log --pretty=format:'%s' --no-merges --abbrev-commit $(LAST_RELEASE)..HEAD \ + @git log --pretty=format:'%s' --no-merges \ + --abbrev-commit $(LAST_RELEASE)..HEAD \ | sed -n -e 's/^ *Feature: */ + /p' | sort -uf @printf "\n- Fixes since $(LAST_RELEASE)\n" - @git log --pretty=format:'%s' --no-merges --abbrev-commit $(LAST_RELEASE)..HEAD \ - | sed -n -e 's/^ *\(Fix\|High\|Bug\): */ + /p' | sed \ - -e 's@\(cib\|pacemaker-based\|based\):@CIB:@' \ - -e 's@\(crmd\|pacemaker-controld\|controld\):@controller:@' \ - -e 's@\(lrmd\|pacemaker-execd\|execd\):@executor:@' \ - -e 's@\(Fencing\|stonithd\|stonith\|pacemaker-fenced\|fenced\):@fencing:@' \ - -e 's@\(PE\|pengine\|pacemaker-schedulerd\|schedulerd\):@scheduler:@' \ + @git log --pretty=format:'%s' --no-merges \ + --abbrev-commit $(LAST_RELEASE)..HEAD \ + | sed -n -e 's/^ *\(Fix\|High\|Bug\): */ + /p' | sed \ + -e 's/\(cib\|pacemaker-based\|based\):/CIB:/' \ + -e 's/\(lrmd\|pacemaker-execd\|execd\):/executor:/' \ + -e 's/\(crmd\|pacemaker-controld\|controld\):/controller:/' \ + -e 's/\(Fencing\|stonithd?\|pacemaker-fenced\|fenced\):/fencing:/' \ + -e 's/\(PE\|pengine\|pacemaker-schedulerd\|schedulerd\):/scheduler:/' \ | sort -uf @printf "\n- Public API changes since $(LAST_RELEASE)\n" - @git log --pretty=format:'%s' --no-merges --abbrev-commit $(LAST_RELEASE)..HEAD \ + @git log --pretty=format:'%s' --no-merges \ + --abbrev-commit $(LAST_RELEASE)..HEAD \ | sed -n -e 's/^ *API: */ + /p' | sort -uf -.PHONY: rc-changes -rc-changes: - @$(MAKE) $(AM_MAKEFLAGS) NEXT_RELEASE=$(shell echo $(LAST_RC) | sed s:-rc.*::) LAST_RELEASE=$(LAST_RC) changes +.PHONY: changelog +changelog: require_last_release + @printf "%s\n\n%s\n" \ + "$$($(MAKE) $(AM_MAKEFLAGS) changes \ + | grep -v 'make\(\[[0-9]*\]\)\?:')" \ + "$$(cat ../ChangeLog)" > ../ChangeLog .PHONY: authors -authors: +authors: require_last_release git log $(LAST_RELEASE)..$(COMMIT) --format='%an' | sort -u -.PHONY: changelog -changelog: - @$(MAKE) $(AM_MAKEFLAGS) changes > ../ChangeLog - @printf "\n">> ../ChangeLog - git show $(LAST_RELEASE):ChangeLog >> ../ChangeLog - # # gnulib updates # # See https://www.gnu.org/software/gnulib/manual/html_node/ # # V3 = scandir unsetenv alphasort xalloc # V2 = setenv strerror strchrnul strndup GNU_MODS = crypto/md5-buffer # stdint appears to be surrogate only for C99-lacking environments GNU_MODS_AVOID = stdint .PHONY: gnulib-update gnulib-update: @echo 'Newer versions of gnulib require automake 1.14' @echo 'Pacemaker cannot update until minimum supported automake is 1.14' @exit 1 if test -e gnulib; then \ cd gnulib && git pull; \ else \ git clone https://git.savannah.gnu.org/git/gnulib.git gnulib \ && cd gnulib && git config pull.rebase false; \ fi cd $(top_srcdir) && maint/gnulib/gnulib-tool --source-base=lib/gnu \ --lgpl=2 --no-vc-files --no-conditional-dependencies --libtool \ $(GNU_MODS_AVOID:%=--avoid %) --import $(GNU_MODS) sed -i -e "s/bundled(gnulib).*/bundled(gnulib) = `date +'%Y%m%d'`/" \ ../rpm/pacemaker.spec.in sed -i -e "s/_GL_EXTERN_INLINE/_GL_INLINE/" \ -e "s#left_over -= 64;#left_over \&= 63; /* helps static analysis */#" \ -e "s#&ctx->buffer\[16\]#\&(((char *) ctx->buffer)[64]) /* helps static analysis */#" \ ../lib/gnu/md5.c diff --git a/mk/release.mk b/mk/release.mk index 9bf9651504..7d7259cbaf 100644 --- a/mk/release.mk +++ b/mk/release.mk @@ -1,87 +1,87 @@ # # Copyright 2008-2022 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # Define variables related to release version and such COMMIT ?= HEAD # TAG defaults to DIST when in a source distribution instead of a git checkout, # the tag name if COMMIT is tagged, and the full commit ID otherwise. TAG ?= $(shell \ T=$$(git describe --tags --exact-match '$(COMMIT)' 2>/dev/null); \ [ -n "$${T}" ] && echo "$${T}" \ || git log --pretty=format:%H -n 1 '$(COMMIT)' 2>/dev/null \ || echo DIST) # If DIRTY=anything is passed to make, generated versions will end in ".mod" # as long as there are uncommitted changes and COMMIT is not changed from the # default. DIRTY_EXT = $(shell [ -n "$(DIRTY)" ] \ && [ "$(COMMIT)" == "HEAD" ] \ && ! git diff-index --quiet HEAD -- 2>/dev/null \ && echo .mod) # These can be used in case statements to avoid make interpreting parentheses lparen = ( rparen = ) -# git tag of highest-versioned release candidate (such as "Pacemaker-2.1.5-rc2") -# or empty if not in git checkout -LAST_RC ?= $(shell git tag -l 2>/dev/null \ - | sed -n -e 's/^\(Pacemaker-[0-9.]*-rc[0-9]*\)$$/\1/p' \ - | sort -Vr | head -n 1) - -# true if in a git checkout -CHECKOUT = $(shell git rev-parse --git-dir >/dev/null 2>/dev/null \ - && echo true) +# This will be empty if not in a git checkout +CHECKOUT = $(shell git rev-parse --git-dir 2>/dev/null) # VERSION is set by configure, but we allow some make targets to be run without # running configure first, so set a reasonable default in that case. VERSION ?= $(shell if [ -z "$(CHECKOUT)" ]; then \ echo 0.0.0; \ else \ git tag -l \ | sed -n -e 's/^\(Pacemaker-[0-9.]*\)$$/\1/p' \ | sort -Vr | head -n 1; \ fi) # What the git tag would be for configured VERSION (such as "Pacemaker-2.1.5") LAST_RELEASE ?= Pacemaker-$(VERSION) -# What the git tag would be for configured VERSION with minor-minor version bump -# (such as "Pacemaker-2.1.6"; this should be manually overriden when bumping +# What the git tag would be for the release after the configured VERSION +# (LAST_RELEASE stripped of its -rc* suffix if present, or with minor-minor +# version bumped if not; this should be manually overriden when bumping # the major or minor version) -NEXT_RELEASE ?= $(shell echo $(LAST_RELEASE) \ - | awk -F. '/[0-9]+\./{$$3+=1;OFS=".";print $$1,$$2,$$3}') +NEXT_RELEASE ?= $(shell case "$(LAST_RELEASE)" in \ + *-rc*$(rparen) \ + echo $(LAST_RELEASE) | sed s:-rc.*:: ;; \ + *$(rparen) \ + echo $(LAST_RELEASE) | awk -F. \ + '/[0-9]+\./{$$3+=1;OFS=".";print $$1,$$2,$$3}' \ + ;; \ + esac) # We have two make targets for creating distributions: # # - "make dist" is automake's native functionality, based on the various # dist/nodist make variables; it always uses the current sources # # - "make export" is a custom target based on "git archive" and relevant # entries from .gitattributes; it defaults to current sources but can use any # git tag # # Both targets use the same name for the result, though they generate different # contents. # # The directory is named pacemaker- when in a source distribution # instead of a git checkout, pacemaker- for tagged # commits, and pacemaker- otherwise. top_distdir = $(PACKAGE)-$(shell \ case $(TAG) in \ DIST$(rparen) \ [ -n "$(VERSION)" ] && echo "$(VERSION)" \ || echo DIST;; \ Pacemaker-*$(rparen) \ echo '$(TAG)' | cut -c11-;; \ *$(rparen) \ git log --pretty=format:%h -n 1 '$(TAG)';; \ esac)$(DIRTY_EXT) diff --git a/rpm/Makefile.am b/rpm/Makefile.am index 9622e82cdd..c7975e4c81 100644 --- a/rpm/Makefile.am +++ b/rpm/Makefile.am @@ -1,281 +1,282 @@ # # Copyright 2003-2022 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # We want to support the use case where this file is fed straight to make # without running automake first, so define defaults for any automake variables # used in this file. top_srcdir ?= .. abs_srcdir ?= $(shell pwd) abs_builddir ?= $(abs_srcdir) MAKE ?= make PACKAGE ?= pacemaker AM_V_at ?= @ MKDIR_P ?= mkdir -p include $(top_srcdir)/mk/common.mk include $(top_srcdir)/mk/release.mk EXTRA_DIST = pacemaker.spec.in \ rpmlintrc # Where to put RPM artifacts; possible values: # # - subtree (default): RPM sources (i.e. TARFILE) in top-level build directory, # everything else in dedicated "rpm" subdirectory of build tree # # - toplevel (deprecated): RPM sources, spec, and source rpm in top-level build # directory, everything else uses the usual rpmbuild defaults # # - anything else: The value will be treated as a directory path to be used for # all RPM artifacts. WARNING: The entire directory will get removed with # "make clean" or "make rpm-clean". # RPMDEST ?= subtree RPM_SPEC_DIR_subtree = $(abs_builddir)/SPECS RPM_SRCRPM_DIR_subtree = $(abs_builddir)/SRPMS RPM_OPTS_subtree = --define "_sourcedir $(abs_builddir)/.." \ --define "_topdir $(abs_builddir)" RPM_CLEAN_subtree = "$(abs_builddir)/BUILD" \ "$(abs_builddir)/BUILDROOT" \ "$(abs_builddir)/RPMS" \ "$(abs_builddir)/SPECS" \ "$(abs_builddir)/SRPMS" RPM_SPEC_DIR_toplevel = $(abs_builddir)/.. RPM_SRCRPM_DIR_toplevel = $(abs_builddir)/.. RPM_OPTS_toplevel = --define "_sourcedir $(abs_builddir)/.." \ --define "_specdir $(RPM_SPEC_DIR_toplevel)" \ --define "_srcrpmdir $(RPM_SRCRPM_DIR_toplevel)" RPM_CLEAN_toplevel = RPM_SPEC_DIR_other = $(RPMDEST)/SPECS RPM_SRCRPM_DIR_other = $(RPMDEST)/SRPMS RPM_OPTS_other = --define "_sourcedir $(abs_builddir)/.." \ --define "_topdir $(RPMDEST)" RPM_CLEAN_other = "$(RPMDEST)" RPMTYPE = $(shell case "$(RPMDEST)" in \ toplevel$(rparen) echo toplevel ;; \ subtree$(rparen) echo subtree ;; \ *$(rparen) echo other ;; \ esac) RPM_SPEC_DIR = $(RPM_SPEC_DIR_$(RPMTYPE)) RPM_SRCRPM_DIR = $(RPM_SRCRPM_DIR_$(RPMTYPE)) RPM_OPTS = $(RPM_OPTS_$(RPMTYPE)) RPM_CLEAN = $(RPM_CLEAN_$(RPMTYPE)) WITH ?= --without doc # If $(BUILD_COUNTER) is an existing file, its contents will be used as the # spec version in built RPMs, unless $(SPECVERSION) is set to override it, # and the next increment will be written back to the file after building. BUILD_COUNTER ?= $(shell test -e build.counter && echo build.counter || echo ../build.counter) LAST_COUNT = $(shell test -e "$(BUILD_COUNTER)" && cat "$(BUILD_COUNTER)" || echo 0) COUNT = $(shell expr 1 + $(LAST_COUNT)) SPECVERSION ?= $(COUNT) # SPEC_COMMIT is identical to TAG for DIST and tagged releases, otherwise it is # the short commit ID (which must be used in order for "make export" to use the # same archive name as "make dist") SPEC_COMMIT ?= $(shell \ case $(TAG) in \ Pacemaker-*|DIST$(rparen) \ echo '$(TAG)' ;; \ *$(rparen) \ git log --pretty=format:%h -n 1 '$(TAG)';; \ esac)$(DIRTY_EXT) SPEC_ABBREV = $(shell printf %s '$(SPEC_COMMIT)' | wc -c) SPEC_RELEASE = $(shell case "$(WITH)" in \ *pre_release*$(rparen) \ [ "$(LAST_RELEASE)" = "$(TAG)" ] \ && echo "$(LAST_RELEASE)" \ || echo "$(NEXT_RELEASE)" ;; \ *$(rparen) \ echo "$(LAST_RELEASE)" ;; \ esac) SPEC_RELEASE_NO = $(shell echo $(SPEC_RELEASE) | sed -e s:Pacemaker-:: -e s:-.*::) MOCK_DIR = $(abs_builddir)/mock MOCK_OPTIONS ?= --resultdir="$(MOCK_DIR)" --no-cleanup-after F ?= $(shell test ! -e /etc/fedora-release && echo 0; test -e /etc/fedora-release && rpm --eval %{fedora}) ARCH ?= $(shell test ! -e /etc/fedora-release && uname -m; test -e /etc/fedora-release && rpm --eval %{_arch}) MOCK_CFG ?= $(shell test -e /etc/fedora-release && echo fedora-$(F)-$(ARCH)) distdir = $(top_distdir)/rpm TARFILE = $(abs_builddir)/../$(top_distdir).tar.gz # Create a source distribution based on a git archive. (If we aren't in a git # checkout, do a make dist instead.) export: cd $(abs_srcdir)/..; \ if [ -z "$(CHECKOUT)" ] && [ -f "$(TARFILE)" ]; then \ echo "`date`: Using existing tarball: $(TARFILE)"; \ elif [ -z "$(CHECKOUT)" ]; then \ $(MAKE) $(AM_MAKEFLAGS) dist; \ echo "`date`: Rebuilt tarball: $(TARFILE)"; \ elif [ -n "$(DIRTY_EXT)" ]; then \ git commit -m "DO-NOT-PUSH" -a; \ git archive --prefix=$(top_distdir)/ -o "$(TARFILE)" HEAD^{tree}; \ git reset --mixed HEAD^; \ echo "`date`: Rebuilt $(TARFILE)"; \ elif [ -f "$(TARFILE)" ]; then \ echo "`date`: Using existing tarball: $(TARFILE)"; \ else \ git archive --prefix=$(top_distdir)/ -o "$(TARFILE)" $(TAG)^{tree}; \ echo "`date`: Rebuilt $(TARFILE)"; \ fi # Depend on spec-clean so the spec gets rebuilt every time $(RPM_SPEC_DIR)/$(PACKAGE).spec: spec-clean pacemaker.spec.in $(AM_V_at)$(MKDIR_P) "$(RPM_SPEC_DIR)" $(AM_V_GEN)if [ x"`git ls-files -m pacemaker.spec.in 2>/dev/null`" != x ]; then \ cat "$(abs_srcdir)/pacemaker.spec.in"; \ elif git cat-file -e $(TAG):rpm/pacemaker.spec.in 2>/dev/null; then \ git show $(TAG):rpm/pacemaker.spec.in; \ elif git cat-file -e $(TAG):pacemaker.spec.in 2>/dev/null; then \ git show $(TAG):pacemaker.spec.in; \ else \ cat "$(abs_srcdir)/pacemaker.spec.in"; \ fi | sed \ -e 's/^\(%global pcmkversion \).*/\1$(SPEC_RELEASE_NO)/' \ -e 's/^\(%global specversion \).*/\1$(SPECVERSION)/' \ -e 's/^\(%global commit \).*/\1$(SPEC_COMMIT)/' \ -e 's/^\(%global commit_abbrev \).*/\1$(SPEC_ABBREV)/' \ -e "s/PACKAGE_DATE/$$(date +'%a %b %d %Y')/" \ -e 's/PACKAGE_VERSION/$(SPEC_RELEASE_NO)-$(SPECVERSION)/' \ > "$@" .PHONY: spec $(PACKAGE).spec spec $(PACKAGE).spec: $(RPM_SPEC_DIR)/$(PACKAGE).spec spec-clean: -rm -f "$(RPM_SPEC_DIR)/$(PACKAGE).spec" .PHONY: srpm srpm: export srpm-clean $(RPM_SPEC_DIR)/$(PACKAGE).spec if [ -e "$(BUILD_COUNTER)" ]; then \ echo $(COUNT) > "$(BUILD_COUNTER)"; \ fi rpmbuild -bs $(RPM_OPTS) $(WITH) "$(RPM_SPEC_DIR)/$(PACKAGE).spec" .PHONY: srpm-clean srpm-clean: -rm -f "$(RPM_SRCRPM_DIR)"/*.src.rpm # e.g. make WITH="--with pre_release" rpm .PHONY: rpm rpm: srpm @echo To create custom builds, edit the flags and options in $(PACKAGE).spec first rpmbuild $(RPM_OPTS) $(WITH) --rebuild "$(RPM_SRCRPM_DIR)"/*.src.rpm .PHONY: rpm-clean rpm-clean: spec-clean srpm-clean -if [ -n "$(RPM_CLEAN)" ]; then rm -rf $(RPM_CLEAN); fi .PHONY: rpmlint rpmlint: $(RPM_SPEC_DIR)/$(PACKAGE).spec rpmlint -f rpmlintrc "$<" .PHONY: rpm-dep rpm-dep: $(RPM_SPEC_DIR)/$(PACKAGE).spec sudo yum-builddep "$(RPM_SPEC_DIR)/$(PACKAGE).spec" .PHONY: release release: $(MAKE) $(AM_MAKEFLAGS) TAG=$(LAST_RELEASE) rpm +# Build the highest-versioned rc tag .PHONY: rc rc: - if [ -n "$(LAST_RC)" ]; then \ - @echo 'rc can only be used in git checkout'; \ - false; \ - else \ - $(MAKE) $(AM_MAKEFLAGS) TAG=$(LAST_RC) rpm; \ + @if [ -z "$(CHECKOUT)" ]; then \ + echo 'This target must be run from a git checkout'; \ + exit 1; \ fi + $(MAKE) $(AM_MAKEFLAGS) TAG="$$(git tag -l 2>/dev/null \ + | sed -n -e 's/^\(Pacemaker-[0-9.]*-rc[0-9]*\)$$/\1/p' \ + | sort -Vr | head -n 1)" rpm .PHONY: chroot chroot: mock-$(MOCK_CFG) mock-install-$(MOCK_CFG) mock-sh-$(MOCK_CFG) @echo Done .PHONY: mock-next mock-next: $(MAKE) $(AM_MAKEFLAGS) F=$(shell expr 1 + $(F)) mock .PHONY: mock-rawhide mock-rawhide: $(MAKE) $(AM_MAKEFLAGS) F=rawhide mock mock-install-%: @echo "Installing packages" mock --root=$* $(MOCK_OPTIONS) --install "$(MOCK_DIR)"/*.rpm \ vi sudo valgrind lcov gdb fence-agents psmisc .PHONY: mock-install mock-install: mock-install-$(MOCK_CFG) @echo Done .PHONY: mock-sh mock-sh: mock-sh-$(MOCK_CFG) @echo Done mock-sh-%: @echo Connecting mock --root=$* $(MOCK_OPTIONS) --shell @echo Done mock-%: srpm mock-clean mock $(MOCK_OPTIONS) --root=$* --no-cleanup-after --rebuild \ $(WITH) "$(RPM_SRCRPM_DIR)"/*.src.rpm .PHONY: mock mock: mock-$(MOCK_CFG) @echo Done .PHONY: dirty dirty: $(MAKE) $(AM_MAKEFLAGS) DIRTY=yes mock .PHONY: mock-clean mock-clean: -rm -rf "$(MOCK_DIR)" # Make debugging makefile issues easier vars: @echo "CHECKOUT=$(CHECKOUT)" @echo "VERSION=$(VERSION)" @echo "COMMIT=$(COMMIT)" @echo "TAG=$(TAG)" @echo "DIRTY=$(DIRTY)" @echo "DIRTY_EXT=$(DIRTY_EXT)" - @echo "LAST_RC=$(LAST_RC)" @echo "LAST_RELEASE=$(LAST_RELEASE)" @echo "NEXT_RELEASE=$(NEXT_RELEASE)" @echo "top_distdir=$(top_distdir)" @echo "RPMDEST=$(RPMDEST)" @echo "RPMTYPE=$(RPMTYPE)" @echo "RPM_SPEC_DIR=$(RPM_SPEC_DIR)" @echo "RPM_SRCRPM_DIR=$(RPM_SRCRPM_DIR)" @echo "RPM_OPTS=$(RPM_OPTS)" @echo "RPM_CLEAN=$(RPM_CLEAN)" @echo "WITH=$(WITH)" @echo "BUILD_COUNTER=$(BUILD_COUNTER)" @echo "LAST_COUNT=$(LAST_COUNT)" @echo "COUNT=$(COUNT)" @echo "SPECVERSION=$(SPECVERSION)" @echo "SPEC_COMMIT=$(SPEC_COMMIT)" @echo "SPEC_ABBREV=$(SPEC_ABBREV)" @echo "SPEC_RELEASE=$(SPEC_RELEASE)" @echo "SPEC_RELEASE_NO=$(SPEC_RELEASE_NO)" @echo "TARFILE=$(TARFILE)" clean-local: mock-clean rpm-clean -rm -f "$(TARFILE)"