From 27e198aa3005ac334529cdbdba169261cc42d3c5 Mon Sep 17 00:00:00 2001 From: matt brennan Date: Fri, 9 Nov 2018 10:46:13 +0000 Subject: [PATCH] split index.mk into single-task makefiles (#143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐿 v2.10.3 --- index.mk | 295 ++---------------------------------- secret-squirrel.js | 7 +- src/setup.mk | 62 ++++++++ src/tasks/a11y.mk | 13 ++ src/tasks/aliases.mk | 5 + src/tasks/assets.mk | 4 + src/tasks/build.mk | 12 ++ src/tasks/clean.mk | 4 + src/tasks/deploy-by-day.mk | 19 +++ src/tasks/env.mk | 22 +++ src/tasks/fix-lintspaces.mk | 12 ++ src/tasks/help.mk | 6 + src/tasks/init.mk | 7 + src/tasks/install.mk | 39 +++++ src/tasks/npm-publish.mk | 7 + src/tasks/smoke.mk | 11 ++ src/tasks/verify.mk | 39 +++++ src/tasks/watch.mk | 4 + 18 files changed, 278 insertions(+), 290 deletions(-) create mode 100644 src/setup.mk create mode 100644 src/tasks/a11y.mk create mode 100644 src/tasks/aliases.mk create mode 100644 src/tasks/assets.mk create mode 100644 src/tasks/build.mk create mode 100644 src/tasks/clean.mk create mode 100644 src/tasks/deploy-by-day.mk create mode 100644 src/tasks/env.mk create mode 100644 src/tasks/fix-lintspaces.mk create mode 100644 src/tasks/help.mk create mode 100644 src/tasks/init.mk create mode 100644 src/tasks/install.mk create mode 100644 src/tasks/npm-publish.mk create mode 100644 src/tasks/smoke.mk create mode 100644 src/tasks/verify.mk create mode 100644 src/tasks/watch.mk diff --git a/index.mk b/index.mk index e9f6efc..02c8858 100644 --- a/index.mk +++ b/index.mk @@ -1,288 +1,11 @@ +# find out where we are so we can include things relatively. MAKEFILE_LIST is the list +# of all included makefiles; this makefile will be the most recent one +this-makefile = $(realpath $(lastword $(MAKEFILE_LIST))) +ngage-dir := $(dir $(this-makefile)) -# Export environment variables if a .env file is present. -ifeq ($(ENV_EXPORTED),) # ENV vars not yet exported -ifneq ("$(wildcard .env)","") -sinclude .env -export $(shell [ -f .env ] && sed 's/=.*//' .env) -export ENV_EXPORTED=true -$(info Note — An .env file exists. Its contents have been exported as environment variables.) -endif -endif +# empty rule to prevent tasks matching their own filenames and trying to remake themselves +$(ngage-dir)src/%.mk: ; -# Enforce repo ownership -ifeq ("$(wildcard ft.yml)","") -$(error 'Projects making use of n-gage *must* define an ft.yml file containing the repo owner’s details (see any next- repo for required structure)') -$(error 'If you are creating a project not to be maintained by the next team please feel free to copy what you need from our build tools but don’t add an ft.yml.') -$(error 'Integrating with our tooling may result in unwanted effects e.g. nightly builds, slack alerts, emails etc') -endif - -# ./node_modules/.bin on the PATH -export PATH := $(PATH):./node_modules/.bin - -# Use bash not sh -SHELL := /bin/bash - -ifeq ("$(wildcard node_modules/@financial-times/n-gage/index.mk)","") -PATH_TO_NGAGE := -else -PATH_TO_NGAGE := node_modules/@financial-times/n-gage/ -endif - -# verify that githooks are configured correctly -GITHOOKS := $(shell node ${PATH_TO_NGAGE}scripts/githooks.js) -ifneq ("$(GITHOOKS)","") -$(error $(GITHOOKS)) -endif - -# Some handy utilities -GLOB = git ls-files -z $1 | tr '\0' '\n' | xargs -I {} find {} ! -type l -NPM_INSTALL = npm prune --production=false --no-package-lock && npm install --no-package-lock -BOWER_INSTALL = bower prune && bower install --config.registry.search=https://origami-bower-registry.ft.com --config.registry.search=https://registry.bower.io -JSON_GET_VALUE = grep $1 | head -n 1 | sed 's/[," ]//g' | cut -d : -f 2 -IS_GIT_IGNORED = grep -q $(if $1, $1, $@) .gitignore -VERSION = master -APP_NAME = $(shell cat package.json 2>/dev/null | $(call JSON_GET_VALUE,name)) -DONE = echo ✓ $@ done -IS_USER_FACING = `find . -type d \( -path ./bower_components -o -path ./node_modules -o -path ./coverage \) -prune -o -name '*.html' -print` -MAKEFILE_HAS_A11Y = `grep -rli "a11y" Makefile` -REPLACE_IN_GITIGNORE = sed -i -e 's/$1/$2/g' .gitignore && rm -f .gitignore-e ||: -ENTRY_MAKEFILE = $(firstword $(MAKEFILE_LIST)) - -# -# META TASKS -# - -# Note: A 'node_modules' directory is created when n-gage self-installs. -# However: Subsequent calls to `node_modules`, made in order to execute $NPM_INSTALL, -# are *not* processed because the node_modules directory exists. -# Therefore use .PHONY to tell Make to not look for a node_modules file/folder, -# but to run the node_modules task instead. 'bower_components' is incuded for similar -# reasons, though it's not strictly neccessary at this point in time. -.PHONY: test node_modules bower_components - -# -# COMMON TASKS -# - -clea%: ## clean: Clean this git repository. -# HACK: Can't use -e option here because it's not supported by our Jenkins - @git clean -fxdi - @$(DONE) - -ini%: ## init: Clean this repository and start from a fresh build. -ini%: - $(MAKE) clean - $(MAKE) install - $(MAKE) .env - $(MAKE) build - @$(DONE) - -instal%: ## install: Setup this repository. -instal%: node_modules bower_components stylelint-transition .editorconfig .eslintrc.js .stylelintrc .pa11yci.js - @$(MAKE) $(foreach f, $(shell find functions/* -type d -maxdepth 0 2>/dev/null), $f/node_modules $f/bower_components) - @$(DONE) - @if [ -z $(CIRCLECI) ] && [ ! -e .env ]; then (echo "Note: If this is a development environment, you will likely need to import the project's environment variables by running 'make .env'."); fi - -verif%: ## verify: Verify this repository. -verif%: ci-n-ui-check _verify_lintspaces _verify_eslint _verify_stylelint _verify_pa11y_testable - @$(DONE) - -a11%: ## a11y: Check accessibility for this repository. -a11%: _run_pa11y - @$(DONE) - -asset%: ## assets: Build the static assets. -asset%: ## assets-production: Build the static assets for production. - @if [ -e webpack.config.js ]; then webpack $(if $(findstring assets-production,$@),--bail,--debug); fi - -buil%: ## build: Build this repository. -buil%: ## build-production: Build this repository for production. -buil%: public/__about.json - @if [ -e webpack.config.js ]; then $(MAKE) $(subst build,assets,$@); fi - @if [ -e Procfile ] && [ "$(findstring build-production,$@)" == "build-production" ]; then haikro build; fi - @$(DONE) - -smok%: -ifneq ($(CIRCLE_BRANCH),) - TEST_URL=${TEST_APP}; \ - echo ${TEST_APP} | grep http -s || TEST_URL=http://${TEST_APP}.herokuapp.com; \ - n-test smoke -H $$TEST_URL; -else - @if [ -z "$(TEST_URL)" ]; then TEST_URL=local.ft.com:3002; fi; \ - n-test smoke -H $$TEST_URL; -endif - @$(DONE) - -watc%: ## watch: Watch for static asset changes. - @if [ -e webpack.config.js ]; then webpack --watch --debug; fi - @$(DONE) - -# -# SUB-TASKS -# - -ci-n-ui-check: -# In CircleCI -ifneq ($(CIRCLE_BUILD_NUM),) -# The app is using n-ui -ifneq ($(shell grep -s -Fim 1 '"n-ui"' bower.json),) -# versions in package.json and bower.json are not equal -ifneq ($(shell awk '$$1 == "\"version\":" {print $$2}' bower_components/n-ui/.bower.json | sed s/,//),$(shell awk '$$1 == "\"version\":" {print $$2}' node_modules/@financial-times/n-ui/package.json | sed s/,//)) - $(error 'Projects using n-ui must maintain parity between versions. Rebuild without cache and update your bower.json and package.json if necessary. If this error persists make sure that the n-ui build succeeded in publishing a new version to NPM (https://circleci.com/gh/Financial-Times/n-ui) and that both NPM and Bower registries have the latest version.') -endif -endif -endif - -# INSTALL SUB-TASKS - -# Regular npm install -node_modules: package.json - @if [ -e package-lock.json ]; then rm package-lock.json; fi - @if [ -e package.json ]; then $(NPM_INSTALL) && $(DONE); fi - -# Regular bower install -bower_components: bower.json - @if [ -e bower.json ]; then $(BOWER_INSTALL) && $(DONE); fi - -# These tasks have been intentionally left blank -package.json: -bower.json: - -# node_modules for Lambda functions -functions/%/node_modules: - @cd $(dir $@) && if [ -e package.json ]; then $(NPM_INSTALL) && $(DONE); fi - -# bower_components for Lambda functions -functions/%/bower_components: - @cd $(dir $@) && if [ -e bower.json ]; then $(BOWER_INSTALL) && $(DONE); fi - -# Manage various dot/config files if they're in the .gitignore -.editorconfig .eslintrc.js .stylelintrc .pa11yci.js: - @if $(call IS_GIT_IGNORED); then cp './node_modules/@financial-times/n-gage/dotfiles/$@' $@ && $(DONE); fi - -stylelint-transition: - @if ! $(call IS_GIT_IGNORED,'.stylelintrc') && $(call IS_GIT_IGNORED,'.scss-lint.yml'); \ - then $(call REPLACE_IN_GITIGNORE,'.scss-lint.yml','.stylelintrc') \ - && echo "*** Next developers***\nProjects making use of SCSS linting must now include .stylelintrc instead of .scss-lint.yml in .gitignore. Please commit your modified .gitignore" \ - && $(DONE); \ - fi - -ENV_MSG_IGNORE_ENV = - -# Environment variables come from https://github.com/Financial-Times/next-vault-sync -.env: - @if [[ -z "$(shell command -v vault)" ]]; then echo "Error: You don't have Vault installed. Follow the guide at https://github.com/Financial-Times/vault/wiki/Getting-Started"; exit 1; fi - @if [[ -z "$(shell find ~/.vault-token -mmin -480)" ]]; then echo "Error: You are not logged into Vault. Try vault login --method github."; exit 1; fi - @if [[ -z "$(shell grep '*.env*' .gitignore)" ]]; then echo "Error: .gitignore must include: *.env* (including the asterisks)"; exit 1; fi - @if [[ ! -e package.json ]]; then echo "Error: package.json not found."; exit 1; fi - @if [[ ! -z "$(CIRCLECI)" ]]; then echo "Error: The CIRCLECI environment variable must *not* be set."; exit 1; fi - - @ngage get-config --team $(TEAM) - - @$(DONE) - -# for use with CI deployments that need the env vars in a file (dotenv format) -.env-vault-circleci-dotenv: - @ngage get-config --env prod --team $(TEAM) - @$(DONE) - -# for use with CI deployments that need the env vars in a file (JSON format) -.env-vault-circleci-json: - @ngage get-config --env prod --format json --team $(TEAM) - @$(DONE) - -# VERIFY SUB-TASKS - -_verify_eslint: - @if [ -e .eslintrc.js ]; then $(call GLOB,'*.js') | xargs eslint --ignore-pattern '!' --fix && $(DONE); fi - -_verify_lintspaces: - @if [ -e .editorconfig ] && [ -e package.json ]; then $(call GLOB) | grep -Ev '(package.json|bower.json|circle.yml)' | xargs lintspaces -e .editorconfig -i js-comments -i html-comments && $(DONE); fi - -_verify_stylelint: - @if [ -e .stylelintrc ]; \ - then $(call GLOB,'*.scss') | xargs stylelint \ - && echo "*** Next developers ***\nPro tip for fixing SCSS linting errors: stylelint client/**.scss --fix" \ - && $(DONE); \ - fi - -VERIFY_MSG_NO_DEMO = "Error: Components with templates must have a demo app, so that pa11y can test against it. This component doesn’t seem to have one. Add a demo app to continue peacefully. See n-image for an example." -VERIFY_MSG_NO_PA11Y = "\n**** Error ****\nIt looks like your code is user-facing; your Makefile should include make a11y\nIf you need to disable a11y, use export IGNORE_A11Y = true in your Makefile\n********\n\n" -#check if project has HTML and missing make a11y command -#check if project has demo app if there's a make a11y command -_verify_pa11y_testable: - @if [ ! -z "$(IS_USER_FACING)" ] && [ -z $(MAKEFILE_HAS_A11Y) ] && [ ! ${IGNORE_A11Y} ]; then (printf $(VERIFY_MSG_NO_PA11Y) && exit 1); fi - @if [ ! -z "$(IS_USER_FACING)" ] && [ ! -d server ] && [ ! -f demos/app.js ] && [ ! -f demos/app.ts ] && [ ! ${IGNORE_A11Y} ]; then (echo $(VERIFY_MSG_NO_DEMO) && exit 1); fi - @$(DONE) - - -_run_pa11y: - echo $(CIRCLE_BRANCH) -ifneq ($(CIRCLE_BRANCH),) - @export TEST_URL=${TEST_APP}; \ - echo ${TEST_APP} | grep http -s || export TEST_URL=http://${TEST_APP}.herokuapp.com; \ - pa11y-ci; -else - @if [ -z "$(TEST_URL)" ]; then export TEST_URL=https://local.ft.com:5050; fi; pa11y-ci; -endif - -# autofix common lintspaces issues -# -# 1. convert two spaces to one tab -# 2. convert space-tab to tab with all files -# 3. convert solitary space at the beginning of line to tab -# 4 convert "blank" lines to be actually blank -fix-lintspaces: - $(call GLOB,'*.js') | xargs sed -Ei '' 's/ / /g' \ - && $(call GLOB,'*.js') | xargs sed -Ei '' 's/ / /g' \ - && $(call GLOB,'*.js') | xargs sed -Ei '' 's/^ / /g' \ - && $(call GLOB,'*') | xargs sed -Ei '' 's/[[:blank:]]+$$//g' \ - && $(DONE) - - -# DEPLOY SUB-TASKS - -npm-publis%: ## npm-publish: Publish this package to npm. -ifneq ($(CIRCLE_TAG),) - npm version --no-git-tag-version ${CIRCLE_TAG} -else - npm-prepublish --verbose -endif - npm publish --access public - -# BUILD SUB-TASKS - -# Only apply to Heroku apps for now -public/__about.json: - @if [ -e Procfile ]; then mkdir -p public && echo '{"description":"$(call APP_NAME)","support":"next.team@ft.com","supportStatus":"active","appVersion":"$(shell git rev-parse HEAD | xargs echo -n)","buildCompletionTime":"$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")"}' > $@ && $(DONE); fi - -hel%: ## help: Show this help message. - @echo "usage: make [target] ..." - @echo "" - @echo "targets:" - @grep -Eh '^.+:\ ##\ .+' ${MAKEFILE_LIST} | cut -d ' ' -f '3-' | column -t -s ':' - -# Wrapper for make deploy which prevents it running when build is a nightly -# Nightly builds are trigger by next-rebuild-bot -# If a nightly build is triggered during the day, we want it to deploy since it is a rerun build! -# CircleCI runs in UTC, so give an hour leeway each way. - -HOUR = $(shell date +%H) - -deploy-by-day: -ifeq ($(FT_NIGHTLY_BUILD),) - $(MAKE) deploy -else - @echo "The hour is $(HOUR)"; - @if [ $(HOUR) -gt 8 -a $(HOUR) -lt 19 ] ; then \ - echo "Nightly build can deploy between 8am and 7pm, so deploying..."; $(MAKE) deploy; \ - else \ - echo "Nightly build and out of hours - exiting before deploy"; \ - fi; -endif - -# some aliases -css: - nui build --sass-only -js: - nui build --js-only +# include all tasks +include $(ngage-dir)src/setup.mk +include $(ngage-dir)src/tasks/*.mk diff --git a/secret-squirrel.js b/secret-squirrel.js index e7154d9..7edbaff 100644 --- a/secret-squirrel.js +++ b/secret-squirrel.js @@ -1,14 +1,13 @@ module.exports = { files: { allow: [ - 'dotfiles/.stylelintrc' + 'dotfiles/.stylelintrc', + '.*.mk' ], allowOverrides: [] }, strings: { deny: [], - denyOverrides: [ - '20b036d0-6714-11e7-9516-4db7cf5df6d0' // README.md:3 - ] + denyOverrides: [] } }; diff --git a/src/setup.mk b/src/setup.mk new file mode 100644 index 0000000..749d0fe --- /dev/null +++ b/src/setup.mk @@ -0,0 +1,62 @@ +# common variables for tasks, make flags, meta rules + +# Export environment variables if a .env file is present. +ifeq ($(ENV_EXPORTED),) # ENV vars not yet exported +ifneq ("$(wildcard .env)","") +sinclude .env +export $(shell [ -f .env ] && sed 's/=.*//' .env) +export ENV_EXPORTED=true +$(info Note — An .env file exists. Its contents have been exported as environment variables.) +endif +endif + +# Enforce repo ownership +ifeq ("$(wildcard ft.yml)","") +$(error 'Projects making use of n-gage *must* define an ft.yml file containing the repo owner’s details (see any next- repo for required structure)') +$(error 'If you are creating a project not to be maintained by the next team please feel free to copy what you need from our build tools but don’t add an ft.yml.') +$(error 'Integrating with our tooling may result in unwanted effects e.g. nightly builds, slack alerts, emails etc') +endif + +# ./node_modules/.bin on the PATH +export PATH := $(PATH):./node_modules/.bin + +# Use bash not sh +SHELL := /bin/bash + +ifeq ("$(wildcard node_modules/@financial-times/n-gage/index.mk)","") +PATH_TO_NGAGE := +else +PATH_TO_NGAGE := node_modules/@financial-times/n-gage/ +endif + +# verify that githooks are configured correctly +GITHOOKS := $(shell node ${PATH_TO_NGAGE}scripts/githooks.js) +ifneq ("$(GITHOOKS)","") +$(error $(GITHOOKS)) +endif + +# Some handy utilities +GLOB = git ls-files -z $1 | tr '\0' '\n' | xargs -I {} find {} ! -type l +NPM_INSTALL = npm prune --production=false --no-package-lock && npm install --no-package-lock +BOWER_INSTALL = bower prune && bower install --config.registry.search=https://origami-bower-registry.ft.com --config.registry.search=https://registry.bower.io +JSON_GET_VALUE = grep $1 | head -n 1 | sed 's/[," ]//g' | cut -d : -f 2 +IS_GIT_IGNORED = grep -q $(if $1, $1, $@) .gitignore +VERSION = master +APP_NAME = $(shell cat package.json 2>/dev/null | $(call JSON_GET_VALUE,name)) +DONE = echo ✓ $@ done +IS_USER_FACING = `find . -type d \( -path ./bower_components -o -path ./node_modules -o -path ./coverage \) -prune -o -name '*.html' -print` +MAKEFILE_HAS_A11Y = `grep -rli "a11y" Makefile` +REPLACE_IN_GITIGNORE = sed -i -e 's/$1/$2/g' .gitignore && rm -f .gitignore-e ||: +ENTRY_MAKEFILE = $(firstword $(MAKEFILE_LIST)) + +# +# META TASKS +# + +# Note: A 'node_modules' directory is created when n-gage self-installs. +# However: Subsequent calls to `node_modules`, made in order to execute $NPM_INSTALL, +# are *not* processed because the node_modules directory exists. +# Therefore use .PHONY to tell Make to not look for a node_modules file/folder, +# but to run the node_modules task instead. 'bower_components' is incuded for similar +# reasons, though it's not strictly neccessary at this point in time. +.PHONY: test node_modules bower_components diff --git a/src/tasks/a11y.mk b/src/tasks/a11y.mk new file mode 100644 index 0000000..b81530f --- /dev/null +++ b/src/tasks/a11y.mk @@ -0,0 +1,13 @@ +a11%: ## a11y: Check accessibility for this repository. +a11%: _run_pa11y + @$(DONE) + +_run_pa11y: + echo $(CIRCLE_BRANCH) +ifneq ($(CIRCLE_BRANCH),) + @export TEST_URL=${TEST_APP}; \ + echo ${TEST_APP} | grep http -s || export TEST_URL=http://${TEST_APP}.herokuapp.com; \ + pa11y-ci; +else + @if [ -z "$(TEST_URL)" ]; then export TEST_URL=https://local.ft.com:5050; fi; pa11y-ci; +endif diff --git a/src/tasks/aliases.mk b/src/tasks/aliases.mk new file mode 100644 index 0000000..64f3e6c --- /dev/null +++ b/src/tasks/aliases.mk @@ -0,0 +1,5 @@ +# some aliases +css: + nui build --sass-only +js: + nui build --js-only diff --git a/src/tasks/assets.mk b/src/tasks/assets.mk new file mode 100644 index 0000000..8392733 --- /dev/null +++ b/src/tasks/assets.mk @@ -0,0 +1,4 @@ + +asset%: ## assets: Build the static assets. +asset%: ## assets-production: Build the static assets for production. + @if [ -e webpack.config.js ]; then webpack $(if $(findstring assets-production,$@),--bail,--debug); fi diff --git a/src/tasks/build.mk b/src/tasks/build.mk new file mode 100644 index 0000000..49d4bf3 --- /dev/null +++ b/src/tasks/build.mk @@ -0,0 +1,12 @@ +buil%: ## build: Build this repository. +buil%: ## build-production: Build this repository for production. +buil%: public/__about.json + @if [ -e webpack.config.js ]; then $(MAKE) $(subst build,assets,$@); fi + @if [ -e Procfile ] && [ "$(findstring build-production,$@)" == "build-production" ]; then haikro build; fi + @$(DONE) + +# BUILD SUB-TASKS + +# Only apply to Heroku apps for now +public/__about.json: + @if [ -e Procfile ]; then mkdir -p public && echo '{"description":"$(call APP_NAME)","support":"next.team@ft.com","supportStatus":"active","appVersion":"$(shell git rev-parse HEAD | xargs echo -n)","buildCompletionTime":"$(shell date -u +"%Y-%m-%dT%H:%M:%SZ")"}' > $@ && $(DONE); fi diff --git a/src/tasks/clean.mk b/src/tasks/clean.mk new file mode 100644 index 0000000..8559215 --- /dev/null +++ b/src/tasks/clean.mk @@ -0,0 +1,4 @@ +clea%: ## clean: Clean this git repository. +# HACK: Can't use -e option here because it's not supported by our Jenkins + @git clean -fxdi + @$(DONE) diff --git a/src/tasks/deploy-by-day.mk b/src/tasks/deploy-by-day.mk new file mode 100644 index 0000000..e8b33f2 --- /dev/null +++ b/src/tasks/deploy-by-day.mk @@ -0,0 +1,19 @@ + +# Wrapper for make deploy which prevents it running when build is a nightly +# Nightly builds are trigger by next-rebuild-bot +# If a nightly build is triggered during the day, we want it to deploy since it is a rerun build! +# CircleCI runs in UTC, so give an hour leeway each way. + +HOUR = $(shell date +%H) + +deploy-by-day: +ifeq ($(FT_NIGHTLY_BUILD),) + $(MAKE) deploy +else + @echo "The hour is $(HOUR)"; + @if [ $(HOUR) -gt 8 -a $(HOUR) -lt 19 ] ; then \ + echo "Nightly build can deploy between 8am and 7pm, so deploying..."; $(MAKE) deploy; \ + else \ + echo "Nightly build and out of hours - exiting before deploy"; \ + fi; +endif diff --git a/src/tasks/env.mk b/src/tasks/env.mk new file mode 100644 index 0000000..83ff32e --- /dev/null +++ b/src/tasks/env.mk @@ -0,0 +1,22 @@ + +# Environment variables come from https://github.com/Financial-Times/next-vault-sync +.env: + @if [[ -z "$(shell command -v vault)" ]]; then echo "Error: You don't have Vault installed. Follow the guide at https://github.com/Financial-Times/vault/wiki/Getting-Started"; exit 1; fi + @if [[ -z "$(shell find ~/.vault-token -mmin -480)" ]]; then echo "Error: You are not logged into Vault. Try vault login --method github."; exit 1; fi + @if [[ -z "$(shell grep '*.env*' .gitignore)" ]]; then echo "Error: .gitignore must include: *.env* (including the asterisks)"; exit 1; fi + @if [[ ! -e package.json ]]; then echo "Error: package.json not found."; exit 1; fi + @if [[ ! -z "$(CIRCLECI)" ]]; then echo "Error: The CIRCLECI environment variable must *not* be set."; exit 1; fi + + @ngage get-config --team $(TEAM) + + @$(DONE) + +# for use with CI deployments that need the env vars in a file (dotenv format) +.env-vault-circleci-dotenv: + @ngage get-config --env prod --team $(TEAM) + @$(DONE) + +# for use with CI deployments that need the env vars in a file (JSON format) +.env-vault-circleci-json: + @ngage get-config --env prod --format json --team $(TEAM) + @$(DONE) diff --git a/src/tasks/fix-lintspaces.mk b/src/tasks/fix-lintspaces.mk new file mode 100644 index 0000000..d64cc67 --- /dev/null +++ b/src/tasks/fix-lintspaces.mk @@ -0,0 +1,12 @@ +# autofix common lintspaces issues +# +# 1. convert two spaces to one tab +# 2. convert space-tab to tab with all files +# 3. convert solitary space at the beginning of line to tab +# 4 convert "blank" lines to be actually blank +fix-lintspaces: + $(call GLOB,'*.js') | xargs sed -Ei '' 's/ / /g' \ + && $(call GLOB,'*.js') | xargs sed -Ei '' 's/ / /g' \ + && $(call GLOB,'*.js') | xargs sed -Ei '' 's/^ / /g' \ + && $(call GLOB,'*') | xargs sed -Ei '' 's/[[:blank:]]+$$//g' \ + && $(DONE) diff --git a/src/tasks/help.mk b/src/tasks/help.mk new file mode 100644 index 0000000..e429b30 --- /dev/null +++ b/src/tasks/help.mk @@ -0,0 +1,6 @@ + +hel%: ## help: Show this help message. + @echo "usage: make [target] ..." + @echo "" + @echo "targets:" + @grep -Eh '^.+:\ ##\ .+' ${MAKEFILE_LIST} | cut -d ' ' -f '3-' | column -t -s ':' diff --git a/src/tasks/init.mk b/src/tasks/init.mk new file mode 100644 index 0000000..91e3a6a --- /dev/null +++ b/src/tasks/init.mk @@ -0,0 +1,7 @@ +ini%: ## init: Clean this repository and start from a fresh build. +ini%: + $(MAKE) clean + $(MAKE) install + $(MAKE) .env + $(MAKE) build + @$(DONE) diff --git a/src/tasks/install.mk b/src/tasks/install.mk new file mode 100644 index 0000000..614e13b --- /dev/null +++ b/src/tasks/install.mk @@ -0,0 +1,39 @@ +instal%: ## install: Setup this repository. +instal%: node_modules bower_components stylelint-transition .editorconfig .eslintrc.js .stylelintrc .pa11yci.js + $(MAKE) $(foreach f, $(shell find functions/* -type d -maxdepth 0 2>/dev/null), $f/node_modules $f/bower_components) + @$(DONE) + @if [ -z $(CIRCLECI) ] && [ ! -e .env ]; then (echo "Note: If this is a development environment, you will likely need to import the project's environment variables by running 'make .env'."); fi + +# INSTALL SUB-TASKS + +# Regular npm install +node_modules: package.json + @if [ -e package-lock.json ]; then rm package-lock.json; fi + @if [ -e package.json ]; then $(NPM_INSTALL) && $(DONE); fi + +# Regular bower install +bower_components: bower.json + @if [ -e bower.json ]; then $(BOWER_INSTALL) && $(DONE); fi + +# These tasks have been intentionally left blank +package.json: +bower.json: + +# node_modules for Lambda functions +functions/%/node_modules: + @cd $(dir $@) && if [ -e package.json ]; then $(NPM_INSTALL) && $(DONE); fi + +# bower_components for Lambda functions +functions/%/bower_components: + @cd $(dir $@) && if [ -e bower.json ]; then $(BOWER_INSTALL) && $(DONE); fi + +# Manage various dot/config files if they're in the .gitignore +.editorconfig .eslintrc.js .stylelintrc .pa11yci.js: + @if $(call IS_GIT_IGNORED); then cp './node_modules/@financial-times/n-gage/dotfiles/$@' $@ && $(DONE); fi + +stylelint-transition: + @if ! $(call IS_GIT_IGNORED,'.stylelintrc') && $(call IS_GIT_IGNORED,'.scss-lint.yml'); \ + then $(call REPLACE_IN_GITIGNORE,'.scss-lint.yml','.stylelintrc') \ + && echo "*** Next developers***\nProjects making use of SCSS linting must now include .stylelintrc instead of .scss-lint.yml in .gitignore. Please commit your modified .gitignore" \ + && $(DONE); \ + fi diff --git a/src/tasks/npm-publish.mk b/src/tasks/npm-publish.mk new file mode 100644 index 0000000..f2352f3 --- /dev/null +++ b/src/tasks/npm-publish.mk @@ -0,0 +1,7 @@ +npm-publis%: ## npm-publish: Publish this package to npm. +ifneq ($(CIRCLE_TAG),) + npm version --no-git-tag-version ${CIRCLE_TAG} +else + npm-prepublish --verbose +endif + npm publish --access public diff --git a/src/tasks/smoke.mk b/src/tasks/smoke.mk new file mode 100644 index 0000000..0b7bcf1 --- /dev/null +++ b/src/tasks/smoke.mk @@ -0,0 +1,11 @@ + +smok%: +ifneq ($(CIRCLE_BRANCH),) + TEST_URL=${TEST_APP}; \ + echo ${TEST_APP} | grep http -s || TEST_URL=http://${TEST_APP}.herokuapp.com; \ + n-test smoke -H $$TEST_URL; +else + @if [ -z "$(TEST_URL)" ]; then TEST_URL=local.ft.com:3002; fi; \ + n-test smoke -H $$TEST_URL; +endif + @$(DONE) diff --git a/src/tasks/verify.mk b/src/tasks/verify.mk new file mode 100644 index 0000000..01640ac --- /dev/null +++ b/src/tasks/verify.mk @@ -0,0 +1,39 @@ +verif%: ## verify: Verify this repository. +verif%: ci-n-ui-check _verify_lintspaces _verify_eslint _verify_stylelint _verify_pa11y_testable + @$(DONE) + +# DEPLOY SUB-TASKS + +ci-n-ui-check: +# In CircleCI +ifneq ($(CIRCLE_BUILD_NUM),) +# The app is using n-ui +ifneq ($(shell grep -s -Fim 1 '"n-ui"' bower.json),) +# versions in package.json and bower.json are not equal +ifneq ($(shell awk '$$1 == "\"version\":" {print $$2}' bower_components/n-ui/.bower.json | sed s/,//),$(shell awk '$$1 == "\"version\":" {print $$2}' node_modules/@financial-times/n-ui/package.json | sed s/,//)) + $(error 'Projects using n-ui must maintain parity between versions. Rebuild without cache and update your bower.json and package.json if necessary. If this error persists make sure that the n-ui build succeeded in publishing a new version to NPM (https://circleci.com/gh/Financial-Times/n-ui) and that both NPM and Bower registries have the latest version.') +endif +endif +endif + +_verify_eslint: + @if [ -e .eslintrc.js ]; then $(call GLOB,'*.js') | xargs eslint --ignore-pattern '!' --fix && $(DONE); fi + +_verify_lintspaces: + @if [ -e .editorconfig ] && [ -e package.json ]; then $(call GLOB) | grep -Ev '(package.json|bower.json|circle.yml)' | xargs lintspaces -e .editorconfig -i js-comments -i html-comments && $(DONE); fi + +_verify_stylelint: + @if [ -e .stylelintrc ]; \ + then $(call GLOB,'*.scss') | xargs stylelint \ + && echo "*** Next developers ***\nPro tip for fixing SCSS linting errors: stylelint client/**.scss --fix" \ + && $(DONE); \ + fi + +VERIFY_MSG_NO_DEMO = "Error: Components with templates must have a demo app, so that pa11y can test against it. This component doesn’t seem to have one. Add a demo app to continue peacefully. See n-image for an example." +VERIFY_MSG_NO_PA11Y = "\n**** Error ****\nIt looks like your code is user-facing; your Makefile should include make a11y\nIf you need to disable a11y, use export IGNORE_A11Y = true in your Makefile\n********\n\n" +#check if project has HTML and missing make a11y command +#check if project has demo app if there's a make a11y command +_verify_pa11y_testable: + @if [ ! -z "$(IS_USER_FACING)" ] && [ -z $(MAKEFILE_HAS_A11Y) ] && [ ! ${IGNORE_A11Y} ]; then (printf $(VERIFY_MSG_NO_PA11Y) && exit 1); fi + @if [ ! -z "$(IS_USER_FACING)" ] && [ ! -d server ] && [ ! -f demos/app.js ] && [ ! -f demos/app.ts ] && [ ! ${IGNORE_A11Y} ]; then (echo $(VERIFY_MSG_NO_DEMO) && exit 1); fi + @$(DONE) diff --git a/src/tasks/watch.mk b/src/tasks/watch.mk new file mode 100644 index 0000000..886deb0 --- /dev/null +++ b/src/tasks/watch.mk @@ -0,0 +1,4 @@ + +watc%: ## watch: Watch for static asset changes. + @if [ -e webpack.config.js ]; then webpack --watch --debug; fi + @$(DONE)