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

ci: added generators for build, test & helm sync #3

Closed
wants to merge 1 commit into from
Closed
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
127 changes: 127 additions & 0 deletions ci-generate-build-n-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const fs = require("fs");

const services = [
"auditlogs",
"create-artifact-worker",
"deployments",
"deviceauth",
"deviceconfig",
"deviceconnect",
"devicemonitor",
"inventory",
"mender-gateway",
"tenantadm",
"useradm",
"workflows",
Comment on lines +4 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

This list contains enterprise services and mender-gateway which is not part of this repository.

];

const pipelineTemplate = (jobs) => `stages:
- build
- test
${jobs.join("")}
`;

const getChangesRule = ({
RULES_CHANGES_COMPARE_TO_REF,
service,
}) => `- changes:
paths: ["backend/services/${service}/**/*", "backend/pkg/**/*"]
compare_to: "${RULES_CHANGES_COMPARE_TO_REF}"`;

const buildTemplate = ({
CI_COMMIT_REF_NAME,
CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX,
CI_PIPELINE_ID,
CI_REGISTRY_IMAGE,
DOCKER_PUBLISH_COMMIT_TAG,
RULES_CHANGES_COMPARE_TO_REF,
service,
}) => `
build:${service}:docker-multiplatform:
Copy link
Contributor

Choose a reason for hiding this comment

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

Building services in different jobs, although parallel is more wasteful as it cannot leverage the local go cache.

image: "registry.gitlab.com/northern.tech/mender/mender-test-containers:docker-multiplatform-buildx-v1-master"
stage: build
rules:
${getChangesRule({ RULES_CHANGES_COMPARE_TO_REF, service })}
- if: '$CI_COMMIT_TAG =~ /^saas-[a-zA-Z0-9.]+$/'
when: never
- when: on_success
tags:
- hetzner-amd-beefy
services:
- name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:20.10.21-dind
Copy link
Contributor

Choose a reason for hiding this comment

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

This version of docker is over 3 years old. Could we make the docker version more transparent in the global variable section?

Suggested change
- name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:20.10.21-dind
- name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/docker:${DOCKER_VERSION}-dind

alias: docker
needs: []
variables:
DOCKER_BUILDKIT: 1
GITLAB_REGISTRY_TAG: '${CI_REGISTRY_IMAGE}:${CI_PIPELINE_ID}'
before_script:
- *dind-login
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
script:
- echo "building ${service} with tags \${GITLAB_REGISTRY_TAG} and ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}"
- docker context create builder
- docker buildx create builder --use --driver-opt network=host --buildkitd-flags '--debug --allow-insecure-entitlement network.host'
- docker buildx build
--cache-to type=registry,ref=${CI_REGISTRY_IMAGE}:ci_cache,mode=max
--cache-from type=registry,ref=${CI_REGISTRY_IMAGE}:ci_cache
--tag \${GITLAB_REGISTRY_TAG}
--tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_NAME}
--file backend/services/${service}/Dockerfile
--build-arg GIT_COMMIT_TAG="${DOCKER_PUBLISH_COMMIT_TAG}"
--platform $MULTIPLATFORM_PLATFORMS
--provenance false
--push
\${EXTRA_DOCKER_ARGS}
.
`;
Comment on lines +64 to +76
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we instead use the make targets? That makes it easier to reproduce locally and make it more obvious to compare local vs CI builds.

make -C backend/services/${service} docker


const testTemplate = ({
GOLANG_VERSION,
RULES_CHANGES_COMPARE_TO_REF,
service,
}) => `
test:${service}:unit:
image: golang:${GOLANG_VERSION}
stage: test
rules:
${getChangesRule({ RULES_CHANGES_COMPARE_TO_REF, service })}
- if: '$CI_COMMIT_TAG =~ /^saas-[a-zA-Z0-9.]+$/'
when: never
- when: on_success
tags:
- hetzner-amd-beefy
needs:
- job: build:${service}:docker-multiplatform
artifacts: true
script:
- go test -trimpath -ldflags -s -w ./...
Copy link
Contributor

Choose a reason for hiding this comment

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

How do we deal with the test with the same toolchain version as we're building. Today we're not doing a very good job at that - versions managed inside gitlab tend to lag major versions (Go term - not semver) behind the Dockerfile.

Suggested change
- go test -trimpath -ldflags -s -w ./...
- go test -trimpath -ldflags='-s -w' ./...

`;

const generate = ({ branch, commit = "", ref }) => {
const jobs = services.reduce((accu, service) => {
accu.push(
buildTemplate({
CI_COMMIT_REF_NAME: "pr_124",
CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX: "menderRegistry",
CI_PIPELINE_ID: "123",
CI_REGISTRY_IMAGE: `mendersoftware/${service}`,
DOCKER_PUBLISH_COMMIT_TAG: `${ref ? ref : "master"}-${commit}`,
RULES_CHANGES_COMPARE_TO_REF: "main",
branch,
service,
})
);
accu.push(
testTemplate({
GOLANG_VERSION: "1.23.0",
RULES_CHANGES_COMPARE_TO_REF: "main",
service,
})
);
return accu;
}, []);
const pipeline = pipelineTemplate(jobs);
fs.writeFileSync("generated-build-n-test.yml", pipeline);
};

generate({ branch: "main" });
97 changes: 97 additions & 0 deletions ci-generate-sync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const fs = require("fs");

const services = [
"auditlogs",
"create-artifact-worker",
"deployments",
"deviceauth",
"deviceconfig",
"deviceconnect",
"devicemonitor",
"inventory",
"mender-gateway",
"tenantadm",
"useradm",
"workflows",
];

const pipelineTemplate = (jobs, shared) => `stages:
- version-bump
${shared}
${jobs.join("")}
`;

const getChangesRule = ({
RULES_CHANGES_COMPARE_TO_REF,
service,
}) => `- changes:
paths: ["backend/services/${service}/**/*", "backend/pkg/**/*"]
compare_to: "${RULES_CHANGES_COMPARE_TO_REF}"`;

const sharedTemplate = ({ CI_COMMIT_REF_NAME, CI_COMMIT_SHA }) => `
.trigger:mender-helm-version-bump:
stage: version-bump
allow_failure: true
trigger:
project: Northern.tech/Mender/mender-helm
strategy: depend
resource_group: mender-helm
variables:
SYNC_IMAGE_TAG: $DOCKER_PUBLISH_COMMIT_TAG
DOCKER_PUBLISH_COMMIT_TAG: ${CI_COMMIT_REF_NAME}_${CI_COMMIT_SHA}
GITHUB_HELM_REPO: "github.com/mendersoftware/mender-helm.git"
CHART_DIR: "mender"
`;

const template = ({
CI_COMMIT_REF_NAME,
CI_PIPELINE_ID,
CONTAINER_NAME,
RULES_CHANGES_COMPARE_TO_REF,
service,
}) => `
trigger:mender-helm-version-bump:${service}:staging:
extends:
- .trigger:mender-helm-version-bump
rules:
${getChangesRule({ RULES_CHANGES_COMPARE_TO_REF, service })}
- if: $CI_COMMIT_BRANCH =~ /^(staging)$/
Comment on lines +56 to +58
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this is a topic for the QA meeting, but IMO we could drop the staging branch and deploy to staging from main.

Suggested change
rules:
${getChangesRule({ RULES_CHANGES_COMPARE_TO_REF, service })}
- if: $CI_COMMIT_BRANCH =~ /^(staging)$/
rules:
${getChangesRule({ "HEAD~1", service })}
- if: $CI_COMMIT_BRANCH == main

variables:
SYNC_CONTAINER_NAME: ${CONTAINER_NAME}
CONTAINER: ${service}
SYNC_ENVIRONMENT: staging
HELM_PATCH_VERSION: ${CI_PIPELINE_ID}-staging # pre-release version for trigger staging only deploy

trigger:mender-helm-version-bump:${service}:prod:
extends:
- .trigger:mender-helm-version-bump
rules:
- if: "$CI_COMMIT_TAG =~ /^saas-[a-zA-Z0-9.]+$/"
when: manual
variables:
SYNC_ENVIRONMENT: prod
HELM_PATCH_VERSION: ${CI_PIPELINE_ID}
DOCKER_PUBLISH_COMMIT_TAG: ${CI_COMMIT_REF_NAME}

`;

const generate = ({ branch, commit = "", ref }) => {
const jobs = services.map((service) =>
template({
CI_COMMIT_REF_NAME: "pr_124",
CI_PIPELINE_ID: "123",
RULES_CHANGES_COMPARE_TO_REF: "main",
DOCKER_PUBLISH_COMMIT_TAG: `${ref ? ref : "master"}-${commit}`,
CI_COMMIT_SHA: "124532t4r",
CONTAINER_NAME: service,
service,
})
);
const pipeline = pipelineTemplate(
jobs,
sharedTemplate({ CI_COMMIT_REF_NAME: "pr_124", CI_COMMIT_SHA: "124532t4r" })
);
fs.writeFileSync("generated-helm-bump-jobs.yml", pipeline);
};

generate({ branch: "main" });