Skip to content

Commit

Permalink
feat: Automaattitestit: pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
haapamakim committed Feb 18, 2022
1 parent 63d6c2b commit 07f1ed2
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 35 deletions.
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 };
}
}
79 changes: 69 additions & 10 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 @@ -24,10 +26,22 @@ export class HassuPipelineStack extends Stack {

async process() {
const config = await Config.instance(this);
const branch = config.getBranch();
let branch: string;
const env = Config.env;
if (env == "dev") {
branch = "main";
} else if (env == "test") {
branch = "test";
} else {
branch = config.getBranch();
}

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");
} else {
Expand All @@ -40,11 +54,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 +142,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

0 comments on commit 07f1ed2

Please sign in to comment.