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

feat: Automaattitestit: pipeline #128

Merged
merged 1 commit into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions deployment/lib/buildspec/buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ phases:
- npm run deploy:backend
- npm run deploy:frontend
- npm run release
post_build:
on-failure: ABORT
commands:
- aws codebuild start-build --project-name Hassu-robottest-dev --source-version $CODEBUILD_SOURCE_VERSION
cache:
paths:
- "/root/.cache/**/*"
Expand Down
26 changes: 26 additions & 0 deletions deployment/lib/buildspec/robottest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: 0.2

phases:
install:
commands:
- npm ci --no-audit
- npm run robot:setup
build:
commands:
- ./tools/robot/run_suite_local.sh
- echo Test report available at https://$FRONTEND_DOMAIN_NAME_DEV/report/robot-$ENVIRONMENT/$CODEBUILD_BUILD_NUMBER/report.html
artifacts:
files:
- "test/.report/**/*"
discard-paths: yes
name: robot-$ENVIRONMENT/$CODEBUILD_BUILD_NUMBER

cache:
paths:
- "/root/.npm/**/*"

reports:
unit-tests:
files: "xunit.xml"
base-directory: test/.report
discard-paths: true
1 change: 1 addition & 0 deletions deployment/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class Config extends BaseConfig {
public static readonly yllapitoBucketName = `hassu-${Config.env}-yllapito`;
public static readonly internalBucketName = `hassu-${Config.env}-internal`;
public static readonly archiveBucketName = `hassu-${Config.env}-archive`;
public static readonly reportBucketName = `hassu-report`;
public readonly dmzProxyEndpoint: string;
// @ts-ignore
public frontendDomainName: string;
Expand Down
65 changes: 46 additions & 19 deletions deployment/lib/hassu-frontend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { S3Origin } from "@aws-cdk/aws-cloudfront-origins";
import { Bucket } from "@aws-cdk/aws-s3";
import * as ssm from "@aws-cdk/aws-ssm";
import { readBackendStackOutputs, readDatabaseStackOutputs } from "../bin/setupEnvironment";
import { IOriginAccessIdentity } from "@aws-cdk/aws-cloudfront/lib/origin-access-identity";

// These should correspond to CfnOutputs produced by this stack
export type FrontendStackOutputs = {
Expand Down Expand Up @@ -196,14 +197,29 @@ export class HassuFrontendStack extends cdk.Stack {
dmzProxyBehaviorWithLambda: BehaviorOptions,
dmzProxyBehavior: BehaviorOptions
): Promise<Record<string, BehaviorOptions>> {
return {
let { keyGroups, originAccessIdentity } = await this.createTrustedKeyGroupsAndOAI(config);
let props: Record<string, any> = {
"/oauth2/*": dmzProxyBehaviorWithLambda,
"/graphql": dmzProxyBehaviorWithLambda,
"/yllapito/tiedostot/*": await this.createYllapitoTiedostotBehavior(config),
"/yllapito/tiedostot/*": await this.createPrivateBucketBehavior(
"yllapitoBucket",
Config.yllapitoBucketName,
keyGroups,
originAccessIdentity
),
"/yllapito/graphql": dmzProxyBehaviorWithLambda,
"/yllapito/kirjaudu": dmzProxyBehaviorWithLambda,
"/keycloak/*": dmzProxyBehavior,
};
if (Config.env == "dev") {
props["/report/*"] = await this.createPrivateBucketBehavior(
"reportBucket",
Config.reportBucketName,
keyGroups,
originAccessIdentity
);
}
return props;
}

private static createDmzProxyBehavior(
Expand Down Expand Up @@ -232,9 +248,34 @@ export class HassuFrontendStack extends cdk.Stack {
return dmzBehavior;
}

private async createYllapitoTiedostotBehavior(config: Config): Promise<BehaviorOptions> {
private async createPrivateBucketBehavior(
name: string,
bucketName: string,
keyGroups: KeyGroup[],
originAccessIdentity?: IOriginAccessIdentity
): Promise<BehaviorOptions> {
return {
origin: new S3Origin(
Bucket.fromBucketAttributes(this, name + "Origin", {
region: "eu-west-1",
bucketName,
}),
{
originAccessIdentity,
}
),
compress: true,
cachePolicy: CachePolicy.CACHING_DISABLED,
originRequestPolicy: OriginRequestPolicy.CORS_S3_ORIGIN,
trustedKeyGroups: keyGroups,
};
}

private async createTrustedKeyGroupsAndOAI(
config: Config
): Promise<{ originAccessIdentity: IOriginAccessIdentity | undefined; keyGroups: KeyGroup[] }> {
let keyGroups: KeyGroup[];
let originAccessIdentity;
let originAccessIdentity: IOriginAccessIdentity | undefined;

if (Config.env === "localstack") {
keyGroups = [];
Expand Down Expand Up @@ -267,20 +308,6 @@ export class HassuFrontendStack extends cdk.Stack {
);
}

return {
origin: new S3Origin(
Bucket.fromBucketAttributes(this, "yllapitoBucketOrigin", {
region: "eu-west-1",
bucketName: Config.yllapitoBucketName,
}),
{
originAccessIdentity,
}
),
compress: true,
cachePolicy: CachePolicy.CACHING_DISABLED,
originRequestPolicy: OriginRequestPolicy.CORS_S3_ORIGIN,
trustedKeyGroups: keyGroups,
};
return { keyGroups, originAccessIdentity };
}
}
69 changes: 60 additions & 9 deletions deployment/lib/hassu-pipeline.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* tslint:disable:no-console no-unused-expression */
import {Construct, SecretValue, Stack} from "@aws-cdk/core";
import { Construct, SecretValue, Stack } from "@aws-cdk/core";
import { Bucket } from "@aws-cdk/aws-s3";
import * as codebuild from "@aws-cdk/aws-codebuild";
import {BuildEnvironmentVariableType, ComputeType, LocalCacheMode} from "@aws-cdk/aws-codebuild";
import {Config} from "./config";
import {BuildSpec} from "@aws-cdk/aws-codebuild/lib/build-spec";
import {LinuxBuildImage} from "@aws-cdk/aws-codebuild/lib/project";
import {Effect, PolicyStatement} from "@aws-cdk/aws-iam";
import {GitHubSourceProps} from "@aws-cdk/aws-codebuild/lib/source";
import { BuildEnvironmentVariableType, ComputeType, LocalCacheMode } from "@aws-cdk/aws-codebuild";
import { Config } from "./config";
import { BuildSpec } from "@aws-cdk/aws-codebuild/lib/build-spec";
import { LinuxBuildImage } from "@aws-cdk/aws-codebuild/lib/project";
import { Effect, PolicyStatement } from "@aws-cdk/aws-iam";
import { GitHubSourceProps } from "@aws-cdk/aws-codebuild/lib/source";
import { Repository } from "@aws-cdk/aws-ecr/lib/repository";

/**
* The stack that defines the application pipeline
Expand All @@ -27,6 +29,10 @@ export class HassuPipelineStack extends Stack {
const branch = config.getBranch();
const env = Config.env;
console.log("Deploying pipeline from branch " + branch + " to enviroment " + env);

if (env == "dev" || env == "test") {
await this.createRobotTestPipeline(env, config);
}

if (Config.isPermanentEnvironment()) {
await this.createPipeline(env, config, "./deployment/lib/buildspec/buildspec.yml");
Expand All @@ -40,11 +46,13 @@ export class HassuPipelineStack extends Stack {
let webhookFilters;
let reportBuildStatus: boolean;
const branch = config.getBranch();
if (branch === "main") {
// Github creds only once per account
if (branch === "main" && env == "dev") {
// GitHub creds only once per account
new codebuild.GitHubSourceCredentials(this, "CodeBuildGitHubCreds", {
accessToken: SecretValue.secretsManager("github-token"),
});
// Common bucket for test reports
new Bucket(this, "reportbucket", { bucketName: Config.reportBucketName });
}
if (config.isFeatureBranch() && !config.isDeveloperEnvironment()) {
webhookFilters = [codebuild.FilterGroup.inEventOf(codebuild.EventAction.PUSH).andBranchIs("feature/*")];
Expand Down Expand Up @@ -126,4 +134,47 @@ export class HassuPipelineStack extends Stack {
})
);
}

private async createRobotTestPipeline(env: string, config: Config) {
const sourceProps: GitHubSourceProps = {
owner: "finnishtransportagency",
repo: "hassu",
webhook: true,
webhookTriggersBatchBuild: false,
reportBuildStatus: true,
webhookFilters: [codebuild.FilterGroup.inEventOf(codebuild.EventAction.PUSH).andBranchIs("robottest/*")],
};
const gitHubSource = codebuild.Source.gitHub(sourceProps);
new codebuild.Project(this, "HassuRobotTest", {
projectName: "Hassu-robottest-" + env,
buildSpec: BuildSpec.fromSourceFilename("./deployment/lib/buildspec/robottest.yml"),
source: gitHubSource,
cache: codebuild.Cache.local(LocalCacheMode.CUSTOM, LocalCacheMode.SOURCE, LocalCacheMode.DOCKER_LAYER),
environment: {
buildImage: LinuxBuildImage.fromEcrRepository(
Repository.fromRepositoryName(this, "RobotBuildImage", "hassu-robot")
),
privileged: true,
computeType: ComputeType.SMALL,
environmentVariables: {
ENVIRONMENT: { value: env },
FRONTEND_DOMAIN_NAME_DEV: { value: await config.getSecureInfraParameter("FrontendDomainName", "dev") },
},
},
grantReportGroupPermissions: true,
badge: true,
artifacts: codebuild.Artifacts.s3({
bucket: Bucket.fromBucketName(this, "RobotTestArtifactBucket", Config.reportBucketName),
includeBuildId: false,
packageZip: false,
identifier: "RobotTest",
}),
}).addToRolePolicy(
new PolicyStatement({
effect: Effect.ALLOW,
actions: ["s3:*", "ecr:*", "ssm:*", "secretsmanager:GetSecretValue"],
resources: ["*"],
})
);
}
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@
"robot:build": "./tools/robot/updateRobotImage.sh",
"robot:pull": "cross-env docker pull 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest",
"robot:setup": "ts-node --project=tsconfig.cdk.json deployment/bin/setupRobotEnvironment.ts",
"robot": "cross-env docker run --rm --add-host=host.docker.internal:host-gateway -v $(pwd):/work -e TEST_SUITE 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest",
"robot:browser": "cross-env ROBOT_OPEN_BROWSER=true ./tools/robot/run_suite_local.sh robot --console verbose --outputdir ./test/.report",
"robot": "cross-env docker run --rm --add-host=host.docker.internal:host-gateway -v $(pwd):/work -e TEST_SUITE 283563576583.dkr.ecr.eu-west-1.amazonaws.com/hassu-robot:latest /work/tools/robot/run_suite.sh",
"robot:browser": "cross-env ROBOT_OPEN_BROWSER=true ./tools/robot/run_suite_local.sh",
"ecrLogin": "aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 283563576583.dkr.ecr.eu-west-1.amazonaws.com"
},
"browserslist": {
Expand Down
8 changes: 6 additions & 2 deletions tools/robot/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ RUN python3 -m pip install robotframework && pip install robotframework-requests
RUN pip install webdrivermanager
RUN webdrivermanager firefox chrome --linkpath /usr/local/bin

CMD ["/work/tools/robot/run_suite.sh"]

ENV NODE_VERSION=14.17.0
RUN apt install -y curl && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
ENV NVM_DIR=/root/.nvm
RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION} && nvm use v${NODE_VERSION} && nvm alias default v${NODE_VERSION}
ENV PATH="/root/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"

RUN . "$NVM_DIR/nvm.sh" && npm install -g npm@8.1.3
2 changes: 1 addition & 1 deletion tools/robot/run_suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if [ -z "$TEST_SUITE" ]; then
fi

export DOCKER=true
CMD="robot --console verbose --outputdir /work/test/.report /work/test/suites/$TEST_SUITE"
CMD="robot --console verbose --outputdir /work/test/.report --xunit xunit.xml /work/test/suites/$TEST_SUITE"

echo ${CMD}

Expand Down
2 changes: 1 addition & 1 deletion tools/robot/run_suite_local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if [ -z "$TEST_SUITE" ]; then
fi

export DOCKER=false
CMD="robot --console verbose --outputdir ./test/.report ./test/suites/$TEST_SUITE"
CMD="robot --console verbose --outputdir ./test/.report --xunit xunit.xml ./test/suites/$TEST_SUITE"

echo ${CMD}

Expand Down