Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix(pipelines): changing synth action doesn't restart pipeline #10176

Merged
merged 8 commits into from
Sep 10, 2020

Conversation

rix0rrr
Copy link
Contributor

@rix0rrr rix0rrr commented Sep 4, 2020

Pipeline structure looks like this:

┌────────┐        ┌────────┐        ┌──────────┐
│        │        │        │        │          │
│  src   │───────▶│ synth  │───────▶│selfupdate│─────▶...(deploy)...
│        │        │        │        │          │
└────────┘        └────────┘        └──────────┘

When changing the pipeline structure, we expect it to restart (and it
does).

However, when changing something about the "synth" action (such as
adding tests to the list of commands), we would ALSO expect the pipeline to restart.
This would ensure that if we add tests, the tests get executed and
must pass before we start the actual deployments. That is, we'd like
to run the tests on the CURRENT commit as well, but by the time
we update the buildspec to run the tests, we've already passed the stage
where the tests would be run.

This is because doing something like adding
a test didn't actually change the Pipeline structure (causing
a restart). Instead, it would change the buildspec of the
CodeBuild Project the pipeline was referencing, leaving the pipeline
unchanged and ready to continue deploying. The tests would
only be executed for FUTURE commits, leaving the current commit
untested.

The solution is a hash of the buildspec somewhere, but where?

We could have put it in the CodeBuild Project's logical id, so that we
would have torn down and created a new CodeBuild project to ensure that
the pipeline would restart. However, doing so would prevent giving the
CodeBuild project a deterministic display name (replacement would fail).
Plus, a simpler and cheaper solution is to put a hash of the buildspec
in the Action that references the CodeBuild project.

There is exactly one field where we can stash some user-specified
data that doesn't impact the build result: EnvironmentVariables.
We add an environment variable with an unlikely name, which is not
used by the build itself. Its sole purpose is to make the pipeline
definition change when the buildspec changes, causing a pipeline
restart.

Fixes #9458.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license

Pipeline structure looks like this:

```
┌────────┐        ┌────────┐        ┌──────────┐
│        │        │        │        │          │
│  src   │───────▶│ synth  │───────▶│selfupdate│─────▶...(deploy)...
│        │        │        │        │          │
└────────┘        └────────┘        └──────────┘
```

When changing the pipeline structure, we expect it to restart (and it
does).

However, when changing something about the "synth" step (such as
adding tests to the step), we would ALSO expect the pipeline to restart.
This would ensure that if we add tests, the tests get executed and
must pass before we start the actual deployments.

Previously that didn't happen, because doing something like adding
a test didn't actually change the *Pipeline structure* (causing
a restart). Instead, it would change the buildspec of the
CodeBuild Project the pipeline was referencing, leaving the pipeline
unchanged and ready to continue deploying.

The solution is a hash of the buildspec somewhere, but where?

We could have put it in the CodeBuild Project's logical id, so that we
would have torn down and created a new CodeBuild project to ensure that
the pipeline would restart. However, doing so would prevent giving the
CodeBuild project a deterministic display name (replacement would fail).
Plus, a simpler and cheaper solution is to put a hash of the buildspec
in the Action that references the CodeBuild project.

There is exactly one field where we can stash some user-specified
data that doesn't impact the build result: `EnvironmentVariables`.
We add an environment variable with an unlikely name, which is not
used by the build itself. Its sole purpose is to make the pipeline
definition change when the buildspec changes, causing a pipeline
restart.

Fixes #9458.
@rix0rrr rix0rrr requested a review from a team September 4, 2020 09:38
@rix0rrr rix0rrr self-assigned this Sep 4, 2020
@mergify mergify bot added the contribution/core This is a PR that came from AWS. label Sep 4, 2020
@njlynch njlynch added the pr/do-not-merge This PR should not be merged at this time. label Sep 8, 2020
nija-at
nija-at previously requested changes Sep 8, 2020
});

const project = new codebuild.PipelineProject(scope, 'CdkBuildProject', {
projectName: this.props.projectName ?? this.props.projectName,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Comment on lines 320 to 322
// Inclusion of the hash here will lead to the pipeline structure changing if the
// buildspec changes, and hence the pipeline being restarted. This is necessary if
// the users adds (for example) build or test commands to the buildspec.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not just the buildspec but anything around the CodeBuild project.

Suggested change
// Inclusion of the hash here will lead to the pipeline structure changing if the
// buildspec changes, and hence the pipeline being restarted. This is necessary if
// the users adds (for example) build or test commands to the buildspec.
// Inclusion of the hash here will lead to the pipeline structure changing for any
// changes to the underlying CodeBuild project, and hence the pipeline being restarted.
// This is necessary if the users adds (for example) build or test commands to the buildspec.

@@ -281,6 +281,90 @@ export function notMatching(matcher: any): PropertyMatcher {
});
}

export type TypeValidator<T> = (x: any) => x is T;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add corresponding entries in the README for these new features

* });
* console.log(someValue.capturedValue);
*/
export class Capture<T=any> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sigh one more thing to consider when rewriting this module as a JSII-able module.

I would've asked - why not just

const notThisHash = ...;

expect(stack).not.toHaveResourceLike('AWS::CodeBuild::Project', {
  ...
  Value: notThisHash
});

But looking at the usage and the deep nesting, I understand why you had to do this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality is legit and should be ported, I feel.

The jsii-able version of this might drop the type assertions but I didn't see any point in having this wobbly-typed since this module is long past jsii-ability anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine by me.

We'll definitely consider for this to be ported. Just wanted to make note that the form might have to change.

@rix0rrr rix0rrr removed the pr/do-not-merge This PR should not be merged at this time. label Sep 10, 2020
@mergify
Copy link
Contributor

mergify bot commented Sep 10, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@aws-cdk-automation
Copy link
Collaborator

AWS CodeBuild CI Report

  • CodeBuild project: AutoBuildProject6AEA49D1-qxepHUsryhcu
  • Commit ID: f929a29
  • Result: SUCCEEDED
  • Build Logs (available for 30 days)

Powered by github-codebuild-logs, available on the AWS Serverless Application Repository

@mergify
Copy link
Contributor

mergify bot commented Sep 10, 2020

Thank you for contributing! Your pull request will be updated from master and then merged automatically (do not update manually, and be sure to allow changes to be pushed to your fork).

@mergify mergify bot merged commit 14c8a98 into master Sep 10, 2020
@mergify mergify bot deleted the huijbers/restart-pipeline branch September 10, 2020 12:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contribution/core This is a PR that came from AWS.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[cdk-pipelines] Changing the buildspec (e.g. adding tests) does not restart the pipeline (but it should!)
4 participants