GithubHelp home page GithubHelp logo

jlhood / github-codebuild-logs Goto Github PK

View Code? Open in Web Editor NEW
84.0 7.0 22.0 731 KB

Serverless App that publishes CodeBuild build logs to a publicly accessible location

License: MIT License

Makefile 4.47% Python 95.53%

github-codebuild-logs's Introduction

github-codebuild-logs

Build Status

This serverless app solves a common complaint when using AWS CodeBuild as a CI solution: PR contributors don't have access to the build logs if the CI build fails on their PR branch. The app creates publicly accessible links to PR build logs for a given AWS CodeBuild project and posts them as a comment on the corresponding GitHub PR.

Here is an example GitHub PR comment:

Screenshot

App Architecture

App Architecture

  1. Contributors create or update a PR.
  2. Assuming AWS CodeBuild is already setup as the CI solution for this repo, the PR triggers a new CI build.
  3. Once the CI build completes (success or failure), a CloudWatch Event triggers an AWS Lambda function.
  4. If the event is for a PR build, the Lambda function
    1. copies the build log to an S3 bucket. Note, the build log auto-expires after a configurable number of days (default: 30).
    2. publishes a comment on the GitHub PR with a publicly accessible link to the logs. Note, the app uses the CodeBuild project's GitHub OAUTH token to post the comment.
  5. The logs link goes to an API Gateway endpoint, which redirects to a pre-signed URL for the build logs in the S3 bucket.

Installation Instructions

To attach this app to an existing AWS CodeBuild project in your AWS account,

  1. Go to the app's page on the Serverless Application Repository and click "Deploy"
  2. Provide the CodeBuild project name and any other parameters (see parameter details below) and click "Deploy"

Alternatively, if your CodeBuild project is defined in an AWS SAM template, this app can be embedded as a nested app inside that SAM template. To do this, visit the app's page on the AWS Lambda Console. Click the "Copy as SAM Resource" button and paste the copied YAML into your SAM template.

If you are an AWS CDK user, you can use the aws-serverless.CfnApplication construct to embed this app in your CDK application. Here is a TypeScript example:

import serverless = require('@aws-cdk/aws-sam');

new serverless.CfnApplication(this, 'GitHubCodeBuildLogsSAR', {
  location: {
    applicationId: 'arn:aws:serverlessrepo:us-east-1:277187709615:applications/github-codebuild-logs',
    semanticVersion: '1.6.0'
  },
  parameters: {
    CodeBuildProjectName: project.projectName
  }
});

App Parameters

  1. CodeBuildProjectName (required) - Name of CodeBuild project this app is posting logs for.
  2. ExpirationInDays (optional) - Number of days before a build's log page expires. Default: 30
  3. CodeBuildProjectCustomLogGroupName (optional) - If the CodeBuild Project has a custom log group name, you can specify it here. If not provided, the app will assume the CodeBuild default log group name format of /aws/codebuild/<project name>.
  4. GitHubOAuthToken (optional) - OAuth token used for writing comments to GitHub PRs. If not provided, the app will attempt to pull an OAuth token from the CodeBuild project. Note, if your CodeBuild project does not have a GitHub OAuth token, e.g., it is being used to build a public GitHub repo, then this parameter will be required for the app to function properly.
    • NOTE: The access token used requires public_repo permissions for public repositories or repo for private repositories.
  5. DeletePreviousComments (optional) - Set to true to delete previously posted PR comments before posting a new one. Default: false
  6. LogLevel (optional) - Log level for Lambda function logging, e.g., ERROR, INFO, DEBUG, etc. Default: INFO
  7. CommentOnSuccess (optional) - Set to false to not publish a comment when build is successful. Default: true
  8. BuildEventTimeout (optional) - Timeout for Process Build Event Lambda. Default: 60

App Outputs

  1. ProcessBuildEventsFunctionName - ProcessBuildEvents Lambda function name.
  2. ProcessBuildEventsFunctionArn - ProcessBuildEvents Lambda function ARN.
  3. BuildLogsBucketName - Build logs S3 bucket name.
  4. BuildLogsBucketArn - Build logs S3 bucket ARN.

Security Considerations

The following precautions are taken when the GitHubOAuthToken parameter is provided since it's sensitive data:

  1. The NoEcho option is used on the parameter so the value will never be shown by CloudFormation.
  2. The app stores the value in AWS Secrets Manager.

License Summary

This code is made available under the MIT license. See the LICENSE file.

github-codebuild-logs's People

Contributors

jflasher avatar jlhood avatar jogold avatar mattsb42 avatar navinsoni avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

github-codebuild-logs's Issues

Builds not created by PRs result in an error

When a CodeBuild build is triggered by something other than a PR (ex: manually), the sourceVersion field might not be present in the build details.

Because this field is currently retrieved by a getitem call[1], if the key is not found, a KeyError is thrown[2].

[1] https://github.com/jlhood/github-codebuild-logs/blob/master/src/build.py#L27-L32
[2]

[ERROR] KeyError: 'sourceVersion'
Traceback (most recent call last):
  File "/var/task/processbuildevents.py", line 29, in handler
    if not build.is_pr_build():
  File "/var/task/build.py", line 36, in is_pr_build
    return self.get_pr_id() is not None
  File "/var/task/build.py", line 29, in get_pr_id
    matches = re.match(r'^pr\/(\d+)', self._get_build_details()['sourceVersion'])

Change `DeletePreviousComment` to an int

Context

Hi I'm one of the maintainers of torchserve at PyTorch which we comaintain with AWS and we use codebuild and your bot to be able to share with community members issues with their PRs. We can't share the codebuild links directly since they're internal to AWS.

When we run our CI we need to pass on both linux-cpu, linux-gpu and windows so there's a total 3 of comments that need to show and not just 1

https://github.com/pytorch/serve/pulls

Problem

However often our CI is flaky or it takes a few commits for people to get their PR right so we end up with with dozens of comments from a bot which drown out the useful comments like reviews. And we can't set DeletePreviousComment because we need 3 comments to show at a time at a minimum from each of the distributions

Proposed solution

So if we could instead the number of previous comments to be something like 3 or 6 it makes the discussions on github PRs much more readable.

Screen Shot 2022-02-18 at 2 18 25 PM

Update README and Application Settings to inform about public builds in AWS CodeBuild

Thank you @jlhood for creating this application.
We've used in AWS SDK for JavaScript (https://github.com/aws/aws-sdk-js and https://github.com/aws/aws-sdk-js-v3) for the past two years.

Is your feature request related to a problem? Please describe.

CodeBuild has now introduced public builds which allows public to access logs.
The feature provided by this serverless app is now natively supported by CodeBuild.

Describe the solution you'd like

Put github-codebuild-logs on deprecation path. An example could be:

  • Update README sharing link to blog post Introducing public builds for AWS CodeBuild, advising visitors to used native option instead.
  • Add a required option (say IWantToDeployDespiteNativeSupport) in Application Settings when deploying new version so that future users of the application are aware of the native support.

Describe alternatives you've considered

  • Not making any changes: This suggestion is not recommended, as:
    • It's convenient for AWS customers to use the feature natively.
    • AWS customers discovering github-codebuild-logs from blog post or GitHub projects already using the feature may not be knowing about native support.
  • Archiving this repository: Archiving can be done at a latter time if users of github-codebuild-logs actually switch to native support. Also, archiving without information about native support would create confusion.

Add optional HidePreviousComments option which defaults to false

Is your feature request related to a problem? Please describe.
github-codebuild-logs posts multiple comments based on how many times CodeBuild was run for the PR, which depends on how many times additional pushes were done to PR branch after the PR was posted. Example aws/aws-sdk-js-v3#824

Describe the solution you'd like
Add optional HidePreviousComments option which is false by default. When true, it will hide previously posted PR comments as Outdated before posting a new one.

Describe alternatives you've considered

  • Manually hide old comments from github-codebuild-logs as outdated, for example aws/aws-sdk-js-v3#976
  • Use DeletePreviousComments option, but it deletes the comments instead of hiding them

Deployment fails with "AWS::Events::Rule does not support attribute {Arn}" error

Describe the bug
Deployment of the Serverless Application Repository fails with the following error:

[Error] /Resources/ProcessBuildEventsBuildStatusPermission/Properties/SourceArn/Fn::GetAtt: Resource type AWS::Events::Rule does not support attribute {Arn}. Rollback requested by user.

To Reproduce

  • Visit Serverless Application Repository given in README
  • Click on "Deploy"
  • Enter "CodeBuildProjectName"
  • Click on "Deploy"
  • Notice that stack fails to get deployed and goes to ROLLBACK_COMPLETE state

Expected behavior
The Cloudformation stack serverlessrepo-github-codebuild-logs gets deployed

Screenshots
Screen Shot 2019-10-03 at 3 50 07 PM

Support CodeBuild projects that only write logs to S3

CodeBuild now supports writing logs to S3 in addition to or instead of CloudWatch logs. This app should be updated to work in the case that the CodeBuild project is configured to only write to S3 with CloudWatch logs disabled.

CodeBuild writes the logs to a gzipped S3 file. This app should be able to copy an unzipped version of the file to the app's S3 bucket for PR contributors to view.

CodeBuild projects for public repos do not appear to always have auth info

Because the PR updater attempts to piggy-back on the CodeBuild GitHub permissions, if permissions are not present, the updater will fail.

It looks like even if the CodeBuild Project was configured through GitHub OAUTH, if the GitHub repo is public, CodeBuild does not obtain an auth token. IMO, this is reasonable and good, because they aren't writing anything, so they don't need one. However, it does mean that for these public repos (the primary purpose of this project's functionality), this project does not appear to consistently work.

hephaestus:pipipxx matt$ aws codebuild batch-get-projects --names pipipxx-linux-py37
{
    "projects": [
        {
            "name": "pipipxx-linux-py37",
            "arn": "arn:aws:codebuild:us-west-2:111222333444:project/pipipxx-linux-py37",
            "source": {
                "type": "GITHUB",
                "location": "https://github.com/mattsb42/pipipxx.git",
                "gitCloneDepth": 1,
                "gitSubmodulesConfig": {
                    "fetchSubmodules": false
                },
                "buildspec": ".codebuild/linux-buildspec.yaml",
                "reportBuildStatus": false,
                "insecureSsl": false
            },
            "secondarySources": [],
            "artifacts": {
                "type": "NO_ARTIFACTS"
            },
            "secondaryArtifacts": [],
            "cache": {
                "type": "NO_CACHE"
            },
            "environment": {
                "type": "LINUX_CONTAINER",
                "image": "aws/codebuild/standard:2.0",
                "computeType": "BUILD_GENERAL1_SMALL",
                "environmentVariables": [
                    {
                        "name": "PYTHON_BUILD_VERSION",
                        "value": "3.7",
                        "type": "PLAINTEXT"
                    }
                ],
                "privilegedMode": false,
                "imagePullCredentialsType": "CODEBUILD"
            },
            "serviceRole": "arn:aws:iam::111222333444:role/service-role/test-codebuild-pipipxx",
            "timeoutInMinutes": 60,
            "queuedTimeoutInMinutes": 480,
            "encryptionKey": "arn:aws:kms:us-west-2:111222333444:alias/aws/s3",
            "tags": [],
            "created": 1558918666.096,
            "lastModified": 1558924935.24,
            "webhook": {
                "url": "https://api.github.com/repos/mattsb42/pipipxx/hooks/112678088",
                "payloadUrl": "xxxxxxxxxxxxxxxx",
                "filterGroups": [
                    [
                        {
                            "type": "EVENT",
                            "pattern": "PUSH, PULL_REQUEST_CREATED, PULL_REQUEST_UPDATED, PULL_REQUEST_REOPENED",
                            "excludeMatchedPattern": false
                        }
                    ]
                ]
            },
            "badge": {
                "badgeEnabled": true,
                "badgeRequestUrl": "https://codebuild.us-west-2.amazonaws.com/badges?uuid=eyJlbmNyeXB0ZWREYXRhIjoiQU5URTJKdnBHQkFwTStnckNjNGlaUGZQNk51V0s1V1JDL0FIUjBERWNmYnNnckM5Vy8vNlZNOWUxWElMLyt3SjlVY2RhSTk3QlByaDZsOEVkZFYzWDVNPSIsIml2UGFyYW1ldGVyU3BlYyI6Ik53bU14aTBqQkFkWmpET2UiLCJtYXRlcmlhbFNldFNlcmlhbCI6MX0%3D&branch=master"
            },
            "logsConfig": {
                "cloudWatchLogs": {
                    "status": "ENABLED"
                },
                "s3Logs": {
                    "status": "DISABLED",
                    "encryptionDisabled": false
                }
            }
        }
    ],
    "projectsNotFound": []
}

IAM permission error if custom log group is set in CodeBuild config

CodeBuild allows for a custom Log Group name to be defined for a Project.

Because the template assumes the default Log Group name of /aws/codebuild/${ProjectName} is used, if a custom name was set when configuring the CodeBuild Project, the event processor will throw permissions errors.

One solution to this would be to add an optional parameter that is used, perhaps with a Condition, to build the ProcessBuildEvents policy.

Add CodeBuild project name and commit ID to PR statement

While debugging an issue with my Windows CI[1], I ran into two issues with keeping track of what was doing what when.

  1. I have two CodeBuild projects acting as CI for that repo (Linux and Windows). The CI report contains no indication of which one the report is for. This can make tracking down issues difficult.
  2. Windows builds are a lot slower than Linux. :) I ran into one case where I had a syntax issue that also caused my Linux build to fail (commit A). I updated my branch with a fix for this (commit B), and the build for Linux-commit-B actually completed and had a report back in the PR before the Windows-commit-A build finished. Fortunately, I could easily tell from the logs that it had the issue from commit A, but if I hadn't known what to look for, it would have been confusing to try to track down the real issue.

[1] mattsb42-meta/pipx-in-pipx#17

Never a PR Build

I am not sure why but the sourceVersion field in the JSON event never starts with pr/.

matches = re.match(r'^pr\/(\d+)', self._get_build_details().get('sourceVersion', ""))

A sample from my event as output when DEBUG is enabled:
'currentPhase': 'COMPLETED', 'buildStatus': 'SUCCEEDED', 'sourceVersion': '686fcdc44df8358e3382e80379d7abec66f47e38', 'resolvedSourceVersion': '686fcdc44df8358e3382e80379d7abec66f47e38',

Am I a missing something silly, do you have to create the PR in a certain way?

Github authentication fails if OAuth token is updated in Secrets Manager [console]

Leading to #13, I was troubleshooting the permissions on my access tokens, and since you cannot modify the permissions on an existing token, I had to create a new token for each permissions attempt.

If the token is set through the SAR console on creation, everything works fine. However, if the token is then changed in Secrets Manager, the Github call fails with Invalid Credentials.
I skimmed the github proxy, and it looks like everything is being done correctly (secret value pulled fresh each time), so I'm not entirely sure why this is failing

I did update the value through the Secrets Manager console, which makes me wonder if some whitespace might be sneaking its way in to the value. I'll do some testing with this to see if I can narrow this down.

AttributeError: 'NoneType' object has no attribute 'get'

I'm not sure why but this repo is broken.

We are not able to make it work.

The lambda: serverlessrepo-github-codebuild-logs-GetBuildLogs-NsIuFeRMuqgw throw error:

[ERROR] AttributeError: 'NoneType' object has no attribute 'get'
Traceback (most recent call last):
  File "/var/task/getbuildlogs.py", line 21, in handler
    log_key = api_event.get('queryStringParameters', 
{}
).get('key')

we are on debug mode but we don't see more logs...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.