diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..485dee64bcfb48793379b200a1afd14e85a8aaf4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/ci-wrappers.sh b/ci-wrappers.sh index 3224e8c53faa0d607f1cca86a0812d37a1e94d37..3a2e0760da825abe587c2542e2b73719d758f3ca 100644 --- a/ci-wrappers.sh +++ b/ci-wrappers.sh @@ -1,21 +1,38 @@ -#!/bin/bash +#!/usr/bin/env bash _B_TITLE='\033[0;33m' _E_TITLE='\033[0;0m' -VAGRANT_VERSION=2.3.3 -TERRAFORM_VERSION=1.3.6 -DOCKER_CLIENT_VERSION=20.10.19 -DOCKER_COMPOSE_VERSION=2.13.0 +_create_config() ( + # Create or update default config file + mkdir -p "${HOME}/.ci-wrappers/" + cat >!"${HOME}/.ci-wrappers/config" <<END +CI_VAGRANT_VERSION=2.3.4 +CI_TERRAFORM_VERSION=1.3.6 +CI_DOCKER_CLIENT_VERSION=20.10.19 +CI_DOCKER_COMPOSE_VERSION=2.13.0 +CI_GH_CLI_VERSION=2.20.2 -MAVEN_DEFAULT_IMAGE="brunoe/maven:3.8.6-eclipse-temurin-17" -JAVA_DEFAULT_ARCHETYPE_GROUPID="fr.univtln.bruno.demos.archetypes" -JAVA_DEFAULT_ARCHETYPE_ARTIFACTID="demomavenarchetype" -JAVA_DEFAULT_ARCHETYPE_VERSION="1.1-SNAPSHOT" +CI_MAVEN_DEFAULT_IMAGE="brunoe/maven:3.8.6-eclipse-temurin-17" +CI_JAVA_DEFAULT_ARCHETYPE_GROUPID="fr.univtln.bruno.demos.archetypes" +CI_JAVA_DEFAULT_ARCHETYPE_ARTIFACTID="demomavenarchetype" +CI_JAVA_DEFAULT_ARCHETYPE_VERSION="1.1-SNAPSHOT" + +export CI_WRAPPERS_HOME="\${CI_WRAPPERS_HOME:-\${HOME}/.ci-wrappers}" +export DOCKER_CONFIG="\$CI_WRAPPERS_HOME/.docker" +END +) + +_create_config + +_init() { + _create_config + source "${HOME}/.ci-wrappers/config" +} ci-wrappers-usage() { - echo "install-dockerclient-vagrant-terraform\n\t installs a docker client, vagant and terraform in ${HOME}/bin" - echo "new-java-project [projectname]\n\t create a new java+maven project ready for CI" + printf 'install-dockerclient-vagrant-terraform\n\t installs a docker client, vagant and terraform in %s/bin\n'"${HOME}" + printf "new-java-project [projectname]\n\t create a new java+maven project ready for CI\n" echo "docker-wrapper" echo "docker-wrapper-build" echo "docker-wrapper-build-all" @@ -24,41 +41,63 @@ ci-wrappers-usage() { echo "docker-sonar-analysis" } -install-dockerclient-vagrant-terraform() { - mkdir -p ${HOME}/bin && - dockerCurrentVersion=$(docker --version|cut -d " " -f 3|tr -d ',') - if [ -f ${HOME}/bin/docker ]; then - curl -sL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_CLIENT_VERSION}.tgz | - tar --directory=${HOME}/bin/ --strip-components=1 -zx docker/docker && - chmod +x ${HOME}/bin/docker - else - echo "docker client already installed" - fi - if [ -f ${HOME}/.docker/cli-plugins/docker-compose ]; then - mkdir -p ${HOME}/.docker/cli-plugins/ && - curl -SL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ${HOME}/.docker/cli-plugins/docker-compose && - chmod +x ${HOME}/.docker/cli-plugins/docker-compose +install-ci-software() { + _init + + if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi + mkdir -p "${CI_WRAPPERS_HOME}"/bin + #Ensure that tools are in PATH + [[ ":$PATH:" != *":${CI_WRAPPERS_HOME}/bin:"* ]] && PATH="${CI_WRAPPERS_HOME}/bin:${PATH}" + + _version_gh() ("${CI_WRAPPERS_HOME}"/bin/gh --version | head -n 1 | cut -d ' ' -f 3) + if [ ! -f "${CI_WRAPPERS_HOME}"/bin/gh ] || [ "$(_version_gh)" != "${CI_GH_CLI_VERSION}" ]; then + echo "Installing gh client ${CI_GH_CLI_VERSION}" && + curl -sL "https://github.com/cli/cli/releases/download/v${CI_GH_CLI_VERSION}/gh_${CI_GH_CLI_VERSION}_linux_amd64.tar.gz" | + tar --directory="${CI_WRAPPERS_HOME}/bin/" --strip-components=2 -zx "gh_${CI_GH_CLI_VERSION}_linux_amd64/bin/gh" && + chmod +x "${CI_WRAPPERS_HOME}/bin/gh" else - echo "docker compose already installed" + echo "GitHub CLI already installed : $(_version_gh)" fi - if [ -f ${HOME}/bin/vagrant ]; then - export PATH=${HOME}/bin:$PATH && - wget -qO- https://releases.hashicorp.com/vagrant/${vagrant_VAGRANT_VERSION}/${vagrant_VAGRANT_VERSION}_linux_amd64.zip | gunzip - \ - >${HOME}/bin/vagrant && - chmod +x ${HOME}/bin/vagrant + _version_docker() ("${CI_WRAPPERS_HOME}"/bin/docker --version | cut -d " " -f 3 | tr -d ',') + if [ ! -f "${CI_WRAPPERS_HOME}"/bin/docker ] || [ "$(_version_docker)" != "${CI_DOCKER_CLIENT_VERSION}" ]; then + echo "Installing docker client ${CI_DOCKER_CLIENT_VERSION}" + curl -sL "https://download.docker.com/linux/static/stable/x86_64/docker-${CI_DOCKER_CLIENT_VERSION}.tgz" | + tar --directory="${CI_WRAPPERS_HOME}/bin/" --strip-components=1 -zx docker/docker && + chmod +x "${CI_WRAPPERS_HOME}/bin/docker" else - echo "vagrant already installed" + echo "docker client already installed $(_version_docker)" fi - if [ -f ${HOME}/bin/terraform ]; then - export PATH=${HOME}/bin:$PATH && - wget -qO- https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip | gunzip - \ - >${HOME}/bin/terraform && - chmod +x ${HOME}/bin/terraform + _version_dockercompose() ("${DOCKER_CONFIG}"/cli-plugins/docker-compose --version | sed 's/^[^0-9]*\([0-9][0-9\.]*\)[^0-9]*$/\1/g') + if [ ! -f "${CI_WRAPPERS_HOME}"/.docker/cli-plugins/docker-compose ] || [ "$(_version_dockercompose)" != "${CI_DOCKER_COMPOSE_VERSION}" ]; then + echo "Installing docker compose plugin ${CI_DOCKER_COMPOSE_VERSION}" + mkdir -p "${CI_WRAPPERS_HOME}"/.docker/cli-plugins/ && + curl -sL "https://github.com/docker/compose/releases/download/v${CI_DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64" \ + -o "${DOCKER_CONFIG}"/cli-plugins/docker-compose && + chmod +x "${DOCKER_CONFIG}"/cli-plugins/docker-compose + else + echo "Docker compose plugin already installed $(_version_dockercompose)" + fi + + _version_vagrant() ("${CI_WRAPPERS_HOME}"/bin/vagrant --version | sed 's/^[^0-9]*\([0-9][0-9\.]*\)[^0-9]*$/\1/g') + if [ ! -f "${CI_WRAPPERS_HOME}"/bin/vagrant ] || [ "$(_version_vagrant)" != "${CI_VAGRANT_VERSION}" ]; then + echo "Installing vagrant ${CI_VAGRANT_VERSION}" + curl -sL "https://releases.hashicorp.com/vagrant/${CI_VAGRANT_VERSION}/vagrant_${CI_VAGRANT_VERSION}_linux_amd64.zip" | + gunzip - >"${CI_WRAPPERS_HOME}/bin/vagrant" && + chmod +x "${CI_WRAPPERS_HOME}/bin/vagrant" else - echo "terraform already installed" + echo "Vagrant already installed $(_version_vagrant)" fi + _version_terraform() ("${CI_WRAPPERS_HOME}"/bin/terraform --version | head -n 1 | sed 's/^[^0-9]*\([0-9][0-9\.]*\)[^0-9]*$/\1/g') + if [ ! -f "${CI_WRAPPERS_HOME}"/bin/terraform ] || [ "$(_version_terraform)" != "${CI_TERRAFORM_VERSION}" ]; then + echo "Installing terraform ${CI_TERRAFORM_VERSION}" + curl -sL "https://releases.hashicorp.com/terraform/${CI_TERRAFORM_VERSION}/terraform_${CI_TERRAFORM_VERSION}_linux_amd64.zip" | + gunzip - >"${CI_WRAPPERS_HOME}/bin/terraform" && + chmod +x "${CI_WRAPPERS_HOME}"/bin/terraform + else + echo "Terraform already installed $(_version_terraform)" + fi } provision-docker-engine() { @@ -66,29 +105,19 @@ provision-docker-engine() { } _moveVBoxDefaultFolder() { - targetdirectory=${1:-/scratch/${USER}} + targetDirectory=${1:-/scratch/${USER}} VBoxManage list systemproperties | grep "Current default machine folder:" && - mkdir -p ${targetirectory} && - vboxmanage setproperty machinefolder ${targetirectory}/VirtualBox\ VMs && + mkdir -p "${targetDirectory}" && + vboxmanage setproperty machinefolder "${targetDirectory}"/VirtualBox\ VMs && echo -n "New " && VBoxManage list systemproperties | grep "Default machine folder:" } -_check_needed_software() { - for c in docker vagrant; do - if [ -x "$(command -v ${c})" ]; then - echo $c not found - else - echo $c found - fi - done -} - _check_needed_variables() { _check_variables GITHUBLOGIN GITHUBTOKEN GITHUB_ORG SONAR_URL SONAR_TOKEN } _check_variables() { - if [ -n "$ZSH_VERSION" ]; then emulate -L bash; fi + if [ -n "$ZSH_VERSION" ]; then emulate -L ksh; fi for varname in "$@"; do v="${!varname}" if [ ! -n "${v-unset}" ]; then @@ -101,7 +130,7 @@ _check_variables() { # This utility function computes the image name and tag from the project directory and the git branch. _docker_env() { DOCKER_REPO_NAME=${GITHUB_ORG} - IMAGE_NAME=$(echo ${PWD##*/} | tr '[:upper:]' '[:lower:]') + IMAGE_NAME=$(echo "${PWD##*/}" | tr '[:upper:]' '[:lower:]') IMAGE_TAG=$(git rev-parse --abbrev-ref HEAD) DOCKER_TARGET=${DOCKER_TARGET:-finalJLinkAlpine} DOCKER_FULL_IMAGE_NAME="$DOCKER_REPO_NAME/$IMAGE_NAME:$IMAGE_TAG-$DOCKER_TARGET" @@ -171,24 +200,23 @@ docker-mvn() ( _docker_env docker run \ --env IMAGE_NAME="$IMAGE_NAME" \ - --env GITHUB_LOGIN="$GITHUB_LOGIN" \ - --env GITHUB_TOKEN="$GITHUB_TOKEN" \ + --env GITHUB_LOGIN="$GITHUBLOGIN" \ + --env GITHUB_TOKEN="$GITHUBTOKEN" \ --env SONAR_URL="$SONAR_URL" \ --env SONAR_TOKEN="$SONAR_TOKEN" \ --env SONAR_URL="$SONAR_URL" \ --env SONAR_TOKEN="$SONAR_TOKEN" \ --env S6_LOGGING=1 \ --env S6_BEHAVIOUR_IF_STAGE2_FAILS \ - --volume ${HOME}/.m2:/home/user/.m2 \ - --volume ${HOME}/.ssh:/home/user/.ssh \ - --volume ${HOME}/.gitconfig:/home/user/.gitconfig \ - --volume "$ - }(pwd)":/usr/src/mymaven \ + --volume "${HOME}/.m2":"/home/user/.m2" \ + --volume "${HOME}/.ssh":"/home/user/.ssh" \ + --volume "${HOME}/.gitconfig":"/home/user/.gitconfig" \ + --volume "$(pwd)":"/usr/src/mymaven" \ --workdir /usr/src/mymaven \ --rm \ - --env PUID=$(id -u) -e PGID=$(id -g) \ + --env PUID="$(id -u)" -e PGID="$(id -g)" \ --env MAVEN_CONFIG=/home/user/.m2 \ - "${MAVEN_IMAGE:-${MAVEN_DEFAULT_IMAGE}}" \ + "${MAVEN_IMAGE:-${CI_MAVEN_DEFAULT_IMAGE}}" \ runuser --user user \ --group user \ -- mvn --errors --threads 1C --color always --strict-checksums \ @@ -198,82 +226,85 @@ docker-mvn() ( docker-sonar-analysis() ( docker-mvn -P jacoco,sonar \ - -Dsonar.branch.name=$(git rev-parse --abbrev-ref HEAD | tr / _) \ + -Dsonar.branch.name="$(git rev-parse --abbrev-ref HEAD | tr / _)" \ verify sonar:sonar ) new-java-project() ( - printf "${_B_TITLE}Creating Java project ${_E_TITLE}" if [[ ! $# -eq 2 ]]; then - echo "Usage: $0 <projectname> <groupid>" + echo "Usage: $0 <projectname> <groupid> [version]" exit 1 fi + + _init + + PROJECT_NAME=$(echo "$1" | tr '[:upper:]' '[:lower:]') + GROUP_ID=$(echo "$2" | tr '[:upper:]' '[:lower:]') + VERSION="${3:-1.0-SNAPSHOT}" + + printf "${_B_TITLE}Creating Java project${_E_TITLE}\n" + printf "\t Archetype : ${CI_JAVA_DEFAULT_ARCHETYPE_GROUPID}:${CI_JAVA_DEFAULT_ARCHETYPE_ARTIFACTID}:${CI_JAVA_DEFAULT_ARCHETYPE_VERSION}\n" + printf "\t Artefact : ${GROUP_ID}:${PROJECT_NAME}:${VERSION}\n" _check_variables GITHUBLOGIN GITHUBORG GITHUBTOKEN - printf "${_B_TITLE}$1 with groupId $2${_E_TITLE}\n" - printf "${_B_TITLE} calling maven archetype${_E_TITLE}\n" mvn --quiet --color=always --batch-mode archetype:generate \ - -DarchetypeGroupId=${JAVA_DEFAULT_ARCHETYPE_GROUPID} \ - -DarchetypeArtifactId=${JAVA_DEFAULT_ARCHETYPE_ARTIFACTID} \ - -DarchetypeVersion=${JAVA_DEFAULT_ARCHETYPE_VERSION} \ - -DgithubAccount=${GITHUBORG} \ - -DgroupId=${2} \ - -DartifactId=${1} \ - -Dversion=1.0-SNAPSHOT && - cd ${1} && + -DarchetypeGroupId="${CI_JAVA_DEFAULT_ARCHETYPE_GROUPID}" \ + -DarchetypeArtifactId="${CI_JAVA_DEFAULT_ARCHETYPE_ARTIFACTID}" \ + -DarchetypeVersion="${CI_JAVA_DEFAULT_ARCHETYPE_VERSION}" \ + -DgithubAccount="${GITHUBORG}" \ + -DgroupId="${GROUP_ID}" \ + -DartifactId="${PROJECT_NAME}" \ + -Dversion="${VERSION}" && + cd "${PROJECT_NAME}" && printf "${_B_TITLE} Gitflow init${_E_TITLE}\n" && - git flow init -d && git add . && git commit -m "sets initial release." && + git flow init -d && git add . && git commit --quiet -m "sets initial release." && printf "${_B_TITLE} gh-pages branch creation${_E_TITLE}\n" && git checkout --orphan gh-pages && - git rm -rf . && touch index.html && + git rm -rf --quiet . && touch index.html && git add . && - git commit -m "sets initial empty site." && + git commit --quiet -m "sets initial empty site." && git checkout develop && printf "${_B_TITLE} GitHub reposirory creation${_E_TITLE}\n" && - gh repo create ${GITHUBORG}/${PWD##*/} --disable-wiki --private --source=. && + gh repo create "${GITHUBORG}/${PWD##*/}" --disable-wiki --private --source=. && printf "${_B_TITLE} Generate a default deploy key${_E_TITLE}\n" && - _generate_and_install_new_deploy_key ${GITHUBORG} ${1} && - git push origin --mirror && + _generate_and_install_new_deploy_key "${GITHUBORG}" "${PROJECT_NAME}" && + git push origin --mirror --quiet && gh repo view --web ) _generate_and_install_new_deploy_key() ( tmpKeydir=$(mktemp --directory /tmp/ci-wrappers.XXXXXX) - ssh-keygen -q -t ed25519 -C "git@github.com:${1}/${2}.git" -N "" -f ${tmpKeydir}/key + ssh-keygen -q -t ed25519 -C "git@github.com:${1}/${2}.git" -N "" -f "${tmpKeydir}/key" gh repo deploy-key add --allow-write "${tmpKeydir}/key.pub" gh secret set SSH_PRIVATE_KEY <"${tmpKeydir}/key" rm -rf tmpKeydir ) -# runner name +# create a github hosted runner in a container for the current repo github-runner-repo() ( -local workdir="$(mktemp --directory /tmp/ghrunner-${GITHUBORG}-${PWD##*/}.XXXXXX)" -docker run -d --restart always \ - -e REPO_URL="https://github.com/${GITHUBORG}/${PWD##*/}" \ - -e RUNNER_NAME_PREFIX="${GITHUBORG}-${PWD##*/}-runner" \ - -e ACCESS_TOKEN=${GITHUBTOKEN} \ - -e RUNNER_WORKDIR="${workdir}" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v "${workdir}":"${workdir}" \ - myoung34/github-runner:latest - # -e RUNNER_GROUP="my-group" \ -# -e DISABLE_AUTO_UPDATE="true" \ -# -e ORG_NAME="${GITHUBORG}" \ -#-e LABELS="my-label,other-label" \ + local workdir + workdir=$(mktemp --directory "/tmp/ghrunner-${GITHUBORG}_${PWD##*/}_XXXXXX") + docker run -d --restart always --name ghrunner_$(echo "$workdir" | cut -d '-' -f 2) \ + -e REPO_URL="https://github.com/${GITHUBORG}/${PWD##*/}" \ + -e RUNNER_NAME_PREFIX="${GITHUBORG}-${PWD##*/}-runner" \ + -e ACCESS_TOKEN="${GITHUBTOKEN}" \ + -e RUNNER_WORKDIR="${workdir}" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v "${workdir}":"${workdir}" \ + myoung34/github-runner:latest ) +# create a github hosted runner in a container for the org in $GITHUBORG github-runner-org() ( -local workdir="$(mktemp --directory /tmp/ghrunner-org.XXXXXX)" -docker run -d --restart always \ - -e REPO_URL="https://github.com/${GITHUBORG}/${PWD##*/}" \ - -e RUNNER_NAME_PREFIX="${GITHUBORG}-${PWD##*/}-runner" \ - -e ACCESS_TOKEN=${GITHUBTOKEN} \ - -e RUNNER_WORKDIR="${workdir}" \ - -v /var/run/docker.sock:/var/run/docker.sock \ - -v "${workdir}":"${workdir}" \ - -e RUNNER_SCOPE="org" \ - -e ORG_NAME="${GITHUBORG}" \ - myoung34/github-runner:latest -# -e DISABLE_AUTO_UPDATE="true" \ -#-e LABELS="my-label,other-label" \ - # -e RUNNER_GROUP="my-group" \ -) \ No newline at end of file + local workdir + workdir=$(mktemp --directory "/tmp/ghrunner-${GITHUBORG}_XXXXXX") + docker run -d --restart always --name ghrunner_$(echo "$workdir" | cut -d '-' -f 2) \ + -e REPO_URL="https://github.com/${GITHUBORG}/${PWD##*/}" \ + -e RUNNER_NAME_PREFIX="${GITHUBORG}-${PWD##*/}-runner" \ + -e ACCESS_TOKEN="${GITHUBTOKEN}" \ + -e RUNNER_WORKDIR="${workdir}" \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v "${workdir}":"${workdir}" \ + -e RUNNER_SCOPE="org" \ + -e ORG_NAME="${GITHUBORG}" \ + myoung34/github-runner:latest +)