Skip to content

Instantly share code, notes, and snippets.

@eemeli
Last active August 29, 2015 14:17
Show Gist options
  • Save eemeli/10da76978786b0e84ae3 to your computer and use it in GitHub Desktop.
Save eemeli/10da76978786b0e84ae3 to your computer and use it in GitHub Desktop.
GNU make rules to release a new version of an npm project with a Github repo, resulting in an off-tree tagged release containing generated files. Includes checks to make sure releases are only made from a clean working tree that matches the current Github HEAD of the project. License: ISC.
# Copyright (c) 2015 by Eemeli Aro <[email protected]>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# The software is provided "as is" and the author disclaims all warranties
# with regard to this software including all implied warranties of
# merchantability and fitness. In no event shall the author be liable for
# any special, direct, indirect, or consequential damages or any damages
# whatsoever resulting from loss of use, data or profits, whether in an
# action of contract, negligence or other tortious action, arising out of
# or in connection with the use or performance of this software.
VT = \033[$(1)m
VT0 := $(call VT,0)
VT_DIM := $(call VT,2)
VT_HL := $(call VT,33;1)
CHK := $(call VT,32;1)✓${VT0}
ERR := $(call VT,31;1)✖${VT0}
GH_API_FETCH_VALUE = curl -s https://api.github.com/$(1) | grep -m1 '"$(2)"' | cut -d: -f2 | sed 's/^ *"\?//;s/"\?, *$$//'
GENERATED = file1 file2 file3
GH_REPO = owner/repo
NPM_TAG = latest
release-check-init:
@if [ -z "$(VERSION)" ]; then echo "$(ERR) Release version not set! Use 'make release VERSION=... [NPM_TAG=...]'\n"; exit 1; fi
@if ! git diff-index --quiet HEAD; then echo "$(ERR) Git working directory is not clean!\n"; exit 1; fi
@echo "$(CHK) Git working directory is clean"
@echo " $(VT_DIM)Fetching remote data from github...$(VT0)"
release-check-branch:
$(eval GH_BRANCH := $(shell $(call GH_API_FETCH_VALUE,repos/$(GH_REPO),default_branch)))
$(eval GH_BRANCH_PRETTY := $(VT_HL)$(GH_BRANCH)$(VT0))
@if [ `git rev-parse --abbrev-ref HEAD` != "$(GH_BRANCH)" ]; then echo "$(ERR) Not on default branch $(GH_BRANCH_PRETTY)!\n"; exit 1; fi
@echo "$(CHK) Local branch matches remote default $(GH_BRANCH_PRETTY)"
release-check-head: release-check-branch
$(eval GH_HEAD := $(shell $(call GH_API_FETCH_VALUE,repos/$(GH_REPO)/git/refs/heads/$(GH_BRANCH),sha)))
$(eval GH_HEAD_PRETTY := $(VT_HL)$(shell echo "$(GH_HEAD)" | cut -c1-7)$(VT0))
@if [ `git rev-parse HEAD` != "$(GH_HEAD)" ]; then echo "$(ERR) Local HEAD doesn't match remote HEAD $(GH_HEAD_PRETTY)\n"; exit 1; fi
@echo "$(CHK) Local HEAD matches remote HEAD $(GH_HEAD_PRETTY)"
release: release-check-init release-check-branch release-check-head
@echo "$(CHK) All release checks passed\n"
@printf " Push new tag $(VT_HL)v$(VERSION)$(VT0) to github and publish as $(VT_HL)$(VERSION)$(VT0) @ $(VT_HL)$(NPM_TAG)$(VT0) on npm?"
@read -p " [y/N] " -n 1 -r -s; \
if [[ $${REPLY} =~ ^[Yy]$$ ]]; then echo "$${REPLY}\r$(CHK)\n"; \
else echo "\r$(ERR)\n"; exit 1; fi
git checkout -b release
git add -f $(GENERATED)
git commit --message "Packaging output for release"
npm version $(VERSION) -m "Version %s"
git push --tags
npm publish --tag $(NPM_TAG)
git checkout $(GH_BRANCH)
git branch -D release
@eemeli
Copy link
Author

eemeli commented Mar 21, 2015

This is pretty much a direct copy of the relevant sections of the Makefile for make-plural.js. To use, replace at least the contents of GENERATED and GH_REPO as appropriate for your needs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment