diff --git a/.github/workflows/adf.yml b/.github/workflows/adf.yml index 3da236166..962e2c829 100644 --- a/.github/workflows/adf.yml +++ b/.github/workflows/adf.yml @@ -17,7 +17,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - name: Set the correct Node version using nvm - shell: bash -l {0} + shell: bash -l {0} run: nvm install - name: Install dependencies run: make init diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/mega-linter.yml new file mode 100644 index 000000000..de54d5bbc --- /dev/null +++ b/.github/workflows/mega-linter.yml @@ -0,0 +1,71 @@ +--- +# MegaLinter GitHub Action configuration file +# More info at https://oxsecurity.github.io/megalinter +name: MegaLinter + +on: [push, pull_request] + +env: + APPLY_FIXES: none + APPLY_FIXES_EVENT: pull_request + APPLY_FIXES_MODE: pull_request + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + build: + name: MegaLinter + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + fetch-depth: 0 + + - name: MegaLinter + id: ml + uses: oxsecurity/megalinter@v6 + env: + # All available variables are described in documentation + # https://oxsecurity.github.io/megalinter/configuration/ + VALIDATE_ALL_CODEBASE: true + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Archive production artifacts + if: ${{ success() }} || ${{ failure() }} + uses: actions/upload-artifact@v2 + with: + name: MegaLinter reports + path: | + megalinter-reports + mega-linter.log + + # Create pull request if applicable (this only works on PRs from the same repository, not from forks) + - name: Create Pull Request with applied fixes + id: cpr + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + commit-message: "[MegaLinter] Apply linters automatic fixes" + title: "[MegaLinter] Apply linters automatic fixes" + labels: bot + - name: Create PR output + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + + # Push new commit if applicable (this only works on PRs from the same repository, not from forks) + - name: Prepare commit + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + run: sudo chown -Rc $UID .git/ + - name: Commit and push applied linter fixes + if: steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == 'all' || env.APPLY_FIXES_EVENT == github.event_name) && env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository) && !contains(github.event.head_commit.message, 'skip fix') + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: ${{ github.event.pull_request.head.ref || github.head_ref || github.ref }} + commit_message: "[MegaLinter] Apply linters fixes" diff --git a/.gitignore b/.gitignore index 16165b2e2..2debaecf8 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,5 @@ dmypy.json # Pyre type checker .pyre/ + +megalinter-reports/ diff --git a/.mega-linter.yml b/.mega-linter.yml new file mode 100644 index 000000000..b3aa98d29 --- /dev/null +++ b/.mega-linter.yml @@ -0,0 +1,32 @@ +# Configuration file for MegaLinter +# See all available variables at https://oxsecurity.github.io/megalinter/configuration/ and in linters documentation + +# all, none, or list of linter keys +APPLY_FIXES: none + +# If you use ENABLE variable, all other languages/formats/tooling-formats will be disabled by default +# ENABLE: + +# If you use ENABLE_LINTERS variable, all other linters will be disabled by default +ENABLE_LINTERS: + - CLOUDFORMATION_CFN_LINT + - DOCKERFILE_HADOLINT + - JSON_JSONLINT + - JSON_PRETTIER + - JSON_V8R + - JAVASCRIPT_STANDARD + - SPELL_MISSPELL + - TERRAFORM_TFLINT + - YAML_YAMLLINT + +# DISABLE: +# - COPYPASTE # Comment to enable checks of excessive copy-pastes +# - SPELL # Comment to enable checks of spelling mistakes + +SHOW_ELAPSED_TIME: true +FILEIO_REPORTER: false +# DISABLE_ERRORS: true # Uncomment if you want MegaLinter to detect errors but not block CI to pass + +JSON_PRETTIER_PRE_COMMANDS: + - command: npm install prettier-plugin-multiline-arrays@1.1.0 + cwd: "workspace" \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..519d6676c --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + plugins: [ + '/node-deps/node_modules/prettier-plugin-multiline-arrays' + ], + trailingComma: 'es5', + semi: false, + singleQuote: true +} diff --git a/.yamllint b/.yamllint.yml similarity index 95% rename from .yamllint rename to .yamllint.yml index 332b7476b..0e2498813 100644 --- a/.yamllint +++ b/.yamllint.yml @@ -2,7 +2,6 @@ yaml-files: - '*.yaml' - '*.yml' - - '.yamllint' rules: braces: @@ -20,7 +19,6 @@ rules: document-start: disable empty-lines: enable empty-values: disable - empty-values: disable float-values: forbid-inf: true forbid-nan: true @@ -38,3 +36,4 @@ rules: trailing-spaces: enable truthy: level: error + check-keys: false diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8fe7aa34d..2d5853c28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,6 +36,24 @@ In order to run the tests locally you need a virtual environment that is used by 3. Install dependencies: `make init` 4. To run the tests, execute: `tox` + +## Running linters locally + +You need to have NodeJS and Docker installed on your computer to run MegaLinter locally with MegaLinter Runner. + +You can run mega-linter-runner without installation by using `npx` (Run from the root of the repository!). + +```sh +npx mega-linter-runner +``` + +Some linters can automatically fix findings by running the command below. + +```sh +npx mega-linter-runner --fix +``` + + ## Contributing via Pull Requests Contributions via pull requests are much appreciated. @@ -53,11 +71,13 @@ To send us a pull request, please: 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. -3. Ensure local tests pass. -4. Commit to your fork using clear commit messages. -5. Send us a pull request, answering any default questions in the pull request +3. Make sure your editor is configured to use [editorconfig](https://editorconfig.org/), + this helps maintain consistent coding styles and prevents linter findings later. +4. Ensure local tests and linters pass. +5. Commit to your fork using clear commit messages. +6. Send us a pull request, answering any default questions in the pull request interface. -6. Pay attention to any automated CI failures reported in the pull request, +7. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. GitHub provides additional document on diff --git a/Makefile b/Makefile index a21a95798..304594de2 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ test: lint: # Linter performs static analysis to catch latent bugs find src/ -iname "*.py" -not -path "src/.aws-sam/*" | xargs pylint --rcfile .pylintrc - find src -iname "*.yml" -o -iname "*.yaml" -not -path "src/.aws-sam/*" | xargs yamllint -c .yamllint + find src -iname "*.yml" -o -iname "*.yaml" -not -path "src/.aws-sam/*" | xargs yamllint -c .yamllint.yml cfn-lint build: diff --git a/README.md b/README.md index ac482d000..5be9ea72b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # AWS Deployment Framework -[![Build Status](https://travis-ci.org/awslabs/aws-deployment-framework.svg?branch=master)](https://travis-ci.org/awslabs/aws-deployment-framework) +[![Build Status](https://github.com/awslabs/aws-deployment-framework/workflows/ADF%20CI/badge.svg?branch=master)](https://github.com/awslabs/aws-deployment-framework/actions?query=workflow%3AADF%20CI+branch%3Amaster) + +[![MegaLinter](https://github.com/awslabs/aws-deployment-framework/workflows/MegaLinter/badge.svg?branch=master)](https://github.com/awslabs/aws-deployment-framework/actions?query=workflow%3AMegaLinter+branch%3Amaster) The AWS Deployment Framework *(ADF)* is an extensive and flexible framework to manage and deploy resources across multiple AWS accounts and regions within an diff --git a/samples/sample-cdk-app/tsconfig.json b/samples/sample-cdk-app/tsconfig.json index f2e82ef87..d050bcc50 100644 --- a/samples/sample-cdk-app/tsconfig.json +++ b/samples/sample-cdk-app/tsconfig.json @@ -1,8 +1,12 @@ { "compilerOptions": { - "target":"ES2018", + "target": "ES2018", "module": "commonjs", - "lib": ["es2016", "es2017.object", "es2017.string"], + "lib": [ + "es2016", + "es2017.object", + "es2017.string" + ], "strict": true, "noImplicitAny": true, "strictNullChecks": true, @@ -15,7 +19,6 @@ "inlineSourceMap": true, "inlineSources": true, "experimentalDecorators": true, - "strictPropertyInitialization":false + "strictPropertyInitialization": false } } - diff --git a/samples/sample-fargate-node-app/Dockerfile b/samples/sample-fargate-node-app/Dockerfile index 9ef7ffa6c..541f46587 100644 --- a/samples/sample-fargate-node-app/Dockerfile +++ b/samples/sample-fargate-node-app/Dockerfile @@ -1,9 +1,6 @@ -FROM node:latest - -ADD . . - +FROM node:current-alpine +WORKDIR /app +COPY . . RUN npm install - EXPOSE 3000 - -ENTRYPOINT ["npm", "start"] +ENTRYPOINT ["npm", "start"] \ No newline at end of file diff --git a/samples/sample-fargate-node-app/index.js b/samples/sample-fargate-node-app/index.js index 0768bfeac..53f7ada70 100644 --- a/samples/sample-fargate-node-app/index.js +++ b/samples/sample-fargate-node-app/index.js @@ -1,21 +1,21 @@ -const express = require('express'); +const express = require('express') -const app = express(); +const app = express() -app.set('view engine', 'ejs'); -app.use(express.static('public')); +app.set('view engine', 'ejs') +app.use(express.static('public')) app.get('/', (req, res) => { res.render('index', { region: process.env.REGION, environment: process.env.ENVIRONMENT - }); -}); + }) +}) app.get('/version', (req, res) => { - res.json({"version": "0.0.1"}); -}); + res.json({ version: '0.0.1' }) +}) app.listen(3000, () => { - console.log('Listening on 3000'); -}); + console.log('Listening on 3000') +}) diff --git a/samples/sample-terraform/main.tf b/samples/sample-terraform/main.tf index 2cd9d4b34..61d2b061b 100644 --- a/samples/sample-terraform/main.tf +++ b/samples/sample-terraform/main.tf @@ -6,7 +6,7 @@ provider "aws" { } resource "aws_s3_bucket" "b" { - bucket = "${var.my_bucket_name}" + bucket = var.my_bucket_name acl = "private" tags = { diff --git a/samples/sample-vpc/template.yml b/samples/sample-vpc/template.yml index 1042add60..f9fe737c4 100644 --- a/samples/sample-vpc/template.yml +++ b/samples/sample-vpc/template.yml @@ -219,10 +219,9 @@ Resources: PrivateSubnet1a: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 0 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 0 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PrivateOne', 'CIDR'] Tags: @@ -247,10 +246,9 @@ Resources: PrivateSubnet1b: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 1 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 1 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PrivateTwo', 'CIDR'] Tags: @@ -275,10 +273,9 @@ Resources: PrivateSubnet1c: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 2 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 2 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PrivateThree', 'CIDR'] Tags: @@ -329,10 +326,9 @@ Resources: PublicSubnet1a: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 0 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 0 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PublicOne', 'CIDR'] MapPublicIpOnLaunch: true @@ -358,10 +354,9 @@ Resources: PublicSubnet1b: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 1 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 1 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PublicTwo', 'CIDR'] Tags: @@ -386,10 +381,9 @@ Resources: PublicSubnet1c: Type: AWS::EC2::Subnet Properties: - AvailabilityZone: - Fn::Select: - - 2 - - Fn::GetAZs: {Ref: 'AWS::Region'} + AvailabilityZone: !Select + - 2 + - Fn::GetAZs: !Ref 'AWS::Region' VpcId: !Ref 'VPC' CidrBlock: !FindInMap ['SubnetConfig', 'PublicThree', 'CIDR'] Tags: diff --git a/src/account_processing.yml b/src/account_processing.yml index a16f8d8e8..4ae6bcd36 100644 --- a/src/account_processing.yml +++ b/src/account_processing.yml @@ -1,6 +1,6 @@ AWSTemplateFormatVersion: '2010-09-09' Transform: 'AWS::Serverless-2016-10-31' -Description: ADF CloudFormation Stack pertaing to account processing / OU management. +Description: ADF CloudFormation Stack pertaining to account processing / OU management. Parameters: OrganizationID: diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-tagging-policy.json b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-tagging-policy.json index 4cb134f53..4c73dacdc 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-tagging-policy.json +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-bootstrap/example-tagging-policy.json @@ -11,10 +11,8 @@ ] }, "enforced_for": { - "@@assign": [ - "s3:bucket" - ] + "@@assign": ["s3:bucket"] } } } -} \ No newline at end of file +} diff --git a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/tests/stubs/stub_cfn_global.json b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/tests/stubs/stub_cfn_global.json index 921d0a29c..5157a0170 100644 --- a/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/tests/stubs/stub_cfn_global.json +++ b/src/lambda_codebase/initial_commit/bootstrap_repository/adf-build/shared/tests/stubs/stub_cfn_global.json @@ -4,8 +4,8 @@ "Environment": "testing", "MySpecialValue": "resolve:/values/some_value" }, - "Tags" : { - "TagKey" : "123", - "MyKey" : "new_value" + "Tags": { + "TagKey": "123", + "MyKey": "new_value" } }