Skip to content
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
98 changes: 97 additions & 1 deletion .ci/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ pipeline {
REPO = 'apm-agent-nodejs'
BASE_DIR = "src/github.com/elastic/${env.REPO}"
PIPELINE_LOG_LEVEL='INFO'
NOTIFY_TO = credentials('notify-to')
JOB_GCS_BUCKET = credentials('gcs-bucket')
GITHUB_CHECK_ITS_NAME = 'Integration Tests'
ITS_PIPELINE = 'apm-integration-tests-selector-mbp/main'
OPBEANS_REPO = 'opbeans-node'
GITHUB_CHECK = 'true'
RELEASE_URL_MESSAGE = "(<https://github.com/elastic/${env.REPO}/releases/tag/${env.TAG_NAME}|${env.TAG_NAME}>)"
SLACK_CHANNEL = '#apm-agent-node'
NOTIFY_TO = 'build-apm+apm-agent-nodejs@elastic.co'
}
options {
timeout(time: 3, unit: 'HOURS')
Expand Down Expand Up @@ -274,6 +276,9 @@ pipeline {
beforeAgent true
tag pattern: 'v\\d+\\.\\d+\\.\\d+', comparator: 'REGEXP'
}
environment {
SUFFIX_ARN_FILE = 'arn-file.md'
}
stages {
stage('Opbeans') {
environment {
Expand All @@ -294,6 +299,61 @@ pipeline {
}
}
}
stage('Dist') {
steps {
withGithubNotify(context: "Dist") {
setEnvVar('ELASTIC_LAYER_NAME', "elastic-apm-node${getVersion()}")
setEnvVar('RELEASE_NOTES_URL', getReleaseNotesUrl())
deleteDir()
unstash 'source'
withNodeJSEnv(version: 'v14.17.5'){
dir("${BASE_DIR}"){
cmd(label: 'make dist', script: 'make -C .ci dist')
}
}
}
}
}
stage('Publish') {
steps {
withGithubNotify(context: "Publish") {
withGoEnv(){
withAWSEnv(secret: 'secret/observability-team/ci/service-account/apm-aws-lambda', forceInstallation: true, version: '2.4.10') {
dir("${BASE_DIR}"){
cmd(label: 'make publish-in-all-aws-regions', script: 'make -C .ci publish-in-all-aws-regions')
cmd(label: 'make create-arn-file', script: 'make -C .ci create-arn-file')
}
}
}
}
}
post {
always {
archiveArtifacts(allowEmptyArchive: true, artifacts: "${BASE_DIR}/build/aws")
}
}
}
stage('Release Notes') {
steps {
withGhEnv(forceInstallation: true, version: '2.4.0') {
dir("${BASE_DIR}"){
cmd(label: 'make release-notes', script: 'make -C .ci release-notes')
}
}
}
}
}
post {
success {
whenTrue(isTag()) {
notifyStatus(slackStatus: 'good', subject: "[${env.REPO}] Release *${env.TAG_NAME}* published", body: "Build: (<${env.RUN_DISPLAY_URL}|here>)\nRelease URL: ${env.RELEASE_URL_MESSAGE}")
}
}
failure {
whenTrue(isTag()) {
notifyStatus(slackStatus: 'warning', subject: "[${env.REPO}] Release *${env.TAG_NAME}* could not be published.", body: "Build: (<${env.RUN_DISPLAY_URL}|here>)")
}
}
}
}
/**
Expand Down Expand Up @@ -505,3 +565,39 @@ def grabWorkerIP(){
}
return linuxIp
}

/**
* Transform TAG releases from v{major}.{minor}.{patch} to
* ver-{major}-{minor}-{patch}. e.g: given v1.2.3 then
* -ver-1-2-3.
*/
def getVersion() {
if (env.BRANCH_NAME?.trim() && env.BRANCH_NAME.startsWith('v')) {
return env.BRANCH_NAME.replaceAll('v', '-ver-').replaceAll('\\.', '-')
}
return ''
}

/**
* Calculate the elastic.co release notes URL given the TAG release. Otherwise
* it returns the default current URL.
*/
def getReleaseNotesUrl() {
def baseUrl = 'https://www.elastic.co/guide/en/apm/agent/nodejs/current'
if (env.BRANCH_NAME?.trim() && env.BRANCH_NAME.startsWith('v')) {
def version = env.BRANCH_NAME.replaceAll('v', '')
def parts = version.split('\\.')
def major = parts[0]
return "${baseUrl}/release-notes-${major}.x.html#release-notes-${version}"
}
return baseUrl
}

def notifyStatus(def args = [:]) {
releaseNotification(slackChannel: "${env.SLACK_CHANNEL}",
slackColor: args.slackStatus,
slackCredentialsId: 'jenkins-slack-integration-token',
to: "${env.NOTIFY_TO}",
subject: args.subject,
body: args.body)
}
107 changes: 107 additions & 0 deletions .ci/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
SHELL = /bin/bash -eo pipefail

AWS_FOLDER = ../build/aws

export AWS_FOLDER

build:
rm -rf $(AWS_FOLDER) || true
mkdir -p $(AWS_FOLDER)
cd $(AWS_FOLDER); \
npm init -y; \
npm install --global-style https://github.com/elastic/apm-agent-nodejs#$(BRANCH_NAME); \
mkdir nodejs; \
mv node_modules nodejs
env:
env
dist: validate-branch-name build
rm -f $(BRANCH_NAME).zip || true
cd $(AWS_FOLDER) ; \
zip -r $(BRANCH_NAME).zip nodejs
Copy link
Member Author

Choose a reason for hiding this comment

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

Produces

image


# List all the AWS regions
get-all-aws-regions:
@mkdir -p $(AWS_FOLDER)
@aws \
ec2 \
describe-regions \
--region us-east-1 \
--output json \
--no-cli-pager \
| jq -r '.Regions[].RegionName' > $(AWS_FOLDER)/.regions

# Publish the given LAYER in all the AWS regions
publish-in-all-aws-regions: validate-layer-name get-all-aws-regions
@mkdir -p $(AWS_FOLDER)
@while read AWS_DEFAULT_REGION; do \
echo "publish '$(ELASTIC_LAYER_NAME)' in $${AWS_DEFAULT_REGION}"; \
AWS_DEFAULT_REGION="$${AWS_DEFAULT_REGION}" ELASTIC_LAYER_NAME=$(ELASTIC_LAYER_NAME) $(MAKE) publish > $(AWS_FOLDER)/$${AWS_DEFAULT_REGION}.publish; \
AWS_DEFAULT_REGION="$${AWS_DEFAULT_REGION}" ELASTIC_LAYER_NAME=$(ELASTIC_LAYER_NAME) $(MAKE) grant-public-layer-access; \
done < $(AWS_FOLDER)/.regions

# Publish the given LAYER in the given AWS region
publish: validate-layer-name validate-aws-default-region
@aws lambda \
--output json \
publish-layer-version \
--layer-name "$(ELASTIC_LAYER_NAME)" \
--description "AWS Lambda Extension Layer for the Elastic APM Node.js Agent" \
--license "Apache-2.0" \
--compatible-runtimes nodejs14.x nodejs12.x nodejs10.x \
--zip-file "fileb://./$(AWS_FOLDER)/$(BRANCH_NAME).zip"

# Grant public access to the given LAYER in the given AWS region
grant-public-layer-access: validate-layer-name validate-aws-default-region
@echo "[debug] $(ELASTIC_LAYER_NAME) with version: $$($(MAKE) -s --no-print-directory get-version)"
@aws lambda \
--output json \
add-layer-version-permission \
--layer-name "$(ELASTIC_LAYER_NAME)" \
--action lambda:GetLayerVersion \
--principal '*' \
--statement-id "$(ELASTIC_LAYER_NAME)" \
--version-number $$($(MAKE) -s --no-print-directory get-version) > $(AWS_FOLDER)/$(AWS_DEFAULT_REGION).public

# Get the ARN Version for the AWS_REGIONS
# NOTE: jq -r .Version "$(AWS_FOLDER)/$(AWS_DEFAULT_REGION)" fails in the CI
# with 'parse error: Invalid numeric literal at line 1, column 5'
get-version: validate-aws-default-region
@grep '"Version"' "$(AWS_FOLDER)/$(AWS_DEFAULT_REGION).publish" | cut -d":" -f2 | sed 's/ //g' | cut -d"," -f1

# Generate the file with the ARN entries
create-arn-file: validate-suffix-arn-file validate-release-notes-url
@./scripts/create-arn-table.sh

release-notes: validate-branch-name validate-suffix-arn-file
@gh release list
@gh \
release \
create $(BRANCH_NAME) \
--title '$(BRANCH_NAME)' \
--notes-file $(AWS_FOLDER)/$(SUFFIX_ARN_FILE) \
$(AWS_FOLDER)/$(BRANCH_NAME).zip

validate-branch-name:
ifndef BRANCH_NAME
$(error BRANCH_NAME is undefined)
endif

validate-suffix-arn-file:
ifndef SUFFIX_ARN_FILE
$(error SUFFIX_ARN_FILE is undefined)
endif

validate-layer-name:
ifndef ELASTIC_LAYER_NAME
$(error ELASTIC_LAYER_NAME is undefined)
endif

validate-aws-default-region:
ifndef AWS_DEFAULT_REGION
$(error AWS_DEFAULT_REGION is undefined)
endif

validate-release-notes-url:
ifndef RELEASE_NOTES_URL
$(error RELEASE_NOTES_URL is undefined)
endif
31 changes: 31 additions & 0 deletions .ci/scripts/create-arn-table.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
set -o pipefail

#
# Create the AWS ARN table given the below environment variables:
#
# - AWS_FOLDER - that's the location of the publish-layer-version output for each region.
# - SUFFIX_ARN_FILE - that's the output file to be stored in the AWS_FOLDER.
# - RELEASE_NOTES_URL - that's the URL for the changelog in the elastic.co
#

ARN_FILE=${SUFFIX_ARN_FILE}

{
echo "For more information, please see the [changelog](${RELEASE_NOTES_URL})."
echo ''
echo "### Elastic APM Node.js agent layer ARNs"
echo ''
echo '|Region|ARN|'
echo '|------|---|'
} > "${AWS_FOLDER}/${ARN_FILE}"


for f in "${AWS_FOLDER}"/*.publish; do
LAYER_VERSION_ARN=$(grep '"LayerVersionArn"' "${f}" | cut -d":" -f2- | sed 's/ //g' | sed 's/"//g' | cut -d"," -f1)
FILENAME=$(basename /"${f}" .publish)
echo "INFO: create-arn-table ARN(${LAYER_VERSION_ARN}):region(${FILENAME}))"
echo "|${FILENAME}|${LAYER_VERSION_ARN}|" >> "${AWS_FOLDER}/${ARN_FILE}"
done

echo '' >> "${AWS_FOLDER}/${ARN_FILE}"