Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
aed1851
Script to sign and publish package
mrodm Mar 6, 2023
19c8f7a
Add bucket name
mrodm Mar 6, 2023
3433d87
Fix env var
mrodm Mar 6, 2023
cdbfbe6
Fix var
mrodm Mar 6, 2023
2cbfce1
Remove duplicated gcloud
mrodm Mar 6, 2023
1f5be27
Show custom message
mrodm Mar 6, 2023
8475771
Add depends_on key
mrodm Mar 6, 2023
aeff851
use paths
mrodm Mar 6, 2023
c795a30
Download all files from build/packages/
mrodm Mar 6, 2023
6005807
Use ls to loop files
mrodm Mar 6, 2023
0ab3aca
Remove hello step
mrodm Mar 6, 2023
8dc0cbe
show artifacts
mrodm Mar 6, 2023
d56742c
buildkite downloads artifacts with the same folder structure
mrodm Mar 6, 2023
9924b03
Update field for secret
mrodm Mar 6, 2023
72273b8
Show bucket path
mrodm Mar 6, 2023
4219d2a
Show bucket path
mrodm Mar 6, 2023
c06cde6
Force testing triggering Jenkins job
mrodm Mar 7, 2023
6d64c71
Add golang instalation
mrodm Mar 7, 2023
693d072
Add workspace var
mrodm Mar 7, 2023
6e3b29d
Add SETUP_GVM_VERSION var
mrodm Mar 7, 2023
acecf2f
Update PATH
mrodm Mar 7, 2023
0229dde
Fix errors in jenkins command
mrodm Mar 7, 2023
8b5086b
Remove extra var
mrodm Mar 7, 2023
00d771e
Test with other vault path
mrodm Mar 7, 2023
340e69b
Update to 10 secs to check for jenkins status
mrodm Mar 7, 2023
5e733e7
Add tooling script
mrodm Mar 7, 2023
1e02593
Add silent parameter to curl
mrodm Mar 7, 2023
b15e5d3
Update vault path
mrodm Mar 14, 2023
78e8fc1
Add Fatalf
mrodm Mar 14, 2023
5b1a596
Fix jenkins job name
mrodm Mar 14, 2023
1bbc052
Add new parameter --folder
mrodm Mar 14, 2023
f6153a2
Return error if job fails
mrodm Mar 14, 2023
3d7beb8
Fix var name
mrodm Mar 14, 2023
334ee6e
Remove messages in google cloud auth command
mrodm Mar 14, 2023
c7e7ada
Remove trailing slash
mrodm Mar 14, 2023
4e8f311
Ensure files are uploaded into folders in buckets
mrodm Mar 14, 2023
a48db31
Rename step
mrodm Mar 15, 2023
7f9fb9d
Update .buildkite/scripts/triggerJenkinsJob/jenkins/jenkins.go
mrodm Mar 15, 2023
757ddf2
Add base template folder variable
mrodm Mar 16, 2023
613f5c8
Update vault paths
mrodm Mar 16, 2023
fa6b28e
Rename secret var
mrodm Mar 16, 2023
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
8 changes: 8 additions & 0 deletions .buildkite/hooks/pre-command
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ GCP_SERVICE_ACCOUNT_SECRET_PATH=secret/ci/elastic-elastic-package/gcp-service-ac
AWS_SERVICE_ACCOUNT_SECRET_PATH=kv/ci-shared/platform-ingest/aws_account_auth
GITHUB_TOKEN_VAULT_PATH=kv/ci-shared/platform-ingest/github_token
JENKINS_API_TOKEN_PATH=kv/ci-shared/platform-ingest/jenkins_api_tokens
SIGNING_PACKAGES_GCS_CREDENTIALS_PATH=kv/ci-shared/platform-ingest/signing_packages_gcs_artifacts_credentials
PACKAGE_UPLOADER_GCS_CREDENTIALS_PATH=kv/ci-shared/platform-ingest/package_storage_uploader
Comment on lines +29 to +30
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved to shared path and renamed variables


# Secrets must be redacted
# https://buildkite.com/docs/pipelines/managing-log-output#redacted-environment-variables
Expand Down Expand Up @@ -56,4 +58,10 @@ if [[ "$BUILDKITE_PIPELINE_SLUG" == "elastic-package-package-storage-publish" &&
export JENKINS_USERNAME_SECRET=$(retry 5 vault kv get -field username ${JENKINS_API_TOKEN_PATH})
export JENKINS_HOST_SECRET=$(retry 5 vault kv get -field internal_ci_host ${JENKINS_API_TOKEN_PATH})
export JENKINS_TOKEN=$(retry 5 vault kv get -field internal_ci ${JENKINS_API_TOKEN_PATH})

# signing job
export SIGNING_PACKAGES_GCS_CREDENTIALS_SECRET=$(retry 5 vault kv get -field value ${SIGNING_PACKAGES_GCS_CREDENTIALS_PATH})

# publishing job
export PACKAGE_UPLOADER_GCS_CREDENTIALS_SECRET=$(retry 5 vault kv get -field value ${PACKAGE_UPLOADER_GCS_CREDENTIALS_PATH})
fi
12 changes: 8 additions & 4 deletions .buildkite/pipeline.package-storage-publish.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
steps:
- label: "Example Test"
command: echo "Hello!"
env:
SETUP_GVM_VERSION: 'v0.5.0' # https://github.com/andrewkroh/gvm/issues/44#issuecomment-1013231151

steps:
- label: ":go: Build package"
key: build-package
command:
Expand All @@ -11,10 +11,14 @@ steps:
image: "golang:1.19.5"
cpu: "8"
memory: "4G"
artifact_paths:
- build/packages/*.zip

- label: "Test"
- label: "Sign and Publish package"
key: sign-publish
command: ".buildkite/scripts/signAndPublishPackage.sh"
depends_on:
- build-package
agents:
provider: "gcp"
image: family/core-ubuntu-2004
35 changes: 35 additions & 0 deletions .buildkite/scripts/install_deps.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

set -euo pipefail

source .buildkite/scripts/tooling.sh

with_kubernetes() {
mkdir -p ${WORKSPACE}/bin
retry 5 curl -sSLo ${WORKSPACE}/bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64"
chmod +x ${WORKSPACE}/bin/kind
kind version
which kind

mkdir -p ${WORKSPACE}/bin
retry 5 curl -sSLo ${WORKSPACE}/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl"
chmod +x ${WORKSPACE}/bin/kubectl
kubectl version --client
which kubectl
}

with_go() {
mkdir -p ${WORKSPACE}/bin
retry 5 curl -sL -o ${WORKSPACE}/bin/gvm "https://github.com/andrewkroh/gvm/releases/download/${SETUP_GVM_VERSION}/gvm-linux-amd64"
chmod +x ${WORKSPACE}/bin/gvm
eval "$(gvm $(cat .go-version))"
go version
which go
}

with_docker_compose() {
mkdir -p ${WORKSPACE}/bin
retry 5 curl -SL -o ${WORKSPACE}/bin/docker-compose "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64"
chmod +x ${WORKSPACE}/bin/docker-compose
docker-compose version
}
33 changes: 1 addition & 32 deletions .buildkite/scripts/integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,38 +13,7 @@ usage() {
echo -e "\t-h: Show this message"
}

with_kubernetes() {
# FIXME add retry logic
mkdir -p ${WORKSPACE}/bin
curl -sSLo ${WORKSPACE}/bin/kind "https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-linux-amd64"
chmod +x ${WORKSPACE}/bin/kind
kind version
which kind

mkdir -p ${WORKSPACE}/bin
curl -sSLo ${WORKSPACE}/bin/kubectl "https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl"
chmod +x ${WORKSPACE}/bin/kubectl
kubectl version --client
which kubectl
}

with_go() {
# FIXME add retry logic
mkdir -p ${WORKSPACE}/bin
curl -sL -o ${WORKSPACE}/bin/gvm "https://github.com/andrewkroh/gvm/releases/download/${SETUP_GVM_VERSION}/gvm-linux-amd64"
chmod +x ${WORKSPACE}/bin/gvm
eval "$(gvm $(cat .go-version))"
go version
which go
}

with_docker_compose() {
# FIXME add retry logic
mkdir -p ${WORKSPACE}/bin
curl -SL -o ${WORKSPACE}/bin/docker-compose "https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64"
chmod +x ${WORKSPACE}/bin/docker-compose
docker-compose version
}
source .buildkite/scripts/install_deps.sh

TARGET=""
PACKAGE=""
Expand Down
158 changes: 157 additions & 1 deletion .buildkite/scripts/signAndPublishPackage.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
#!/bin/bash
set -euo pipefail

WORKSPACE="$(pwd)"
TMP_FOLDER_TEMPLATE_BASE="tmp.elastic-package"

cleanup() {
echo "Deleting temporal files..."
cd ${WORKSPACE}
rm -rf ${TMP_FOLDER_TEMPLATE_BASE}.*
echo "Done."
}

trap cleanup EXIT

export PATH="${WORKSPACE}/bin:${PATH}"

echo "Checking gsutil command..."
if ! command -v gsutil &> /dev/null ; then
echo "⚠️ gsutil is not installed"
Expand All @@ -9,4 +23,146 @@ else
echo "✅ gsutil is installed"
fi

gsutil help
source .buildkite/scripts/install_deps.sh
source .buildkite/scripts/tooling.sh

isAlreadyPublished() {
local packageZip=$1

if curl -s --head https://package-storage.elastic.co/artifacts/packages/${packageZip} | grep -q "HTTP/2 200" ; then
echo "- Already published ${packageZip}"
return 0
fi
echo "- Not published ${packageZip}"
return 1
}

REPO_NAME=$(repoName "${BUILDKITE_REPO}")
BUILD_TAG="buildkite-${BUILDKITE_PIPELINE_SLUG}-${BUILDKITE_BUILD_NUMBER}"

REPO_BUILD_TAG="${REPO_NAME}/${BUILD_TAG}"

BUILD_PACKAGES_PATH="build/packages"
TMP_FOLDER_TEMPLATE="${TMP_FOLDER_TEMPLATE_BASE}.XXXXXXXXX"
JENKINS_TRIGGER_PATH=".buildkite/scripts/triggerJenkinsJob"
GOOGLE_CREDENTIALS_FILENAME="google-cloud-credentials.json"

## Signing
INFRA_SIGNING_BUCKET_NAME='internal-ci-artifacts'
INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_SUBFOLDER="${REPO_BUILD_TAG}/signed-artifacts"
INFRA_SIGNING_BUCKET_ARTIFACTS_PATH="gs://${INFRA_SIGNING_BUCKET_NAME}/${REPO_BUILD_TAG}"
INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_PATH="gs://${INFRA_SIGNING_BUCKET_NAME}/${INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_SUBFOLDER}"

## Publishing
PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH="gs://elastic-bekitzur-package-storage-internal/queue-publishing/${REPO_BUILD_TAG}"


google_cloud_auth_signing() {
local gsUtilLocation=$(mktemp -d -p . -t ${TMP_FOLDER_TEMPLATE})

local secretFileLocation=${gsUtilLocation}/${GOOGLE_CREDENTIALS_FILENAME}
echo "${SIGNING_PACKAGES_GCS_CREDENTIALS_SECRET}" > ${secretFileLocation}

google_cloud_auth "${secretFileLocation}"

echo "${gsUtilLocation}"
}

google_cloud_auth_publishing() {
local gsUtilLocation=$(mktemp -d -p . -t ${TMP_FOLDER_TEMPLATE})

local secretFileLocation=${gsUtilLocation}/${GOOGLE_CREDENTIALS_FILENAME}
echo "${PACKAGE_UPLOADER_GCS_CREDENTIALS_SECRET}" > ${secretFileLocation}

google_cloud_auth "${secretFileLocation}"

echo "${gsUtilLocation}"
}

signPackage() {
local package=${1}
local packageZip=$(basename ${package})

local gsUtilLocation=$(google_cloud_auth_signing)

# upload zip package (trailing forward slashes are required)
echo "Upload package .zip file for signing ${package} to ${INFRA_SIGNING_BUCKET_ARTIFACTS_PATH}"
gsutil cp ${package} "${INFRA_SIGNING_BUCKET_ARTIFACTS_PATH}/"

echo "Trigger Jenkins job for signing package ${packageZip}"
pushd ${JENKINS_TRIGGER_PATH} > /dev/null

go run main.go \
--jenkins-job sign \
--folder ${INFRA_SIGNING_BUCKET_ARTIFACTS_PATH}

sleep 5
popd > /dev/null

echo "Download signatures"
gsutil cp "${INFRA_SIGNING_BUCKET_SIGNED_ARTIFACTS_PATH}/${packageZip}.asc" "${BUILD_PACKAGES_PATH}"

echo "Rename asc to sig"
for f in $(ls ${BUILD_PACKAGES_PATH}/*.asc); do
mv "$f" "${f%.asc}.sig"
done

ls -l "${BUILD_PACKAGES_PATH}"

echo "Removing temporal location ${gsUtilLocation}"
rm -r "${gsUtilLocation}"
}

publishPackage() {
local package=$1
local packageZip=$(basename ${package})

# create file with credentials
local gsUtilLocation=$(google_cloud_auth_publishing)

# upload files (trailing forward slashes are required)
echo "Upload package .zip file ${package} to ${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}"
gsutil cp ${package} "${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}/"
echo "Upload package .sig file ${package}.sig to ${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}"
gsutil cp ${package}.sig "${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}/"

echo "Trigger Jenkins job for publishing package ${packageZip}"
pushd ${JENKINS_TRIGGER_PATH} > /dev/null

go run main.go \
--jenkins-job publish \
--package "${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}/${packageZip}" \
--signature "${PACKAGE_STORAGE_INTERNAL_BUCKET_QUEUE_PUBLISHING_PATH}/${packageZip}.sig"

sleep 5

popd > /dev/null

echo "Removing temporal location ${gsUtilLocation}"
rm -r "${gsUtilLocation}"
}

# Required to trigger Jenkins job
with_go

# download package artifact from previous step
mkdir -p "${BUILD_PACKAGES_PATH}"

buildkite-agent artifact download "${BUILD_PACKAGES_PATH}/*.zip" --step build-package .
echo "Show artifacts downloaded from previous step ${BUILD_PACKAGES_PATH}"
ls -l "${BUILD_PACKAGES_PATH}"

for package in $(ls ${BUILD_PACKAGES_PATH}/*.zip); do
echo "isAlreadyInstalled ${package}?"
packageZip=$(basename ${package})
if isAlreadyPublished ${packageZip} ; then
echo "Skipping. ${packageZip} already published"
continue
fi

echo "Signing package ${packageZip}"
signPackage "${package}"

echo "Publishing package ${packageZip}"
publishPackage "${package}"
done
Copy link
Member

Choose a reason for hiding this comment

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

Will something like this pipeline work to publish packages from integrations repositories?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, something like this script would be the steps to be used/followed in integrations (iterating for each package defined) or other repositories like endpoint-package or apm-server.

39 changes: 39 additions & 0 deletions .buildkite/scripts/tooling.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
set -euo pipefail

repoName() {
# Example of URL: git@github.com:acme-inc/my-project.git
local repoUrl=$1

orgAndRepo=$(echo $repoUrl | cut -d':' -f 2)
echo "$(basename ${orgAndRepo} .git)"
}

google_cloud_auth() {
local keyFile=$1

gcloud auth activate-service-account --key-file ${keyFile} 2> /dev/null

export GOOGLE_APPLICATIONS_CREDENTIALS=${secretFileLocation}
}

retry() {
local retries=$1
shift

local count=0
until "$@"; do
exit=$?
wait=$((2 ** count))
count=$((count + 1))
if [ $count -lt "$retries" ]; then
>&2 echo "Retry $count/$retries exited $exit, retrying in $wait seconds..."
sleep $wait
else
>&2 echo "Retry $count/$retries exited $exit, no more retries left."
return $exit
fi
done
return 0
}

14 changes: 10 additions & 4 deletions .buildkite/scripts/triggerJenkinsJob/jenkins/jenkins.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ func (j *JenkinsClient) RunJob(ctx context.Context, jobName string, async bool,
return fmt.Errorf("not finished job %s/%d: %w", jobName, build.GetBuildNumber(), err)
}

log.Printf("Build %s finished with result: %v\n", build.GetUrl(), build.GetBuildNumber(), build.GetResult())
log.Printf("Build %s finished with result: %s\n", build.GetUrl(), build.GetResult())

if build.GetResult() != gojenkins.STATUS_SUCCESS {
return fmt.Errorf("build %s finished with result %s", build.GetUrl(), build.GetResult())
}
return nil
}

Expand Down Expand Up @@ -94,16 +98,18 @@ func (j *JenkinsClient) getBuildFromQueueID(ctx context.Context, job *gojenkins.
}

func (j *JenkinsClient) waitForBuildFinished(ctx context.Context, build *gojenkins.Build) error {
const waitingPeriod = 10000 * time.Millisecond
for build.IsRunning(ctx) {
log.Printf("Build still running, waiting for 5 secs...")
log.Printf("Build still running, waiting for %s...", waitingPeriod)
select {
case <-time.After(5000 * time.Millisecond):
case <-time.After(waitingPeriod):
case <-ctx.Done():
return ctx.Err()
}
_, err = build.Poll(ctx)
_, err := build.Poll(ctx)
if err != nil {
return err
}
}
return nil
}
Loading