Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move to CircleCI for Builds and Tests #631

Merged
merged 21 commits into from
May 14, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d6cf33c
Initial CircleCI
woody-apple May 9, 2020
bc50c2d
Restyled by shellharden
restyled-commits May 9, 2020
4892122
Restyled by shfmt
restyled-commits May 9, 2020
f678e99
Appeasing our restyle.io overlord
woody-apple May 9, 2020
31e64f3
testing
woody-apple May 9, 2020
8f7d581
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 11, 2020
3523c99
Trying to figure out this run_if.sh problem
woody-apple May 11, 2020
b7e5aca
Feedback from Rob W
woody-apple May 11, 2020
4496b9a
Restyled by shfmt
restyled-commits May 11, 2020
c7c4d6f
Typo
woody-apple May 11, 2020
1bf1156
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 11, 2020
6b35e84
Updating restyled to match editorconfig tab spacing
woody-apple May 11, 2020
4c3376e
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 11, 2020
dfc5f98
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 11, 2020
99a9df1
Updating devcontainer
woody-apple May 11, 2020
9c183da
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 12, 2020
9e72fe2
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 12, 2020
8b86aef
Merge branch 'master' of https://github.com/project-chip/connectedhom…
woody-apple May 13, 2020
485f144
Restyled by shfmt
restyled-commits May 13, 2020
b785d8b
Adding simple restyle merge
woody-apple May 13, 2020
7271a13
Restyled by shellharden
restyled-commits May 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .circleci/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config.yml linguist-generated
1 change: 1 addition & 0 deletions .circleci/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.tmp/
95 changes: 95 additions & 0 deletions .circleci/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Set SHELL to 'strict mode' without using .SHELLFLAGS for max compatibility.
# See https://fieldnotes.tech/how-to-shell-for-compatible-makefiles/
SHELL := /usr/bin/env bash -euo pipefail -c

# CONFIG is the name of the make target someone
# would invoke to update the main config file (config.yml).
CONFIG ?= ci-config
# VERIFY is the name of the make target someone
# would invoke to verify the config file.
VERIFY ?= ci-verify

CIRCLECI := circleci --skip-update-check
ifeq ($(DEBUG_CIRCLECI_CLI),YES)
CIRCLECI += --debug
endif

# For config processing, always refer to circleci.com not self-hosted circleci,
# because self-hosted does not currently support the necessary API.
CIRCLECI_CLI_HOST := https://circleci.com
export CIRCLECI_CLI_HOST

# Set up some documentation/help message variables.
# We do not attempt to install the CircleCI CLI from this Makefile.
CCI_INSTALL_LINK := https://circleci.com/docs/2.0/local-cli/\#installation
CCI_INSTALL_MSG := Please install CircleCI CLI. See $(CCI_INSTALL_LINK)
CCI_VERSION := $(shell $(CIRCLECI) version 2> /dev/null)
ifeq ($(CCI_VERSION),)
# Attempting to use the CLI fails with installation instructions.
CIRCLECI := echo '$(CCI_INSTALL_MSG)'; exit 1; \#
endif

SOURCE_DIR := config
SOURCE_YML := $(shell [ ! -d $(SOURCE_DIR) ] || find $(SOURCE_DIR) -name '*.yml')
CONFIG_SOURCE := Makefile $(SOURCE_YML) | $(SOURCE_DIR)
OUT := config.yml
TMP := .tmp/config-processed
CONFIG_PACKED := .tmp/config-packed

default: help

help:
@echo "Usage:"
@echo " make $(CONFIG): recompile config.yml from $(SOURCE_DIR)/"
@echo " make $(VERIFY): verify that config.yml is a true mapping from $(SOURCE_DIR)/"
@echo
@echo "Diagnostics:"
@[ -z "$(CCI_VERSION)" ] || echo " circleci-cli version $(CCI_VERSION)"
@[ -n "$(CCI_VERSION)" ] || echo " $(CCI_INSTALL_MSG)"

$(SOURCE_DIR):
@echo No source directory $(SOURCE_DIR) found.; exit 1

# Make sure our .tmp dir exists.
$(shell [ -d .tmp ] || mkdir .tmp)

.PHONY: $(CONFIG)
$(CONFIG): $(OUT)

.PHONY: $(VERIFY)
$(VERIFY): config-up-to-date
@$(CIRCLECI) config validate $(OUT)

define GENERATED_FILE_HEADER
### ***
### WARNING: DO NOT manually EDIT or MERGE this file, it is generated by 'make $(CONFIG)'.
### INSTEAD: Edit or merge the source in $(SOURCE_DIR)/ then run 'make $(CONFIG)'.
### ***
endef
export GENERATED_FILE_HEADER

# GEN_CONFIG writes the config to a temporary file. If the whole process succeeds,
# it them moves that file to $@. This makes is an atomic operation, so if it fails
gerickson marked this conversation as resolved.
Show resolved Hide resolved
# make doesn't consider a half-baked file up to date.
define GEN_CONFIG
@$(CIRCLECI) config pack $(SOURCE_DIR) > $(CONFIG_PACKED)
@echo "$$GENERATED_FILE_HEADER" > $@.tmp || { rm -f $@; exit 1; }
@$(CIRCLECI) config process $(CONFIG_PACKED) >> $@.tmp || { rm -f $@.tmp; exit 1; }
@mv -f $@.tmp $@
endef

$(OUT): $(CONFIG_SOURCE)
$(GEN_CONFIG)
@echo "$@ updated"

$(TMP): $(CONFIG_SOURCE)
$(GEN_CONFIG)

.PHONY: config-up-to-date
config-up-to-date: $(TMP) # Note this must not depend on $(OUT)!
@if diff -w $(OUT) $<; then \
echo "Generated $(OUT) is up to date!"; \
else \
echo "Generated $(OUT) is out of date, run make $(CONFIG) to update."; \
exit 1; \
fi
130 changes: 130 additions & 0 deletions .circleci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# How to use CircleCI multi-file config

This README and the Makefile should be in your `.circleci` directory,
in the root of your repository.
All path references in this README assume we are in this `.circleci` directory.

The `Makefile` in this directory generates `./config.yml` in CircleCI 2.0 syntax,
from the tree rooted at `./config/`, which contains files in CircleCI 2.0 or 2.1 syntax.


## Quickstart

The basic workflow is:

- Edit source files in `./config/`
- When you are done, run `make ci-config` to update `./config.yml`
- Commit this entire `.circleci` directory, including that generated file together.
- Run `make ci-verify` to ensure the current `./config.yml` is up to date with the source.

When merging this `.circleci` directory:

- Do not merge the generated `./config.yml` file, instead:
- Merge the source files under `./config/`, and then
- Run `make ci-config` to re-generate the merged `./config.yml`

And that's it, for more detail, read on!


## How does it work, roughly?

CircleCI supports [generating a single config file from many],
using the `$ circleci config pack` command.
It also supports [expanding 2.1 syntax to 2.0 syntax]
using the `$ circleci config process` command.
We use these two commands, stitched together using the `Makefile`
to implement the workflow.

[generating a single config file from many]: https://circleci.com/docs/2.0/local-cli/#packing-a-config
[expanding 2.1 syntax to 2.0 syntax]: https://circleci.com/docs/2.0/local-cli/#processing-a-config


## Prerequisites

You will need the [CircleCI CLI tool] installed and working,
at least version `0.1.5607`.
You can [download this tool directly from GitHub Releases].

```
$ circleci version
0.1.5607+f705856
```

[CircleCI CLI tool]: https://circleci.com/docs/2.0/local-cli/
[download this tool directly from GitHub Releases]: https://github.com/CircleCI-Public/circleci-cli/releases


## Updating the config source

Before making changes, be sure to understand the layout
of the `./config/` file tree, as well as circleci 2.1 syntax.
See the [Syntax and layout] section below.

To update the config, you should edit, add or remove files
in the `./config/` directory,
and then run `make ci-config`.
If that's successful,
you should then commit every `*.yml` file in the tree rooted in this directory.
That is: you should commit both the source under `./config/`
and the generated file `./config.yml` at the same time, in the same commit.
The included git pre-commit hook will help with this.
Do not edit the `./config.yml` file directly, as you will lose your changes
next time `make ci-config` is run.

[Syntax and layout]: #syntax-and-layout


### Verifying `./config.yml`

To check whether or not the current `./config.yml` is up to date with the source
and valid, run `$ make ci-verify`.
Note that `$ make ci-verify` should be run in CI,
in case not everyone has the git pre-commit hook set up correctly.


#### Example shell session

```sh
$ make ci-config
config.yml updated
$ git add -A . # The -A makes sure to include deletions/renames etc.
$ git commit -m "ci: blah blah blah"
Changes detected in .circleci/, running 'make -C .circleci ci-verify'
--> Generated config.yml is up to date!
--> Config file at config.yml is valid.
```


### Syntax and layout

It is important to understand the layout of the config directory.
Read the documentation on [packing a config] for a full understanding
of how multiple YAML files are merged by the circleci CLI tool.

[packing a config]: https://circleci.com/docs/2.0/local-cli/#packing-a-config

Here is an example file tree (with comments added afterwards):

```sh
$ tree .
.
├── Makefile
├── README.md # This file.
├── config # The source code for config.yml is rooted here.
│   ├── @config.yml # Files beginning with @ are treated specially by `circleci config pack`
│   ├── commands # Subdirectories of config become top-level keys.
│   │   └── go_test.yml # Filenames (minus .yml) become top-level keys under
│   │   └── go_build.yml # their parent (in this case "commands").
│ │ # The contents of go_test.yml therefore are placed at: .commands.go_test:
│   └── jobs # jobs also becomes a top-level key under config...
│   ├── build.yml # ...and likewise filenames become keys under their parent.
│   └── test.yml
└── config.yml # The generated file in 2.0 syntax.
```

About those `@` files... Preceding a filename with `@`
indicates to `$ circleci config pack` that the contents of this YAML file
should be at the top-level, rather than underneath a key named after their filename.
This naming convention is unfortunate as it breaks autocompletion in bash,
but there we go.

Loading