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

Add image builder helper tools #22

Merged
merged 39 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ab35aaf
wip
Victoremepunto Sep 11, 2023
8e90226
first iteration
Victoremepunto Sep 13, 2023
116db05
first phase
Victoremepunto Sep 13, 2023
dcc61e3
Fix tests
Victoremepunto Sep 14, 2023
4e0d4c1
rename of libraries
Victoremepunto Sep 14, 2023
f90aaf3
fix for CI
Victoremepunto Sep 14, 2023
e60590a
fix shellcheck tips
Victoremepunto Sep 14, 2023
55d4dcf
fix workflow
Victoremepunto Sep 14, 2023
14de779
fix e2e tests
Victoremepunto Sep 14, 2023
0c1b975
full coverage
Victoremepunto Sep 14, 2023
7e13c8a
fix e2e test
Victoremepunto Sep 14, 2023
acb1089
Apply ShellCheck suggestions
Victoremepunto Sep 14, 2023
cf46e0e
refactor to add module setup phase
Victoremepunto Sep 15, 2023
c2b9abe
fix E2E tests
Victoremepunto Sep 15, 2023
2727d7f
Increase coverage
Victoremepunto Sep 15, 2023
3152994
Increased coverage
Victoremepunto Sep 18, 2023
5ec3077
increase coverage
Victoremepunto Sep 18, 2023
1c4881f
Update README.md
Victoremepunto Sep 18, 2023
557967d
Test for image_builder
Victoremepunto Sep 18, 2023
cc57df4
fix quotes
Victoremepunto Sep 18, 2023
b1d5270
wip
Victoremepunto Sep 20, 2023
d767571
tests fixed
Victoremepunto Sep 20, 2023
9ab473d
fix
Victoremepunto Sep 20, 2023
72b9ea3
small bits
Victoremepunto Sep 20, 2023
8943a34
renamed path
Victoremepunto Sep 20, 2023
a385a70
rename to build_and_push
Victoremepunto Sep 20, 2023
5343ffa
vertical order fix
Victoremepunto Sep 20, 2023
38f9c95
Add is_ci_context feature
Victoremepunto Sep 21, 2023
8f942fb
Add get_full_image_name feature
Victoremepunto Sep 21, 2023
5682f40
increase coverage
Victoremepunto Sep 21, 2023
30a835c
auto formatting
Victoremepunto Sep 25, 2023
a7b8072
reformat README
Victoremepunto Sep 25, 2023
d985946
Add note about style guide used
Victoremepunto Sep 28, 2023
e759cb9
rename from cicd_tools to cicd
Victoremepunto Sep 28, 2023
59fe7b0
Clarify usage of main and bootstrap scripts
Victoremepunto Sep 28, 2023
a2d833f
refactor build
Victoremepunto Sep 28, 2023
94d1504
Force new container registry credentials on CI context
Victoremepunto Sep 28, 2023
75308ee
use local_build as condition
Victoremepunto Sep 28, 2023
8d5dc07
Fix tests for local builds
Victoremepunto Sep 28, 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ tags

# End of https://www.toptal.com/developers/gitignore/api/vim
.cicd_tools
coverage
.idea
147 changes: 108 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,92 +1,161 @@
# CI/CD Tools

## Description

Utilities used to run smoke tests in an ephemeral environment within a CI/CD pipeline

## Getting Started
Grab the Jenkinsfile template for your [backend](examples/backend-pipeline-pr-checks/Jenkinsfile) or [frontend](examples/frontends-pipeline-pr-checks/Jenkinsfile) and cater it to your specific needs. This file should reside in your git repositories root directory. That Jenkinsfile will download the necessary files from this repository. It does not have a unit test file so that will need to be made in your repository. You can find a unit test template file [here](examples/unit_test_example.sh).

Grab the Jenkinsfile template for your [backend](examples/backend-pipeline-pr-checks/Jenkinsfile)
or [frontend](examples/frontends-pipeline-pr-checks/Jenkinsfile) and cater it to your specific
needs. This file should reside in your git repositories root directory. That Jenkinsfile will
download the necessary files from this repository. It does not have a unit test file so that will
need to be made in your repository. You can find a unit test template
file [here](examples/unit_test_example.sh).

## Scripts

| Script | Description |
| ----------------------- | ----------- |
| bootstrap.sh | Clone bonfire into workspace, setup python venv, modify PATH, login to container registries, login to Kube/OCP, and set envvars used by following scripts. |
| Script | Description |
|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| bootstrap.sh | Clone bonfire into workspace, setup python venv, modify PATH, login to container registries, login to Kube/OCP, and set envvars used by following scripts. |
| build.sh | Using docker (rhel7) or podman (else) build, tag, and push an image to Quay and Red Hat registries. If its a GitHub or GitLab PR/MR triggered script execution, tag image with `pr-123-SHA` and `pr-123-testing`, else use a short SHA for the target repo HEAD. |
| deploy_ephemeral_db.sh | Deploy using `bonfire process` and `<oc_wrapper> apply`, removing dependencies and setting up database envvars. |
| deploy_ephemeral_env.sh | Deploy using `bonfire deploy` into ephemeral, specifying app, component, and relevant image tag args. Passes `EXTRA_DEPLOY_ARGS` which can be set by the caller via pr_checks.sh.
| cji_smoke_test.sh | Run iqe-tests container for the relevant app plugin using `bonfire deploy-iqe-cji`. Waits for tests to complete, and fetches artifacts using minio.
| post_test_results.sh | Using artifacts fetched from `cji_smoke_test.sh`, add a GitHub status or GitLab comment linking to the relevant test results in Ibutsu.
| smoke_test.sh | **DEPRECATED**, use [cji_smoke_test.sh](cji_smoke_test.sh) |
| iqe_pod | **DEPRECATED**, use [cji_smoke_test.sh](cji_smoke_test.sh) |
| deploy_ephemeral_db.sh | Deploy using `bonfire process` and `<oc_wrapper> apply`, removing dependencies and setting up database envvars. |
| deploy_ephemeral_env.sh | Deploy using `bonfire deploy` into ephemeral, specifying app, component, and relevant image tag args. Passes `EXTRA_DEPLOY_ARGS` which can be set by the caller via pr_checks.sh. |
| cji_smoke_test.sh | Run iqe-tests container for the relevant app plugin using `bonfire deploy-iqe-cji`. Waits for tests to complete, and fetches artifacts using minio. |
| post_test_results.sh | Using artifacts fetched from `cji_smoke_test.sh`, add a GitHub status or GitLab comment linking to the relevant test results in Ibutsu. |
| smoke_test.sh | **DEPRECATED**, use [cji_smoke_test.sh](cji_smoke_test.sh) |
| iqe_pod | **DEPRECATED**, use [cji_smoke_test.sh](cji_smoke_test.sh) |

## Bash script helper scripts usage

The collection of helper scripts are expected to be loaded using the provided [src/bootstrap.sh](bootstrap) script.
The collection of helper libraries are expected to be loaded using the
provided [src/bootstrap.sh](bootstrap) script.

Currently, there are 2 supported libraries:

| Library ID | Description |
|---------------|----------------------------------------------------------------------------|
| container | Provides wrapper functions for invoking container engine agnostic commands |
| image_builder | Provides helper functions to simplify the image building process |

### How to use the helper libraries

This library is intended to be used to gather the most common shell scripts used in pipelines in a
centralized way. This should be helpful to reduce the amount of code needed to write the most common
operations in a pipeline for routine tasks, such as operating with containers or building container
images.

The [src/main.sh](main.sh) script is the main entrypoint and should be used to load the modules
included in this library. This script requires all the other scripts available in a local directory
following the same structure in this repository.

To use any of the provided libraries, you must source the [src/main.sh](main.sh) script
and pass the unique library ID to be loaded as a parameter.

There's two different approaches for loading these scripts, depending on if you're a contributor or
an end user.

#### Contributing to the repository

This is the intended way when developing new modules for this library. The recommended approach for
contributing is to create a new fork and then open a pull request against the `main` branch.

When working with a local copy of the repository, you should source the [src/main.sh](main.sh)
script directly.

Currently there is 1 collection available:
#### Using the library from other scripts

- Container helper scripts: provides wrapper functions for invoking container engine agnostic commands
There is an existing helper script named [src/bootstrap.sh](bootstrap) to help with sourcing the
[src/main.sh](main.sh) script if you're not contributing to this repo.

**This is the intended way of using this library from external projects**.

To use any of the provided libraries, you must source the [src/bootstrap.sh](bootstrap.sh) script.
One can simply either source the [src/bootstrap.sh](bootstrap) script directly:

```
$ source <(curl -sSL https://raw.githubusercontent.com/RedHatInsights/cicd-tools/main/src/bootstrap.sh)
$ container_engine_cmd --version
$ source <(curl -sSL https://raw.githubusercontent.com/RedHatInsights/cicd-tools/main/src/bootstrap.sh) container

$ cicd::container::cmd --version
podman version 4.6.1

```

In case you want to refactor some of your scripts using this library, here's a snippet you can use:
Or choose to be more specific and select a specific repository and branch name (useful for working
with forks and testing new WIP features)

The following is a snippet you can use to place on top of a script to load the helper module you
need:

```
load_cicd_helper_functions() {

local LIBRARY_TO_LOAD=${1:-all}
local LIBRARY_TO_LOAD="$1"
local CICD_TOOLS_REPO_BRANCH='main'
local CICD_TOOLS_REPO_ORG='RedHatInsights'
local CICD_TOOLS_URL="https://raw.githubusercontent.com/${CICD_TOOLS_REPO_ORG}/cicd-tools/${CICD_TOOLS_REPO_BRANCH}/src/bootstrap.sh"
set -e
source <(curl -sSL "$CICD_TOOLS_URL") "$LIBRARY_TO_LOAD"
set +e
}

load_cicd_helper_functions
load_cicd_helper_functions container
```

you can select which collection needs to load independently as a parameter:

```
source bootstrap.sh container_engine
source bootstrap.sh container
```

The bootstrap script will download the selected version of the CICD scripts (or `latest` if none specified) into the directory defined by
the `CICD_TOOLS_WORKDIR` variable (defaults to `.cicd_tools` in the current directory).
The bootstrap script will download the selected version of the CICD scripts (or `latest` if none
specified) into the directory defined by the `CICD_TOOLS_WORKDIR` variable (defaults
to `.cicd_tools` in the current directory).

**Please note** that when cloning the repo, the directory defined by the `CICD_TOOLS_WORKDIR` will be deleted!
**Please note** that when cloning the repo, the directory defined by the `CICD_TOOLS_WORKDIR` will
be deleted!
You can disable running the `git clone` by setting the `CICD_TOOLS_SKIP_GIT_CLONE` variable

The bootstrap.sh can be invoked multiple times but it has a status control to ensure each
of the libraries is loaded only once. This is to prevent potential issues with collections
that are not supposed to be loaded many times.
After loading the requested module the `CICD_TOOLS_WORKDIR` directory will be automatically removed
by the [src/bootstrap.sh](bootstrap) script.

the [src/bootstrap.sh](bootstrap) script can be invoked multiple times, but it has a status control
to ensure each of the libraries is loaded only once. This is to prevent potential issues with
collections that are not supposed to be loaded many times.

An example of this is the _container_ library, where the selected container engine
is **set only once the first command using the library helper function `cicd::container::cmd`
is used**.

Each of the libraries will export their functions and variables to the shell when sourcing the
bootstrap script the helper functions.

An example of this is the _container_engine_ library, where the selected container engine
is **set only once the first command using the library helper function `container_engine_cmd` is used**.
This library
follows [Google's Shell style guide](https://google.github.io/styleguide/shellguide.html), and the
functions are all namespaced to its corresponding module, meaning the names follow the naming
format:

```
cicd::library::function
```

where:

- *cicd* represents the namespace root, which is shared by all functions
- *library* would match with each of the imported library IDs.

## Template Scripts
| Script | Description |
| ----------------------- | ----------- |
| examples/backend-pipeline-pr-checks/Jenkinsfile | Templated example of the pr-check pipeline for backend apps |

| Script | Description |
|---------------------------------------------------|--------------------------------------------------------------|
| examples/backend-pipeline-pr-checks/Jenkinsfile | Templated example of the pr-check pipeline for backend apps |
| examples/frontends-pipeline-pr-checks/Jenkinsfile | Templated example of the pr-check pipeline for frontend apps |
| examples/pr_check_template.sh | |
| examples/unit_test_example.sh | |
| examples/unit_test_example_ephemeral_db.sh | |
| examples/pr_check_template.sh | |
| examples/unit_test_example.sh | |
| examples/unit_test_example_ephemeral_db.sh | |

## Contributing

Suggested method for testing changes to these scripts:

- Modify `bootstrap.sh` to `git clone` your fork and branch of bonfire.
- Open a PR in a repo using bonfire pr_checks and the relevant scripts, modifying `pr_check` script to clone your fork and branch of bonfire.
- Observe modified scripts running in the relevant CI/CD pipeline.
#
- Open a PR in a repo using bonfire pr_checks and the relevant scripts, modifying `pr_check` script
to clone your fork and branch of bonfire.
- Observe modified scripts running in the relevant CI/CD pipeline.
35 changes: 18 additions & 17 deletions src/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,37 @@ CICD_TOOLS_SKIP_CLEANUP=${CICD_TOOLS_SKIP_CLEANUP:-}

clone_cicd_tools_repo() {

if [ -d "${CICD_TOOLS_ROOTDIR}" ]; then
_delete_cicd_tools_rootdir
fi
if [ -d "${CICD_TOOLS_ROOTDIR}" ]; then
_delete_cicd_tools_rootdir
fi

git clone -q \
--branch "$CICD_TOOLS_REPO_BRANCH" \
"https://github.com/${CICD_TOOLS_REPO_ORG}/cicd-tools.git" "$CICD_TOOLS_ROOTDIR"
git clone -q \
--branch "$CICD_TOOLS_REPO_BRANCH" \
"https://github.com/${CICD_TOOLS_REPO_ORG}/cicd-tools.git" "$CICD_TOOLS_ROOTDIR"
}

_delete_cicd_tools_rootdir() {
echo "Removing existing CICD tools directory: '${CICD_TOOLS_ROOTDIR}'"
rm -rf "${CICD_TOOLS_ROOTDIR}"
cicd::debug "Removing existing CICD tools directory: '${CICD_TOOLS_ROOTDIR}'"
rm -rf "${CICD_TOOLS_ROOTDIR}"
}

cleanup() {
_delete_cicd_tools_rootdir
_delete_cicd_tools_rootdir
unset clone_cicd_tools_repo _delete_cicd_tools_rootdir cleanup
}

if [ -z "$CICD_TOOLS_SKIP_GIT_CLONE" ]; then
if ! clone_cicd_tools_repo; then
echo "couldn't clone cicd-tools repository!"
exit 1
fi
if ! clone_cicd_tools_repo; then
echo "couldn't clone cicd-tools repository!"
exit 1
fi
fi

# shellcheck source=src/main.sh
source "$CICD_TOOLS_SCRIPTS_DIR/main.sh" "$@" || exit 1
if [ -z "$CICD_TOOLS_SKIP_CLEANUP" ]; then
if ! cleanup; then
echo "couldn't perform cicd tools cleanup!"
exit 1
fi
if ! cleanup; then
echo "couldn't perform cicd tools cleanup!"
exit 1
fi
fi
72 changes: 49 additions & 23 deletions src/main.sh
Original file line number Diff line number Diff line change
@@ -1,38 +1,64 @@
#!/usr/bin/env bash

CICD_TOOLS_COMMON_LOADED=${CICD_TOOLS_COMMON_LOADED:-1}
CICD_TOOLS_CONTAINER_ENGINE_LOADED=${CICD_TOOLS_CONTAINER_ENGINE_LOADED:-1}
CICD_TOOLS_COMMON_LIB_LOADED=${CICD_TOOLS_COMMON_LIB_LOADED:-1}
CICD_TOOLS_CONTAINER_LIB_LOADED=${CICD_TOOLS_CONTAINER_LIB_LOADED:-1}
CICD_TOOLS_DEBUG="${CICD_TOOLS_DEBUG:-}"
# https://stackoverflow.com/a/246128
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
CICD_TOOLS_SCRIPTS_DIR="${CICD_TOOLS_SCRIPTS_DIR:-$SCRIPT_DIR}"
LIB_TO_LOAD=${1:-all}
LIB_TO_LOAD=${1:-container}

load_library() {
cicd::debug() {
if cicd::_debug_mode; then
cicd::log "$*"
fi
}

cicd::_debug_mode() {
[[ -n "$CICD_TOOLS_DEBUG" ]]
}

cicd::log() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*"
}

case $LIB_TO_LOAD in
cicd::err() {
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}

cicd::load_library() {

all)
_load_all
;;
container_engine)
_load_container_engine
;;
*) echo "Unsupported library: '$LIB_TO_LOAD'"
return 1
case $LIB_TO_LOAD in
all) cicd::_load_all ;;
common) cicd::_load_common_lib ;;
container) cicd::_load_container_lib ;;
image_builder) cicd::_load_image_builder_lib ;;
*) cicd::err "Unsupported library: '$LIB_TO_LOAD'" && return 1 ;;
esac
}

cicd::_load_all() {
cicd::_load_common_lib
cicd::_load_container_lib
cicd::_load_image_builder_lib
}

esac
cicd::_load_common_lib() {
# shellcheck source=src/shared/common_lib.sh
source "${CICD_TOOLS_SCRIPTS_DIR}/shared/common_lib.sh"
}

_load_all() {
_load_container_engine
cicd::_load_container_lib() {
cicd::_load_common_lib
# shellcheck source=src/shared/container_lib.sh
source "${CICD_TOOLS_SCRIPTS_DIR}/shared/container_lib.sh"
}

_load_container_engine() {
# shellcheck source=src/shared/common.sh
source "${CICD_TOOLS_SCRIPTS_DIR}/shared/common.sh"
# shellcheck source=src/shared/container-engine-lib.sh
source "${CICD_TOOLS_SCRIPTS_DIR}/shared/container-engine-lib.sh"
cicd::_load_image_builder_lib() {
cicd::_load_common_lib
cicd::_load_container_lib
# shellcheck source=src/shared/image_builder_lib.sh
source "${CICD_TOOLS_SCRIPTS_DIR}/shared/image_builder_lib.sh"
}

load_library "$LIB_TO_LOAD"
cicd::load_library "$LIB_TO_LOAD"
30 changes: 0 additions & 30 deletions src/shared/common.sh

This file was deleted.

Loading