Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.

Commit d86c053

Browse files
Initial commit
Signed-off-by: Christopher Maier <[email protected]>
0 parents  commit d86c053

27 files changed

+1007
-0
lines changed

.buildkite/pipeline.verify.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
env:
3+
PANTS_CONFIG_FILES: "['pants.toml', 'pants.ci.toml']"
4+
5+
steps:
6+
- label: ":lint-roller::bash: Lint Shell"
7+
command:
8+
- make lint-shell
9+
10+
- label: ":lint-roller::buildkite: Lint Plugin"
11+
command:
12+
- make lint-plugin
13+
14+
- label: ":bash: Unit Tests"
15+
command:
16+
- make test-shell
17+
18+
- label: ":buildkite: Plugin Tests"
19+
command:
20+
- make test-plugin

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.pants.d
2+
.pids

Makefile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
COMPOSE_USER=$(shell id -u):$(shell id -g)
2+
3+
# Linting
4+
########################################################################
5+
6+
.PHONY: lint
7+
lint: lint-plugin lint-shell
8+
9+
.PHONY: lint-plugin
10+
lint-plugin:
11+
docker-compose run --rm plugin-linter
12+
13+
.PHONY: lint-shell
14+
lint-shell:
15+
./pants lint ::
16+
17+
# Formatting
18+
########################################################################
19+
20+
.PHONY: format
21+
format: format-shell
22+
23+
.PHONY: format-shell
24+
format-shell:
25+
./pants fmt ::
26+
27+
# Testing
28+
########################################################################
29+
30+
.PHONY: test
31+
test: test-plugin test-shell
32+
33+
.PHONY: test-plugin
34+
test-plugin:
35+
docker-compose run --rm plugin-tester
36+
37+
.PHONY: test-shell
38+
test-shell:
39+
./pants test ::
40+
41+
########################################################################
42+
43+
.PHONY: all
44+
all: format lint test

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Grapl Artifacts Buildkite Plugin
2+
3+
Encapsulates logic used in Grapl's release pipelines for
4+
record-keeping around the versions of any artifacts that are
5+
generated.
6+
7+
This is highly specific to how we run our CI/CD pipelines at Grapl; it
8+
is not intended to be broadly generalizable.
9+
10+
## Example
11+
12+
```yml
13+
steps:
14+
- label: ":gear::packer: Convert Packer Manifests"
15+
plugins:
16+
- grapl-security/grapl-artifacts#v0.1.0:
17+
action: convert_packer_manifests
18+
```
19+
20+
```yml
21+
steps:
22+
- label: ":knot: Merge Artifact Files"
23+
plugins:
24+
- grapl-security/grapl-artifacts#v0.1.0:
25+
action: merge_artifact_files
26+
```
27+
28+
## Configuration
29+
30+
### action (required, string)
31+
32+
The name of the plugin action to run; currently supports the following:
33+
- `convert_packer_manifests`
34+
- `merge_artifact_files`
35+
36+
#### `convert_packer_manifests`
37+
38+
Extracts the AMI IDs from one or more Packer [manifest
39+
files](https://www.packer.io/docs/post-processors/manifest) into a
40+
simplified JSON form that we can consume more easily in downstream pipeline
41+
jobs.
42+
43+
In particular, it will take a manifest file like this (call it
44+
`my-ami.packer-manifest.json`):
45+
46+
```json
47+
{
48+
"builds": [
49+
{
50+
"name": "amazon-linux-2-amd64-ami",
51+
"builder_type": "amazon-ebs",
52+
"build_time": 1626818948,
53+
"files": null,
54+
"artifact_id": "us-east-1:ami-aaaaaaaaaaaaaaaaa,us-east-2:ami-bbbbbbbbbbbbbbbbb,us-west-1:ami-ccccccccccccccccc,us-west-2:ami-ddddddddddddddddd",
55+
"packer_run_uuid": "f101f1dd-5fdb-bc9e-b0f0-ee49267bf567",
56+
"custom_data": null
57+
}
58+
],
59+
"last_run_uuid": "f101f1dd-5fdb-bc9e-b0f0-ee49267bf567"
60+
}
61+
```
62+
63+
and turn it into `my-ami-${BUILDKITE_JOB_ID}.grapl-artifacts.json`:
64+
65+
```json
66+
{
67+
"my-ami.us-east-1": "ami-aaaaaaaaaaaaaaaaa",
68+
"my-ami.us-east-2": "ami-bbbbbbbbbbbbbbbbb",
69+
"my-ami.us-west-1": "ami-ccccccccccccccccc",
70+
"my-ami.us-west-2": "ami-ddddddddddddddddd",
71+
}
72+
```
73+
74+
The manifest file _must_ have the extension `.packer-manifest.json`;
75+
the resulting file will be named according to whatever the basename of
76+
the manifest file is.
77+
78+
To generate manifests compatible with this plugin, use HCL like this
79+
in your Packer template:
80+
81+
```hcl
82+
build {
83+
# all your sources and provisioners go here...
84+
85+
post-processor "manifest" {
86+
output = "my-ami.packer-manifest.json"
87+
}
88+
}
89+
```
90+
91+
All files previously uploaded using `buildkite-agent artifact upload`
92+
in the current pipeline and ending in `.packer-manifest.json` will be
93+
processed in this way; one `.grapl-artifacts.json` file per Packer
94+
manifest will be generated and uploaded for access in downstream jobs.
95+
96+
#### `merge_artifact_files`
97+
98+
Takes all `*.grapl-artifacts.json` files that have been previously
99+
uploaded in the current pipeline and merges them all into a single
100+
file for subsequent processing.
101+
102+
Each file is assumed to contain a single, flat JSON object, with
103+
mutually disjoint keys.
104+
105+
The final merged file is called `all_artifacts.json` and is uploaded
106+
for access in downstream jobs.
107+
108+
## Building
109+
110+
Requires `make`, `docker`, and `docker-compose`.
111+
112+
`make all` will run all formatting, linting, and testing, though
113+
finer-grained targets are available.

bin/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
shell_library()

bin/convert_packer_manifests.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
# shellcheck source-path=SCRIPTDIR
6+
source "$(dirname "${BASH_SOURCE[0]}")/../lib/artifacts.sh"
7+
# shellcheck source-path=SCRIPTDIR
8+
source "$(dirname "${BASH_SOURCE[0]}")/../lib/packer_artifacts.sh"
9+
10+
# TODO: Could just use the artifacts plugin for this
11+
download_all_packer_manifests() {
12+
buildkite-agent artifact download "*.${PACKER_MANIFEST_EXTENSION}" .
13+
}
14+
15+
upload_all_grapl_artifacts() {
16+
buildkite-agent artifact upload "*.${ARTIFACTS_FILE_EXTENSION}"
17+
}
18+
19+
download_all_packer_manifests
20+
21+
for packer_manifest_file in *."${PACKER_MANIFEST_EXTENSION}"; do
22+
echo -e "--- Extracting AMI information from ${packer_manifest_file}"
23+
slug="$(name_from_manifest_file "${packer_manifest_file}")"
24+
extract_ami_information "${packer_manifest_file}" > "$(artifacts_file_for "${slug}")"
25+
done
26+
27+
# To keep things simple, we _could_ use the artifacts plugin, or
28+
# artifacts_path key instead of this.
29+
#
30+
# Here, at least, we're keeping all the extension knowledge "in house"
31+
upload_all_grapl_artifacts

bin/merge_artifact_files.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env bash
2+
3+
# Given a series of names of artifact files (i.e., files containing
4+
# flat JSON objects mapping artifact names to versions), retrieve them
5+
# from the Buildkite artifact storage facility, merge them all into a
6+
# single new artifact file, and then upload that for subsequent
7+
# processing.
8+
#
9+
# This will allow this logic to be reused across multiple pipelines,
10+
# regardless of how many artifact files they may generate.
11+
12+
set -euo pipefail
13+
14+
# shellcheck source-path=SCRIPTDIR
15+
source "$(dirname "${BASH_SOURCE[0]}")/../lib/artifacts.sh"
16+
17+
echo "--- :buildkite: Downloading all artifact files"
18+
buildkite-agent artifact download "*.${ARTIFACTS_FILE_EXTENSION}" .
19+
20+
merge_artifact_files > "${ALL_ARTIFACTS_JSON_FILE}"
21+
22+
echo "--- :buildkite: Uploading ${ALL_ARTIFACTS_JSON_FILE} file"
23+
buildkite-agent artifact upload "${ALL_ARTIFACTS_JSON_FILE}"
24+
# This artifact then gets picked up by the "Create new release candidate" step in Buildkite

docker-compose.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
version: "3.8"
2+
3+
x-common-variables:
4+
read-only-workdir: &read-only-workdir
5+
type: bind
6+
source: .
7+
target: /workdir
8+
read_only: true
9+
read-write-workdir: &read-write-workdir
10+
type: bind
11+
source: .
12+
target: /workdir
13+
read_only: false
14+
read-only-plugin: &read-only-plugin
15+
# Buildkite containers assume you mount into /plugin
16+
type: bind
17+
source: .
18+
target: /plugin
19+
read_only: true
20+
21+
services:
22+
plugin-tester:
23+
image: buildkite/plugin-tester:latest # the only available tag
24+
volumes:
25+
- *read-only-plugin
26+
27+
plugin-linter:
28+
image: buildkite/plugin-linter:latest # the only available tag
29+
command: ["--id", "grapl-security/grapl-artifacts"]
30+
volumes:
31+
- *read-only-plugin

fixtures/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
resources(
2+
sources=["*.json"]
3+
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"multiple-runs-single-region.us-east-1": "ami-aaaaaaaaaaaaaaaaa"
3+
}

0 commit comments

Comments
 (0)