diff --git a/.editorconfig b/.editorconfig index 1891d60..3f1839c 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Martin Donath +# Copyright (c) 2017-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..8e67ec9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,26 @@ +## Description + +[Description of the bug] + +### Expected behavior + +[What you expected to happen] + +### Actual behavior + +[What is actually happening] + +### Steps to reproduce the bug + +1. [First step] +2. [Second step] +3. [and so on...] + +### Package versions + +* terraform-aws-github-ci: `...` +* terraform: `...` + +### System information + +* OS: [The operating system you're running] diff --git a/.gitignore b/.gitignore index d5d5100..3c76c1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Martin Donath +# Copyright (c) 2017-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -28,14 +28,3 @@ # Terraform state *.tfstate *.tfstate.backup - -# NPM -node_modules -npm-debug.log* - -# Distribution files except *.zip -**/dist/**/*.js* - -# Coverage reports -.nyc_output -coverage diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 616bdbb..0000000 --- a/.travis.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -language: node_js -sudo: false - -# Node.js version -node_js: 8 - -# Limit clone depth to 5, to speed up build -git: - depth: 5 - -# Cache dependencies -cache: - directories: - - node_modules - -# Install dependencies -install: - - curl -fSL "https://releases.hashicorp.com/terraform/0.11.1/terraform_0.11.1_linux_amd64.zip" -o terraform.zip - - sudo unzip terraform.zip -d /opt/terraform - - sudo ln -s /opt/terraform/terraform /usr/bin/terraform - - rm -f terraform.zip - -# Perform build and release -script: - - make lint - - make build diff --git a/CHANGELOG b/CHANGELOG index 4946bc0..999eee5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,38 @@ +terraform-aws-github-ci-1.0.0 (2018-12-26) + + * Added support for CodeBuild environment variables + * Removed custom Lambda functions in favor of native CodeBuild functionality + * Officially deprecated the project - this should be the last release + +terraform-aws-github-ci-0.5.4 (2018-08-18) + + * Fixed GitHub webhook creation by temporarily downgrading provider to < 1 + +terraform-aws-github-ci-0.5.3 (2018-06-04) + + * Added support for privileged mode + +terraform-aws-github-ci-0.5.2 (2018-05-16) + + * Fixed indeterministic environment variable mapping + +terraform-aws-github-ci-0.5.1 (2018-04-12) + + * Fixed broken update for build status badges + +terraform-aws-github-ci-0.5.0 (2018-04-12) + + * Added support to configure build specification file location + * Fixed #10: Webhook fails due to invalid reference + +terraform-aws-github-ci-0.4.1 (2018-04-01) + + * Fixed #5: Removed default for namespace variable + +terraform-aws-github-ci-0.4.0 (2018-03-30) + + * Refactored complete code base into TypeScript + terraform-aws-github-ci-0.3.0 (2017-12-03) * Fixed compatibility errors with Terraform 0.11 @@ -10,7 +45,7 @@ terraform-aws-github-ci-0.2.0 (2017-12-02) terraform-aws-github-ci-0.1.1 (2017-11-15) - * Fixed missing lambda distribution files + * Fixed missing distribution files * Fixed invalid source location for initial status badge terraform-aws-github-ci-0.1.0 (2017-11-15) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0244e46..ae00b14 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ Please consider what kind of change it is: * For a **major feature**, first open an issue and outline your proposal so that it can be discussed. This will also allow us to better coordinate our - efforts, prevent duplication of work, and help you to craft the change so + efforts, prevent duplication of work and help you to craft the change so that it is successfully accepted into the project. * **Small features and bugs** can be crafted and directly submitted as a pull diff --git a/LICENSE b/LICENSE index 01353d0..b6ddf72 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017 Martin Donath +Copyright (c) 2017-2018 Martin Donath Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/Makefile b/Makefile deleted file mode 100644 index efbd04d..0000000 --- a/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -all: lint | build - -# ----------------------------------------------------------------------------- -# Prerequisites -# ----------------------------------------------------------------------------- - -# Install dependencies -.terraform: - terraform init - -# ----------------------------------------------------------------------------- -# Rules -# ----------------------------------------------------------------------------- - -# Build distribution files -build: .terraform - make -C data/lambda build - -# Lint source files -lint: .terraform - terraform validate -check-variables=false - make -C data/lambda lint - -# ----------------------------------------------------------------------------- - -# Special targets -.PHONY: .FORCE build lint -.FORCE: diff --git a/README.md b/README.md index a17ffda..da84456 100644 --- a/README.md +++ b/README.md @@ -1,88 +1,60 @@ -[![Travis][travis-image]][travis-link] -[![Gitter][gitter-image]][gitter-link] -[![GitHub][github-image]][github-link] +![Status][status-image] - [travis-image]: https://travis-ci.org/squidfunk/terraform-aws-github-ci.svg?branch=master - [travis-link]: https://travis-ci.org/squidfunk/terraform-aws-github-ci - [gitter-image]: https://badges.gitter.im/squidfunk/terraform-aws-github-ci.svg - [gitter-link]: https://gitter.im/squidfunk/terraform-aws-github-ci - [github-image]: https://img.shields.io/github/release/squidfunk/terraform-aws-github-ci.svg - [github-link]: https://github.com/squidfunk/terraform-aws-github-ci/releases + [status-image]: https://img.shields.io/badge/status-deprecated-red.svg # Terraform AWS GitHub CI -A Terraform module to setup a GitHub CI server with pull request and build -status support using AWS CodeBuild. +> This project has been deprecated, as AWS CodeBuild now natively supports +> automatic builds on new commits and reports status back to GitHub. However, +> it may serve as a template for anyone trying to get AWS CodeBuild working. -## Architecture - -![Architecture][1] - - [1]: assets/architecture.png - -This module registers a GitHub webhook which is triggered for `push` and -`pull_request` events and starts the build for the respective branch. All -builds run in parallel. The build progress and status for a respective commit -is reported back to GitHub. Furthermore, a badge for the status of `master` is -generated and hosted on S3. - -### Cost - -Building with this CI server is unbelievably cheap - you only pay what you use. -Pricings starts at 0,5 ct per build minute, and AWS CodeBuild offers 100 free -build minutes every month. The price for the other services (Lambda, SNS, S3 -and CloudWatch) are neglectable and should only add a few cents to your monthly -bill. Compare that to the $69 that services like Travis cost every month, -regardless of how much you use them. +A Terraform module to setup a serverless GitHub CI build environment with pull +request and build status support using AWS CodeBuild. ## Usage -### Standalone - You need an AWS and GitHub account and a repository you want to be built. The -repository must specify a `buildspec.yml` which is documented [here][2]. If you -want to get started straight away and have no experience in Terraform, just -[set up your AWS credentials][3], [install Terraform][4], clone the repository -and apply the configuration from the root folder with: - -``` bash -terraform apply \ - -var github_owner= \ - -var github_repository= \ - -var github_oauth_token= -``` - -Now, when you push to `master`, or create a pull request, CodeBuild will -automatically build the commit and report the status back to GitHub. +repository must specify a `buildspec.yml` which is documented [here][2]. First, +you need to go to the [CodeBuild][3] dashboard in your region, manually create +a new project and choose GitHub as the **Source provider**, allowing AWS to +authorize your account. Next, [set up your AWS credentials][4] and +[install Terraform][5] if you haven't got it available already. -### Module + [2]: http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.htm + [3]: https://console.aws.amazon.com/codebuild/home + [4]: http://docs.aws.amazon.com/de_de/cli/latest/userguide/cli-chap-getting-started.html + [5]: https://www.terraform.io/downloads.html -Include and configure this module in your Terraform configuration: +Next, add the following module to your Terraform configuration and apply it: ``` hcl module "github_ci" { source = "github.com/squidfunk/terraform-aws-github-ci" - version = "0.2.0" + version = "1.0.0" + namespace = "" github_owner = "" github_repository = "" github_oauth_token = "" } ``` -All resources (including the S3 bucket) are created through this module. After -applying your configuration, a status badge can be added to your project's -README using the `codebuild_badge_url` and `codebuild_url` outputs printed to -the terminal. +All resources are prefixed with the value specified as `namespace`. If the S3 +bucket name (see below) is not explicitly set, it's set to the given `namespace` +which means there must not already exist an S3 bucket with the same name. This +is a common source of error. -**Note**: the OAuth-token is currently mandatory, because Terraform doesn't -support conditional blocks inside resources. However, this feature is currently -[being implemented][5] and should be released shortly. +Now, when you push to `master`, or create a pull request, CodeBuild will +automatically build the commit and report the status back to GitHub. A status +badge can be added to your project's README using the `codebuild_badge_url` and +`codebuild_url` outputs printed to the terminal. - [2]: http://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.htm - [3]: http://docs.aws.amazon.com/de_de/cli/latest/userguide/cli-chap-getting-started.html - [4]: https://www.terraform.io/downloads.html - [5]: https://github.com/hashicorp/terraform/issues/7034 +**Note**: the OAuth-token is currently mandatory (also for public repositories), +because Terraform doesn't support conditional blocks inside resources. However, +this feature is currently [being implemented][6] and should be released shortly. +If you want to omit it, create your own CodeBuild project [see below][7]. + + [6]: https://github.com/hashicorp/terraform/issues/7034 ## Configuration @@ -90,6 +62,11 @@ The following variables can be configured: ### Required +#### `namespace` + +- **Description**: AWS resource namespace/prefix (lowercase alphanumeric) +- **Default**: `none` + #### `github_owner` - **Description**: GitHub repository owner @@ -107,85 +84,66 @@ The following variables can be configured: ### Optional -#### `github_reporter` - -- **Description**: GitHub commit status reporter -- **Default**: `"AWS CodeBuild"` - -#### `codebuild_project` - -- **Description**: CodeBuild project name (won't create [default project][6]) -- **Default**: `""` -- **Conflicts with**: `codebuild_compute_type`, `codebuild_image` - - [6]: #default-project - #### `codebuild_compute_type` - **Description**: Compute resources used by the build - **Default**: `"BUILD_GENERAL1_SMALL"` -- **Conflicts with**: `codebuild_project` #### `codebuild_image` - **Description**: Base image for provisioning (AWS Registry, Docker) - **Default**: `"aws/codebuild/ubuntu-base:14.04"` -- **Conflicts with**: `codebuild_project` + +#### `codebuild_buildspec` + +- **Description**: Build specification file location ([file format][2]) +- **Default**: `"buildspec.yml"` (at repository root) + +#### `codebuild_privileged_mode` + +- **Description**: If set to true, enables running the Docker daemon inside a + Docker container. +- **Default**: `false` #### `codebuild_bucket` - **Description**: S3 bucket to store status badge and artifacts -- **Default**: `"github-ci"` (equal to namespace) +- **Default**: `"${var.namespace}"` (equal to namespace) -#### `namespace` +#### `codebuild_environment_variables` -- **Description**: AWS resource namespace/prefix -- **Default**: `"github-ci"` +- **Description**: CodeBuild environment variables +- **Default**: [] -### Default project +#### `codebuild_badge_enabled` -If you need more control over the CodeBuild project, you can pass the name of -an external CodeBuild project in this variable. This will avoid the creation -of the default project which has the following configuration: +- **Description**: Generates a publicly-accessible URL for the projects build + badge +- **Default**: `true` -``` hcl -resource "aws_codebuild_project" "codebuild" { - name = "${var.github_repository}" - - build_timeout = "5" - service_role = "${aws_iam_role.codebuild.arn}" - - source { - type = "GITHUB" - location = "..." - - auth { - type = "OAUTH" - resource = "${var.github_oauth_token}" - } - } - - environment { - compute_type = "${var.codebuild_compute_type}" - type = "LINUX_CONTAINER" - image = "${var.codebuild_image}" - } - - artifacts { - type = "S3" - location = "${var.codebuild_bucket}" - name = "${var.github_repository}" - namespace_type = "BUILD_ID" - packaging = "ZIP" - } -} -``` +### Outputs + +The following outputs are exported: + +#### `codebuild_service_role_name` + +- **Description**: CodeBuild service role name + +#### `codebuild_service_role_arn` + +- **Description**: CodeBuild service role ARN + +#### `codebuild_bucket` + +- **Description**: CodeBuild artifacts bucket name + +#### `codebuild_badge_url` + +- **Description**: CodeBuild status badge URL + +#### `codebuild_url` -The corresponding service role and the bucket are always created and exported -as `codebuild_service_role_arn`, `codebuild_service_role_name` and -`codebuild_bucket`. You can reference them in your CodeBuild resource -definition, e.g. to attach further policies, and thus avoid the creation of -your own service role and bucket. +- **Description**: CodeBuild project URL ## Limitations @@ -193,15 +151,15 @@ This module first integrated with AWS CodePipeline but switched to CodeBuild, because the former is heavily opinionated in terms of configuration and much, much slower. For this reason, the deployment of your build artifacts must be handled by another module which can be triggered when the build artifacts are -written to S3, most likely by [using a Lambda function][7]. +written to S3, most likely by [using a Lambda function][8]. - [7]: http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html + [8]: http://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html ## License **MIT License** -Copyright (c) 2017 Martin Donath +Copyright (c) 2017-2018 Martin Donath Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to diff --git a/assets/architecture.png b/assets/architecture.png deleted file mode 100644 index 8bc71d4..0000000 Binary files a/assets/architecture.png and /dev/null differ diff --git a/data/cloudwatch/rules/codebuild.json b/data/cloudwatch/rules/codebuild.json deleted file mode 100644 index 498f76b..0000000 --- a/data/cloudwatch/rules/codebuild.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "source": [ - "aws.codebuild" - ], - "detail-type": [ - "CodeBuild Build Phase Change" - ], - "detail": { - "completed-phase": [ - "SUBMITTED", - "INSTALL", - "BUILD", - "FINALIZING" - ], - "completed-phase-status": [ - "SUCCEEDED", - "STOPPED", - "FAILED", - "FAULT", - "TIMED_OUT" - ] - } -} diff --git a/data/iam/policies/assume-role/lambda.json b/data/iam/policies/assume-role/lambda.json deleted file mode 100644 index defdc77..0000000 --- a/data/iam/policies/assume-role/lambda.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": { - "Effect": "Allow", - "Principal": { - "Service": "lambda.amazonaws.com" - }, - "Action": "sts:AssumeRole" - } -} diff --git a/data/iam/policies/lambda.json b/data/iam/policies/lambda.json deleted file mode 100644 index 7542a02..0000000 --- a/data/iam/policies/lambda.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "logs:CreateLogGroup", - "logs:CreateLogStream", - "logs:PutLogEvents" - ], - "Resource": "arn:aws:logs:*:*:*" - }, - { - "Effect": "Allow", - "Action": [ - "s3:PutObject", - "s3:PutObjectAcl" - ], - "Resource": [ - "${bucket}/*", - "${bucket}" - ] - }, - { - "Effect": "Allow", - "Action": [ - "codebuild:StartBuild" - ], - "Resource": "*" - } - ] -} diff --git a/data/iam/policies/webhook.json b/data/iam/policies/webhook.json deleted file mode 100644 index c29a0d8..0000000 --- a/data/iam/policies/webhook.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "sns:Publish" - ], - "Resource": "${topic}" - } - ] -} diff --git a/data/lambda/.babelrc b/data/lambda/.babelrc deleted file mode 100644 index 0988b7b..0000000 --- a/data/lambda/.babelrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "presets": [ - ["env", { - "targets": { - "node": "6.10" - } - }] - ], - "env": { - "test": { - "presets": [ - ["env", { "modules": "umd" }] - ], - "plugins": [ - "istanbul" - ] - } - } -} diff --git a/data/lambda/.eslintignore b/data/lambda/.eslintignore deleted file mode 100644 index 7ba9434..0000000 --- a/data/lambda/.eslintignore +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# Distribution files -/dist diff --git a/data/lambda/.eslintrc b/data/lambda/.eslintrc deleted file mode 100644 index ed81d6d..0000000 --- a/data/lambda/.eslintrc +++ /dev/null @@ -1,195 +0,0 @@ -{ - "extends": "eslint:recommended", - "env": { - "browser": true, - "es6": true, - "node": true - }, - "parser": "babel-eslint", - "parserOptions": { - "ecmaVersion": 6, - "ecmaFeatures": { - "arrowFunctions": true, - "binaryLiterals": true, - "blockBindings": true, - "classes": true, - "defaultParams": true, - "destructuring": true, - "forOf": true, - "generators": true, - "globalReturn": true, - "modules": true, - "objectLiteralComputedProperties": true, - "objectLiteralDuplicateProperties": true, - "objectLiteralShorthandMethods": true, - "objectLiteralShorthandProperties": true, - "octalLiterals": true, - "regexUFlag": true, - "regexYFlag": true, - "spread": true, - "superInFunctions": false, - "templateStrings": true, - "unicodeCodePointEscapes": true - }, - "impliedStrict": true, - "sourceType": "module" - }, - "plugins": [], - "rules": { - "array-callback-return": 2, - "array-bracket-spacing": 2, - "arrow-parens": [2, "as-needed"], - "arrow-spacing": 2, - "block-scoped-var": 2, - "block-spacing": 2, - "brace-style": 2, - "camelcase": [2, { - "properties": "always" - }], - "comma-dangle": [2, "never"], - "comma-style": [2, "last"], - "complexity": 2, - "computed-property-spacing": 2, - "consistent-this": 2, - "dot-notation": 2, - "eol-last": 2, - "eqeqeq": 2, - "func-call-spacing": 2, - "func-names": [2, "never"], - "func-style": 2, - "generator-star-spacing": 2, - "indent": [2, 2, { - "FunctionDeclaration": { - "body": 1, - "parameters": 2 - }, - "FunctionExpression": { - "body": 1, - "parameters": 2 - }, - "MemberExpression": 1, - "VariableDeclarator": { - "var": 2, - "let": 2, - "const": 3 - }, - "SwitchCase": 1 - }], - "init-declarations": 2, - "key-spacing": 2, - "keyword-spacing": 2, - "linebreak-style": 2, - "lines-around-comment": 2, - "lines-around-directive": 2, - "max-depth": 2, - "max-len": [1, { - "ignorePattern": "\/\/ TODO" - }], - "max-nested-callbacks": 2, - "max-params": 2, - "max-statements-per-line": 2, - "new-cap": 2, - "newline-per-chained-call": 2, - "no-array-constructor": 2, - "no-alert": 2, - "no-caller": 2, - "no-confusing-arrow": [2, { - "allowParens": false - }], - "no-console": 1, - "no-duplicate-imports": 2, - "no-eq-null": 2, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-floating-decimal": 2, - "no-global-assign": 2, - "no-invalid-this": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-multiple-empty-lines": [1, { - "max": 1 - }], - "no-nested-ternary": 2, - "no-new": 0, - "no-new-object": 2, - "no-param-reassign": 2, - "no-prototype-builtins": 2, - "no-shadow": 2, - "no-tabs": 2, - "no-template-curly-in-string": 2, - "no-throw-literal": 2, - "no-trailing-spaces": 2, - "no-undefined": 2, - "no-underscore-dangle": [2, { - "allowAfterThis": true, - "allowAfterSuper": true - }], - "no-unneeded-ternary": 2, - "no-unsafe-negation": 2, - "no-unused-expressions": 2, - "no-unused-vars": 1, - "no-use-before-define": 2, - "no-useless-call": 2, - "no-useless-computed-key": 2, - "no-useless-constructor": 2, - "no-useless-rename": 2, - "no-var": 2, - "no-whitespace-before-property": 2, - "no-with": 2, - "object-curly-spacing": [2, "always"], - "object-shorthand": 2, - "one-var-declaration-per-line": 2, - "operator-assignment": 2, - "prefer-arrow-callback": 2, - "prefer-const": 2, - "prefer-numeric-literals": 2, - "prefer-spread": 2, - "prefer-template": 2, - "quotes": [2, "double"], - "radix": 2, - "require-jsdoc": [1, { - "require": { - "FunctionDeclaration": true, - "MethodDefinition": true, - "ClassDeclaration": false - } - }], - "rest-spread-spacing": 2, - "semi": [2, "never"], - "semi-spacing": 2, - "space-before-function-paren": [2, "never"], - "space-in-parens": 2, - "space-infix-ops": 2, - "space-unary-ops": 2, - "spaced-comment": [2, "always", { - "line": { - "markers": ["/", ":"], - "exceptions": ["-", "+"] - }, - "block": { - "markers": ["!"], - "exceptions": ["*"], - "balanced": true - } - }], - "strict": 2, - "template-curly-spacing": 2, - "unicode-bom": 2, - "valid-jsdoc": [1, { - "prefer": { - "arg": "param", - "argument": "param", - "class": "constructor", - "returns": "return", - "virtual": "abstract" - }, - "requireParamDescription": true, - "requireReturn": false, - "requireReturnDescription": true - }], - "yield-star-spacing": 2 - }, - "root": true -} diff --git a/data/lambda/Makefile b/data/lambda/Makefile deleted file mode 100644 index 748a1b2..0000000 --- a/data/lambda/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -all: clean lint | build - -# ----------------------------------------------------------------------------- -# Prerequisites -# ----------------------------------------------------------------------------- - -# Install dependencies -node_modules: - npm install - -# ----------------------------------------------------------------------------- -# Targets -# ----------------------------------------------------------------------------- - -# Build library for distribution -dist: $(shell find src) .babelrc webpack.config.js - $(shell npm bin)/webpack --env.prod - -# ----------------------------------------------------------------------------- -# Rules -# ----------------------------------------------------------------------------- - -# Build distribution files -build: node_modules dist - -# Clean distribution files -clean: - rm -rf dist - -# Lint source files -lint: node_modules - $(shell npm bin)/eslint --max-warnings 0 . - -# Run unit tests -test: node_modules - $(shell npm bin)/cross-env NODE_ENV=test \ - $(shell npm bin)/nyc --reporter=lcov --reporter=text \ - $(shell npm bin)/babel-node tests/index.js - -# Run unit tests in watch mode -watch: node_modules - $(shell npm bin)/cross-env NODE_ENV=development \ - $(shell npm bin)/nodemon --quiet \ - --watch src --watch tests/unit \ - --exec $(shell npm bin)/babel-node tests/index.js - -# ----------------------------------------------------------------------------- - -# Special targets -.PHONY: .FORCE build clean lint test watch -.FORCE: diff --git a/data/lambda/assets/errored.svg b/data/lambda/assets/errored.svg deleted file mode 100644 index a663b9c..0000000 --- a/data/lambda/assets/errored.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuilderrorederrored \ No newline at end of file diff --git a/data/lambda/assets/failing.svg b/data/lambda/assets/failing.svg deleted file mode 100644 index 843b026..0000000 --- a/data/lambda/assets/failing.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuildfailingfailing \ No newline at end of file diff --git a/data/lambda/assets/passing.svg b/data/lambda/assets/passing.svg deleted file mode 100644 index 87bbae0..0000000 --- a/data/lambda/assets/passing.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuildpassingpassing \ No newline at end of file diff --git a/data/lambda/assets/unknown.svg b/data/lambda/assets/unknown.svg deleted file mode 100644 index a16e0bd..0000000 --- a/data/lambda/assets/unknown.svg +++ /dev/null @@ -1 +0,0 @@ -buildbuildunknownunknown \ No newline at end of file diff --git a/data/lambda/dist/status.zip b/data/lambda/dist/status.zip deleted file mode 100644 index fed41d8..0000000 Binary files a/data/lambda/dist/status.zip and /dev/null differ diff --git a/data/lambda/dist/webhook.zip b/data/lambda/dist/webhook.zip deleted file mode 100644 index b9b66af..0000000 Binary files a/data/lambda/dist/webhook.zip and /dev/null differ diff --git a/data/lambda/package.json b/data/lambda/package.json deleted file mode 100644 index 5e84e5a..0000000 --- a/data/lambda/package.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "terraform-aws-github-ci-data-lambda", - "version": "0.0.0", - "description": "A GitHub CI server using AWS CodeBuild", - "keywords": [], - "homepage": "https://github.com/squidfunk/terraform-aws-github-ci/", - "bugs": { - "url": "https://github.com/squidfunk/terraform-aws-github-ci/", - "email": "martin.donath@squidfunk.com" - }, - "private": true, - "author": { - "name": "Martin Donath", - "email": "martin.donath@squidfunk.com" - }, - "contributors": [], - "repository": { - "type": "git", - "url": "https://github.com/squidfunk/terraform-aws-github-ci.git" - }, - "scripts": { - "build": "make build", - "clean": "make clean", - "lint": "make lint", - "test": "make test", - "watch": "make watch" - }, - "dependencies": { - "github": "^12.0.1" - }, - "devDependencies": { - "archiver": "^2.1.0", - "aws-sdk": "^2.137.0", - "babel-cli": "^6.26.0", - "babel-core": "^6.26.0", - "babel-eslint": "^8.0.1", - "babel-loader": "^7.1.2", - "babel-plugin-istanbul": "^4.1.5", - "babel-plugin-root-import": "^5.1.0", - "babel-preset-env": "^1.6.0", - "binary-loader": "0.0.1", - "cross-env": "^5.0.5", - "eslint": "^4.8.0", - "eslint-plugin-jasmine": "^2.9.1", - "event-hooks-webpack-plugin": "^1.0.0", - "jasmine": "^2.8.0", - "jasmine-spec-reporter": "^4.2.1", - "nodemon": "^1.12.1", - "nyc": "^11.3.0", - "webpack": "^3.8.1", - "webpack-node-externals": "^1.6.0" - } -} diff --git a/data/lambda/src/status.js b/data/lambda/src/status.js deleted file mode 100644 index 7e58e51..0000000 --- a/data/lambda/src/status.js +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2017 Martin Donath - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import AWS from "aws-sdk" -import GitHub from "github" - -import errored from "../assets/errored.svg" -import failing from "../assets/failing.svg" -import passing from "../assets/passing.svg" - -/* ---------------------------------------------------------------------------- - * Constants - * ------------------------------------------------------------------------- */ - -/** - * Status transitions for phases - * - * @type {Object} - */ -const PHASES = { - SUBMITTED: { - SUCCEEDED: ["pending", "Provisioning"] - }, - INSTALL: { - FAILED: ["error", "Provisioning failed"], - SUCCEEDED: ["pending", "Build running"] - }, - BUILD: { - FAILED: ["failure", "Build failed"], - FAULT: ["error", "Build errored"], - STOPPED: ["error", "Build stopped"], - TIMED_OUT: ["error", "Build timed out"] - } -} - -/** - * GitHub state to badge mapping - * - * @const - * @type {Object} - */ -const BADGES = { - success: passing, - failure: failing, - error: errored -} - -/* ---------------------------------------------------------------------------- - * Variables - * ------------------------------------------------------------------------- */ - -/** - * S3 client - * - * @type {AWS.S3} - */ -const s3 = new AWS.S3({ apiVersion: "2006-03-01" }) - -/** - * GitHub client - * - * @type {GitHub} - */ -const github = new GitHub() -if (process.env.GITHUB_OAUTH_TOKEN) - github.authenticate({ - type: "oauth", - token: process.env.GITHUB_OAUTH_TOKEN - }) - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Update commit SHA with pipeline state - * - * @param {Object} event - Event - * @param {Object} context - Context - * @param {Function} cb - Completion callback - */ -export default (event, context, cb) => { - const info = event.detail["additional-information"] - - /* Retrieve commit SHA, owner and repository */ - const sha = info["source-version"] - const [, owner, repo] = /github.com\/([^/]+)\/([^/.]+)/ - .exec(info.source.location) || [] - - /* Resolve phase and state mapping */ - const phase = PHASES[event.detail["completed-phase"]] || {} - let [state, description] = - phase[event.detail["completed-phase-status"]] || [] - - /* Mark build successful in finalizing phase if no errors occured */ - if (event.detail["completed-phase"] === "FINALIZING") - if (!info.phases.find(prev => { - return prev["phase-type"] !== "COMPLETED" && - prev["phase-status"] !== "SUCCEEDED" - })) - [state, description] = ["success", "Build successful"] - - /* Resolve build reference and run URL */ - const ref = info.environment["environment-variables"][0].value - const run = event.detail["build-id"].split(":").pop() - const url = `https://console.aws.amazon.com/codebuild/home?region=${ - process.env.AWS_REGION}#/builds/${repo}:${run}/view/new` - - /* Report current state and phase description, if any */ - if (state && description) { - github.repos.createStatus({ - owner, repo, sha, state, description, - target_url: url, // eslint-disable-line camelcase - context: process.env.GITHUB_REPORTER - }) - - /* Update status badge on S3 */ - .then(() => { - return new Promise((resolve, reject) => { - if (ref === "master" && BADGES[state]) { - s3.putObject({ - Bucket: process.env.CODEBUILD_BUCKET, - Key: `${repo}/status.svg`, - Body: BADGES[state], - ACL: "public-read", - CacheControl: "no-cache, no-store, must-revalidate", - ContentType: "image/svg+xml" - }, err => { - return err - ? reject(err) - : resolve() - }) - } else { - resolve() - } - }) - }) - - /* The event was processed */ - .then(data => cb(null, data)) - - /* An error occurred */ - .catch(cb) - } -} diff --git a/data/lambda/src/webhook.js b/data/lambda/src/webhook.js deleted file mode 100644 index 5c5321e..0000000 --- a/data/lambda/src/webhook.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2017 Martin Donath - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import AWS from "aws-sdk" -import GitHub from "github" - -/* ---------------------------------------------------------------------------- - * Variables - * ------------------------------------------------------------------------- */ - -/** - * Build manager - * - * @type {AWS.CodeBuild} - */ -const codebuild = new AWS.CodeBuild({ apiVersion: "2016-10-06" }) - -/** - * GitHub client - * - * @type {GitHub} - */ -const github = new GitHub() -if (process.env.GITHUB_OAUTH_TOKEN) - github.authenticate({ - type: "oauth", - token: process.env.GITHUB_OAUTH_TOKEN - }) - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Run build on source change - * - * @param {Object} event - Event - * @param {Object} context - Context - * @param {Function} cb - Completion callback - */ -export default (event, context, cb) => { - event.Records.reduce((promise, record) => { - const type = record.Sns.MessageAttributes["X-Github-Event"].Value - const message = JSON.parse(record.Sns.Message) - - /* Retrieve commit SHA and reference */ - const [sha, ref] = type === "pull_request" - ? [message.pull_request.head.sha, message.pull_request.head.ref] - : [message.after, message.ref.replace("refs/heads/", "")] - - /* Return promise chain */ - return promise.then(() => { - - /* Start build for open pull request or master branch */ - if (type === "pull_request" && message.pull_request.state !== "closed" || - type === "push" && ref === "master") { - return new Promise((resolve, reject) => { - codebuild.startBuild({ - projectName: message.repository.name, - sourceVersion: sha, - environmentVariablesOverride: [ - { - name: "GIT_BRANCH", - value: ref - }, - { - name: "GIT_COMMIT", - value: sha - } - ] - }, err => { - return err - ? reject(err) - : resolve() - }) - }) - - /* Update commit SHA with pipeline state */ - .then(() => { - return github.repos.createStatus({ - owner: message.repository.owner.login, - repo: message.repository.name, - sha, - state: "pending", - context: process.env.GITHUB_REPORTER, - description: "Waiting for status to be reported" - }) - }) - } - }) - }, Promise.resolve()) - - /* The event was processed */ - .then(data => cb(null, data)) - - /* An error occurred */ - .catch(cb) -} diff --git a/data/lambda/webpack.config.js b/data/lambda/webpack.config.js deleted file mode 100644 index 41fa43e..0000000 --- a/data/lambda/webpack.config.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2017 Martin Donath - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -const archiver = require("archiver") -const externals = require("webpack-node-externals") -const fs = require("fs") -const path = require("path") - -const EventHooksPlugin = require("event-hooks-webpack-plugin") - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Resolve module dependencies recursively - * - * @param {string} module - Module path - * - * @return {Array} Paths of dependent modules - */ -const resolve = module => { - const metadata = require(path.resolve(module, "package.json")) - return Object.keys(metadata.dependencies || {}).reduce( - (dependencies, name) => { - const dependency = path.resolve([module, __dirname].find(base => { - return fs.existsSync(path.resolve(base, "node_modules", name)) - }), "node_modules", name) - return [...dependencies, dependency, ...resolve(dependency)] - }, []) -} - -/** - * Automatically resolve entrypoints - * - * @param {string} directory Directory - * - * @return {Object} Entrypoints - */ -const entry = directory => { - return fs.readdirSync(directory).reduce((entrypoints, file) => { - if (fs.statSync(`${directory}/${file}`).isDirectory()) { - return { ...entrypoints, ...entry(`${directory}/${file}`) } - } else if (file.match(/\.js$/)) { - const [, name] = /^(.*?)\.js$/.exec(path.relative( - path.resolve(__dirname, "src"), `${directory}/${file}` - )) - entrypoints[name] = path.resolve(__dirname, "src", `${name}.js`) - } - return entrypoints - }, {}) -} - -/* ---------------------------------------------------------------------------- - * Configuration - * ------------------------------------------------------------------------- */ - -module.exports = { - target: "node", - - /* Entrypoints */ - entry: entry(path.resolve(__dirname, "src")), - - /* Loaders */ - module: { - rules: [ - { - test: /\.js$/, - use: "babel-loader", - exclude: /\/node_modules\// - }, - { - test: /\.svg$/, - use: "binary-loader" - } - ] - }, - - /* Output */ - output: { - filename: "[name]/index.js", - path: path.join(__dirname, "dist"), - libraryTarget: "commonjs2" - }, - - /* Plugins */ - plugins: [ - - /* Post-compilation hook to bundle sources with dependencies */ - new EventHooksPlugin({ - done: stats => { - Object.keys(stats.compilation.entrypoints).forEach(name => { - const entrypoint = stats.compilation.entrypoints[name] - entrypoint.chunks.forEach(chunk => { - - /* Create archive for each entrypoint */ - const archive = archiver("zip", { zlib: { level: 9 } }) - const zipfile = fs.createWriteStream( - path.join(__dirname, "dist", `${name}.zip`)) - - /* Iterate modules and include into archive if external */ - chunk.forEachModule(module => { - module.dependencies.forEach(dependency => { - - /* Bundle all non-native modules, except aws-sdk */ - if (dependency.request && dependency.request !== "aws-sdk" && - dependency.request.match(/^[^.]/)) { - const external = path.resolve( - __dirname, "node_modules", dependency.request) - if (fs.existsSync(external)) { - archive.directory(external, - path.join("node_modules", dependency.request)) - - /* Bundle nested dependencies */ - resolve(external).forEach(subexternal => { - archive.directory(subexternal, - path.relative(__dirname, subexternal)) - }) - } - } - }) - }) - - /* Append compiled sources to archive */ - archive.directory(path.resolve(__dirname, "dist", name), false) - - /* Finalize and write archive */ - archive.pipe(zipfile) - archive.finalize() - }) - }) - } - }) - ], - - /* External modules */ - externals: [ - externals() - ], - - /* Module resolver */ - resolve: { - modules: [ - path.resolve(__dirname, "node_modules") - ], - extensions: [".js"] - } -} diff --git a/data/iam/policies/assume-role/codebuild.json b/iam/policies/assume-role/codebuild.json similarity index 78% rename from data/iam/policies/assume-role/codebuild.json rename to iam/policies/assume-role/codebuild.json index a7442f4..7e220c7 100644 --- a/data/iam/policies/assume-role/codebuild.json +++ b/iam/policies/assume-role/codebuild.json @@ -2,9 +2,9 @@ "Version": "2012-10-17", "Statement": { "Effect": "Allow", + "Action": "sts:AssumeRole", "Principal": { "Service": "codebuild.amazonaws.com" - }, - "Action": "sts:AssumeRole" + } } } diff --git a/data/iam/policies/codebuild.json b/iam/policies/codebuild.json similarity index 86% rename from data/iam/policies/codebuild.json rename to iam/policies/codebuild.json index a34928b..8adfdb9 100644 --- a/data/iam/policies/codebuild.json +++ b/iam/policies/codebuild.json @@ -19,8 +19,8 @@ "s3:PutObject" ], "Resource": [ - "${bucket}/*", - "${bucket}" + "arn:aws:s3:::${bucket}/*", + "arn:aws:s3:::${bucket}" ] } ] diff --git a/main.tf b/main.tf index 2fac5a1..76b5327 100644 --- a/main.tf +++ b/main.tf @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Martin Donath +# Copyright (c) 2017-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -19,13 +19,11 @@ # IN THE SOFTWARE. # ----------------------------------------------------------------------------- -# Data: Credentials +# Data: General # ----------------------------------------------------------------------------- # data.aws_region._ -data "aws_region" "_" { - current = true -} +data "aws_region" "_" {} # ----------------------------------------------------------------------------- # Data: GitHub @@ -47,10 +45,10 @@ data "template_file" "codebuild_source_location" { # data.template_file.codebuild_iam_policy.rendered data "template_file" "codebuild_iam_policy" { - template = "${file("${path.module}/data/iam/policies/codebuild.json")}" + template = "${file("${path.module}/iam/policies/codebuild.json")}" vars { - bucket = "${aws_s3_bucket.codebuild.arn}" + bucket = "${aws_s3_bucket._.bucket}" } } @@ -64,7 +62,7 @@ resource "aws_iam_role" "codebuild" { path = "/${var.namespace}/codebuild/" assume_role_policy = "${ - file("${path.module}/data/iam/policies/assume-role/codebuild.json") + file("${path.module}/iam/policies/assume-role/codebuild.json") }" } @@ -81,50 +79,35 @@ resource "aws_iam_policy_attachment" "codebuild" { name = "${var.namespace}-codebuild" policy_arn = "${aws_iam_policy.codebuild.arn}" - roles = ["${aws_iam_role.codebuild.id}"] + roles = ["${aws_iam_role.codebuild.name}"] } # ----------------------------------------------------------------------------- # Resources: S3 # ----------------------------------------------------------------------------- -# aws_s3_bucket.codebuild -resource "aws_s3_bucket" "codebuild" { +# aws_s3_bucket._ +resource "aws_s3_bucket" "_" { bucket = "${coalesce(var.codebuild_bucket, var.namespace)}" acl = "private" } -# aws_s3_bucket_object.codebuild -resource "aws_s3_bucket_object" "codebuild" { - bucket = "${aws_s3_bucket.codebuild.bucket}" - key = "${var.github_repository}/status.svg" - source = "${path.module}/data/lambda/assets/unknown.svg" - acl = "public-read" - cache_control = "no-cache, no-store, must-revalidate" - content_type = "image/svg+xml" - - # Ignore, if there already is a status - lifecycle { - ignore_changes = ["*"] - } -} - # ----------------------------------------------------------------------------- # Resources: CodeBuild # ----------------------------------------------------------------------------- -# aws_codebuild_project.codebuild -resource "aws_codebuild_project" "codebuild" { - count = "${length(var.codebuild_project) == 0 ? 1 : 0}" - +# aws_codebuild_project._ +resource "aws_codebuild_project" "_" { name = "${var.github_repository}" build_timeout = "5" service_role = "${aws_iam_role.codebuild.arn}" + badge_enabled = "${var.codebuild_badge_enabled}" source { - type = "GITHUB" - location = "${data.template_file.codebuild_source_location.rendered}" + type = "GITHUB" + location = "${data.template_file.codebuild_source_location.rendered}" + buildspec = "${var.codebuild_buildspec}" auth { type = "OAUTH" @@ -133,48 +116,23 @@ resource "aws_codebuild_project" "codebuild" { } environment { - compute_type = "${var.codebuild_compute_type}" - type = "LINUX_CONTAINER" - image = "${var.codebuild_image}" + compute_type = "${var.codebuild_compute_type}" + type = "LINUX_CONTAINER" + image = "${var.codebuild_image}" + privileged_mode = "${var.codebuild_privileged_mode}" + environment_variable = "${var.codebuild_environment_variables}" } artifacts { type = "S3" - location = "${aws_s3_bucket.codebuild.bucket}" + location = "${aws_s3_bucket._.bucket}" name = "${var.github_repository}" namespace_type = "BUILD_ID" packaging = "ZIP" } } -# ----------------------------------------------------------------------------- -# Modules -# ----------------------------------------------------------------------------- - -# module.webhook -module "webhook" { - source = "./modules/webhook" - - namespace = "${var.namespace}" - - github_owner = "${var.github_owner}" - github_repository = "${var.github_repository}" - github_oauth_token = "${var.github_oauth_token}" - github_reporter = "${var.github_reporter}" - - bucket = "${aws_s3_bucket.codebuild.bucket}" -} - -# module.status -module "status" { - source = "./modules/status" - - namespace = "${var.namespace}" - - github_owner = "${var.github_owner}" - github_repository = "${var.github_repository}" - github_oauth_token = "${var.github_oauth_token}" - github_reporter = "${var.github_reporter}" - - bucket = "${aws_s3_bucket.codebuild.bucket}" +# aws_codebuild_webhook._ +resource "aws_codebuild_webhook" "_" { + project_name = "${aws_codebuild_project._.name}" } diff --git a/modules/status/main.tf b/modules/status/main.tf deleted file mode 100644 index 87dd220..0000000 --- a/modules/status/main.tf +++ /dev/null @@ -1,116 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# ----------------------------------------------------------------------------- -# Data: IAM -# ----------------------------------------------------------------------------- - -# data.template_file.lambda_iam_policy.rendered -data "template_file" "lambda_iam_policy" { - template = "${file("${path.module}/../../data/iam/policies/lambda.json")}" - - vars { - bucket = "${var.bucket}" - } -} - -# ----------------------------------------------------------------------------- -# Resources: IAM -# ----------------------------------------------------------------------------- - -# aws_iam_role.lambda -resource "aws_iam_role" "lambda" { - name = "${var.namespace}-lambda-status" - path = "/${var.namespace}/lambda/" - - assume_role_policy = "${ - file("${path.module}/../../data/iam/policies/assume-role/lambda.json") - }" -} - -# aws_iam_policy.lambda -resource "aws_iam_policy" "lambda" { - name = "${var.namespace}-lambda-status" - path = "/${var.namespace}/lambda/" - - policy = "${data.template_file.lambda_iam_policy.rendered}" -} - -# aws_iam_policy_attachment.lambda -resource "aws_iam_policy_attachment" "lambda" { - name = "${var.namespace}-lambda-status" - - policy_arn = "${aws_iam_policy.lambda.arn}" - roles = ["${aws_iam_role.lambda.id}"] -} - -# ----------------------------------------------------------------------------- -# Resources: CloudWatch -# ----------------------------------------------------------------------------- - -# aws_cloudwatch_event_rule._ -resource "aws_cloudwatch_event_rule" "_" { - name = "${var.namespace}-status" - - event_pattern = "${ - file("${path.module}/../../data/cloudwatch/rules/codebuild.json") - }" -} - -# aws_cloudwatch_event_target._ -resource "aws_cloudwatch_event_target" "_" { - rule = "${aws_cloudwatch_event_rule._.name}" - arn = "${aws_lambda_function._.arn}" -} - -# ----------------------------------------------------------------------------- -# Resources: Lambda -# ----------------------------------------------------------------------------- - -# aws_lambda_function._ -resource "aws_lambda_function" "_" { - function_name = "${var.namespace}-status" - role = "${aws_iam_role.lambda.arn}" - runtime = "nodejs6.10" - filename = "${path.module}/../../data/lambda/dist/status.zip" - handler = "index.default" - timeout = 10 - - source_code_hash = "${ - base64sha256(file("${path.module}/../../data/lambda/dist/status.zip")) - }" - - environment { - variables = { - GITHUB_OAUTH_TOKEN = "${var.github_oauth_token}" - GITHUB_REPORTER = "${var.github_reporter}" - CODEBUILD_BUCKET = "${var.bucket}" - } - } -} - -# aws_lambda_permission._ -resource "aws_lambda_permission" "_" { - statement_id = "AllowExecutionFromCloudWatch" - action = "lambda:InvokeFunction" - function_name = "${aws_lambda_function._.arn}" - principal = "events.amazonaws.com" - source_arn = "${aws_cloudwatch_event_rule._.arn}" -} diff --git a/modules/status/variables.tf b/modules/status/variables.tf deleted file mode 100644 index 1e44ecf..0000000 --- a/modules/status/variables.tf +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# ----------------------------------------------------------------------------- -# Variables: General -# ----------------------------------------------------------------------------- - -# var.namespace -variable "namespace" { - description = "AWS resource namespace/prefix" -} - -# ----------------------------------------------------------------------------- -# Variables: GitHub -# ----------------------------------------------------------------------------- - -# var.github_owner -variable "github_owner" { - description = "GitHub repository owner" -} - -# var.github_repository -variable "github_repository" { - description = "GitHub repository name" -} - -# var.github_oauth_token -variable "github_oauth_token" { - description = "GitHub OAuth token for repository access" -} - -# var.github_reporter -variable "github_reporter" { - description = "GitHub commit status reporter" -} - -# ----------------------------------------------------------------------------- -# Variables: S3 -# ----------------------------------------------------------------------------- - -# var.bucket -variable "bucket" { - description = "S3 bucket" -} diff --git a/modules/webhook/main.tf b/modules/webhook/main.tf deleted file mode 100644 index 938f731..0000000 --- a/modules/webhook/main.tf +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -provider "github" { - organization = "${var.github_owner}" - token = "${var.github_oauth_token}" -} - -# ----------------------------------------------------------------------------- -# Data: Credentials -# ----------------------------------------------------------------------------- - -# data.aws_region._ -data "aws_region" "_" { - current = true -} - -# ----------------------------------------------------------------------------- -# Data: IAM -# ----------------------------------------------------------------------------- - -# data.template_file.lambda_iam_policy.rendered -data "template_file" "lambda_iam_policy" { - template = "${file("${path.module}/../../data/iam/policies/lambda.json")}" - - vars { - bucket = "${var.bucket}" - } -} - -# data.template_file.webhook_iam_policy.rendered -data "template_file" "webhook_iam_policy" { - template = "${file("${path.module}/../../data/iam/policies/webhook.json")}" - - vars { - topic = "${aws_sns_topic._.arn}" - } -} - -# ----------------------------------------------------------------------------- -# Resources: IAM -# ----------------------------------------------------------------------------- - -# aws_iam_role.lambda -resource "aws_iam_role" "lambda" { - name = "${var.namespace}-lambda-webhook" - path = "/${var.namespace}/lambda/" - - assume_role_policy = "${ - file("${path.module}/../../data/iam/policies/assume-role/lambda.json") - }" -} - -# aws_iam_policy.lambda -resource "aws_iam_policy" "lambda" { - name = "${var.namespace}-lambda-webhook" - path = "/${var.namespace}/lambda/" - - policy = "${data.template_file.lambda_iam_policy.rendered}" -} - -# aws_iam_policy_attachment.lambda -resource "aws_iam_policy_attachment" "lambda" { - name = "${var.namespace}-lambda-webhook" - - policy_arn = "${aws_iam_policy.lambda.arn}" - roles = ["${aws_iam_role.lambda.id}"] -} - -# ----------------------------------------------------------------------------- - -# aws_iam_user._ -resource "aws_iam_user" "_" { - name = "${var.namespace}-webhook" - path = "/${var.namespace}/" -} - -# aws_iam_access_key._ -resource "aws_iam_access_key" "_" { - user = "${aws_iam_user._.name}" -} - -# aws_iam_user_policy._ -resource "aws_iam_user_policy" "_" { - name = "${var.namespace}-webhook" - user = "${aws_iam_user._.name}" - - policy = "${data.template_file.webhook_iam_policy.rendered}" -} - -# ----------------------------------------------------------------------------- -# Resources: SNS -# ----------------------------------------------------------------------------- - -# aws_sns_topic._ -resource "aws_sns_topic" "_" { - name = "${var.namespace}-webhook" -} - -# aws_sns_topic_subscription._ -resource "aws_sns_topic_subscription" "_" { - topic_arn = "${aws_sns_topic._.arn}" - protocol = "lambda" - endpoint = "${aws_lambda_function._.arn}" -} - -# ----------------------------------------------------------------------------- -# Resources: Lambda -# ----------------------------------------------------------------------------- - -# aws_lambda_function._ -resource "aws_lambda_function" "_" { - function_name = "${var.namespace}-webhook" - role = "${aws_iam_role.lambda.arn}" - runtime = "nodejs6.10" - filename = "${path.module}/../../data/lambda/dist/webhook.zip" - handler = "index.default" - timeout = 10 - - source_code_hash = "${ - base64sha256(file("${path.module}/../../data/lambda/dist/webhook.zip")) - }" - - environment { - variables = { - GITHUB_OAUTH_TOKEN = "${var.github_oauth_token}" - GITHUB_REPORTER = "${var.github_reporter}" - } - } -} - -# aws_lambda_permission._ -resource "aws_lambda_permission" "_" { - statement_id = "AllowExecutionFromSNS" - action = "lambda:InvokeFunction" - function_name = "${aws_lambda_function._.arn}" - principal = "sns.amazonaws.com" - source_arn = "${aws_sns_topic._.arn}" -} - -# ----------------------------------------------------------------------------- -# Resources: GitHub -# ----------------------------------------------------------------------------- - -# github_repository_webhook._ -resource "github_repository_webhook" "_" { - repository = "${var.github_repository}" - name = "amazonsns" - - configuration { - aws_key = "${aws_iam_access_key._.id}" - aws_secret = "${aws_iam_access_key._.secret}" - sns_topic = "${aws_sns_topic._.arn}" - sns_region = "${data.aws_region._.name}" - } - - events = ["push", "pull_request"] - - # Ignore, if the webhook already exists - lifecycle { - ignore_changes = ["*"] - } -} diff --git a/modules/webhook/variables.tf b/modules/webhook/variables.tf deleted file mode 100644 index 1e44ecf..0000000 --- a/modules/webhook/variables.tf +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright (c) 2017 Martin Donath - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# ----------------------------------------------------------------------------- -# Variables: General -# ----------------------------------------------------------------------------- - -# var.namespace -variable "namespace" { - description = "AWS resource namespace/prefix" -} - -# ----------------------------------------------------------------------------- -# Variables: GitHub -# ----------------------------------------------------------------------------- - -# var.github_owner -variable "github_owner" { - description = "GitHub repository owner" -} - -# var.github_repository -variable "github_repository" { - description = "GitHub repository name" -} - -# var.github_oauth_token -variable "github_oauth_token" { - description = "GitHub OAuth token for repository access" -} - -# var.github_reporter -variable "github_reporter" { - description = "GitHub commit status reporter" -} - -# ----------------------------------------------------------------------------- -# Variables: S3 -# ----------------------------------------------------------------------------- - -# var.bucket -variable "bucket" { - description = "S3 bucket" -} diff --git a/outputs.tf b/outputs.tf index 136e0bc..a25e006 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Martin Donath +# Copyright (c) 2017-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -19,7 +19,7 @@ # IN THE SOFTWARE. # ----------------------------------------------------------------------------- -# Outputs: CodeBuild +# Outputs # ----------------------------------------------------------------------------- # output.codebuild_service_role_name @@ -34,16 +34,16 @@ output "codebuild_service_role_arn" { # output.codebuild_bucket output "codebuild_bucket" { - value = "${aws_s3_bucket.codebuild.bucket}" + value = "${aws_s3_bucket._.bucket}" } # output.codebuild_badge_url output "codebuild_badge_url" { - value = "https://s3.amazonaws.com/${ - aws_s3_bucket.codebuild.bucket - }/${ - var.github_repository - }/status.svg" + value = "${ + var.codebuild_badge_enabled == "true" + ? aws_codebuild_project._.*.badge_url[0] + : "" + }" } # output.codebuild_url diff --git a/variables.tf b/variables.tf index d0af29f..f1e208d 100644 --- a/variables.tf +++ b/variables.tf @@ -1,4 +1,4 @@ -# Copyright (c) 2017 Martin Donath +# Copyright (c) 2017-2018 Martin Donath # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to @@ -25,7 +25,6 @@ # var.namespace variable "namespace" { description = "AWS resource namespace/prefix" - default = "github-ci" } # ----------------------------------------------------------------------------- @@ -47,22 +46,10 @@ variable "github_oauth_token" { description = "GitHub OAuth token for repository access" } -# var.github_reporter -variable "github_reporter" { - description = "GitHub commit status reporter" - default = "AWS CodeBuild" -} - # ----------------------------------------------------------------------------- # Variables: CodeBuild # ----------------------------------------------------------------------------- -# var.codebuild_project -variable "codebuild_project" { - description = "CodeBuild project name (won't create default project)" - default = "" -} - # var.codebuild_compute_type variable "codebuild_compute_type" { description = "Compute resources used by the build" @@ -75,8 +62,33 @@ variable "codebuild_image" { default = "aws/codebuild/ubuntu-base:14.04" } +# var.codebuild_buildspec +variable "codebuild_buildspec" { + description = "Build specification file location" + default = "" +} + +# var.codebuild_privileged_mode +variable "codebuild_privileged_mode" { + description = "Enables running the Docker daemon inside a Docker container" + default = "false" +} + # var.codebuild_bucket variable "codebuild_bucket" { description = "S3 bucket to store status badge and artifacts" default = "" } + +# var.codebuild_environment_variables +variable "codebuild_environment_variables" { + description = "Environment variables to be used for build" + default = [] + type = "list" + } + +# var.codebuild_badge_enabled +variable "codebuild_badge_enabled" { + description = "Generates a publicly-accessible URL for the projects build badge" + default = "true" +}