Recently while working on a project I needed a way to include secrets in my repo for local development that integrated with my Make based build setup. I found that a nice way to do this is with the include command in Make.

The include command allows you to include external files to augment your makefile. First I created a secrets.mk and declared variables in it for my API keys.

1
2
3
# secrets.mk
github_access_token := 'xxxxxxxxxxxxxxxxx'
slack_access_token := 'xxxxxxxxxxxxxxxxx'

Then in my makefile I added include secrets.mk. Don't forget to add secrets.mk to your .gitignore!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
include secrets.mk
.PHONY: dev

dev: app
  GITHUB_ACCESS_TOKEN=$(github_access_token) \
  SLACK_ACCESS_TOKEN=$(slack_access_token) \
  ./app

app:
  go build -o app main.go

One issue with this I ran into was in my CI build I didn't have a secrets.mk file. Make will fail if it cannot find an include file on disk or if it Make unable to find a rule to generate one. Luckily you can preprend a dash to the include statement to make it optional, so the rest of your tasks that don't require an include will still be usable.

1
-include secrets.mk

Lastly, another neat thing about using this technique is that if an include isn't found, Make will look for a task that can generate it. I added a secrets.mk task to my makefile that creates a stub include file that can get filled out with the correct credentials if needed.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
include secrets.mk
.PHONY: dev

dev: app
  GITHUB_ACCESS_TOKEN=$(github_access_token) \
  SLACK_ACCESS_TOKEN=$(slack_access_token) \
  ./app

app:
  go build -o app main.go

secrets.mk:
  echo "github_access_token:='xxxxxxxx'" > ./secrets.mk
  echo "slack_access_token:='xxxxxxxxx'" >> ./secrets.mk