├── .circleci └── config.yml ├── .github └── CODEOWNERS ├── LICENSE ├── README.md ├── automated-updates.sh ├── gen-dockerfiles.sh ├── manifest ├── release.sh └── variants ├── browsers.Dockerfile.template └── node.Dockerfile.template /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | shell: circleci/shellcheck@3.1.1 5 | 6 | workflows: 7 | lint-scripts: 8 | jobs: 9 | - shell/check: 10 | exclude: "SC1091,SC2128,SC2145,SC2154" 11 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @CircleCI-Public/images 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Circle Internet Services, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `cimg` Shared Scripts [![GitHub License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/CircleCI-Public/cimg-shared/main/LICENSE)[![CircleCI Build Status](https://circleci.com/gh/CircleCI-Public/cimg-shared.svg?style=shield "CircleCI Build Status")](https://circleci.com/gh/CircleCI-Public/cimg-shared) [![GitHub License](https://img.shields.io/badge/license-MIT-lightgrey.svg)](https://raw.githubusercontent.com/CircleCI-Public/cimg-base/main/LICENSE) [![CircleCI Community](https://img.shields.io/badge/community-CircleCI%20Discuss-343434.svg)](https://discuss.circleci.com/c/ecosystem/images) 2 | 3 | This repository contains shared resources used by CircleCI's new deterministic convenience images pilot project. 4 | 5 | ## Overview 6 | 7 | See [the `circleci-cimg` topic tag](https://github.com/search?q=topic%3Acircleci-cimg) for all repositories associated with new convenience images work. 8 | 9 | ## Contributing 10 | 11 | We welcome [issues](https://github.com/CircleCI-Public/cimg-shared/issues) submitted to and [pull requests](https://github.com/CircleCI-Public/cimg-shared/pulls) opened against this repository! 12 | -------------------------------------------------------------------------------- /automated-updates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | vers=() 3 | 4 | ### 5 | # Checks if the version variables are equal to each other; if versionGreaterThan evalutes to true, the version string 6 | # that will be passed to ./shared/release.sh will be generated and added to the vers array 7 | ### 8 | 9 | versionEqual() { 10 | newVersion=$1 11 | currentVersion=$2 12 | 13 | if [ "$newVersion" = "$currentVersion" ]; then 14 | echo "Current version $currentVersion matches $newVersion. Does not need an update" 15 | return 1 16 | else 17 | versionGreaterThan "$newVersion" "$currentVersion" 18 | fi 19 | } 20 | 21 | ### 22 | # versionGreaterThan checks if the version is greater, in which case we return a code that will then be used to determine whether 23 | # a version string will be generated 24 | ### 25 | 26 | versionGreaterThan() { 27 | if [ "$(printf '%s\n' "$newVersion" "$currentVersion" | sort -V | head -n1)" = "$currentVersion" ]; then 28 | echo "Parsed version $newVersion is greater than $currentVersion" 29 | return 0 30 | else 31 | echo "Parsed version $newVersion is not greater than $currentVersion" 32 | return 1 33 | fi 34 | } 35 | 36 | ### 37 | # directory check is a helper function to check the given directory in order to generate a version string. It's enabled by the 38 | # searchTerm variable comparing the newVersion to the currentVersion 39 | # NOTE: because images have varying build parameters, the builtParam variable should be specified within a specific image repo 40 | # otherwise, the default is "" 41 | ### 42 | 43 | directoryCheck() { 44 | local directory=$1 45 | local searchTerm=$2 46 | 47 | if [ -z "$builtParam" ]; then 48 | builtParam="" 49 | fi 50 | 51 | if [ -d "$directory" ]; then 52 | currentVersion=$searchTerm 53 | echo "directory $directory exists; checking for matching versions: $currentVersion" 54 | versionEqual "$newVersion" "$currentVersion" 55 | else 56 | generateVersionString "$newVersion" "$builtParam" 57 | return 1 58 | fi 59 | } 60 | 61 | ### 62 | # generateVersions will help parse out the versions needed. this functions similarly to what already exists in ./shared/gen-dockerfiles 63 | # however, since we are pulling from a source, some parsing needs to happen; an example of ${cut} would be something like: 64 | # $(cut -d 'v' -f2 <<< "$version")" or just "$version" if no edits need to be made 65 | ### 66 | 67 | generateVersions () { 68 | local cut=$1 69 | 70 | if [[ -n $cut ]]; then 71 | newVersion=${cut} 72 | else 73 | newVersion=${version} 74 | fi 75 | 76 | if [[ $newVersion =~ ([0-9]+\.[0-9]+\.[0-9]) ]]; then 77 | majorMinor=${newVersion%.*} 78 | else 79 | majorMinor=${newVersion} 80 | fi 81 | 82 | if [[ $majorMinor =~ ([0-9]+\.[0-9]+\.[0-9]) ]]; then 83 | majorMinor=${majorMinor%.*} 84 | fi 85 | } 86 | 87 | ### 88 | # some cimgs require a separate parameter to specify things like a URL. this function builds the full string to be included 89 | # in the vers array 90 | ### 91 | 92 | generateVersionString() { 93 | local version=$1 94 | 95 | if [ -n "$builtParam" ]; then 96 | versionString=${version}${builtParam} 97 | else 98 | versionString=${version} 99 | fi 100 | 101 | vers+=( "$versionString" ) 102 | } 103 | 104 | ### 105 | # this function attempts to find the values associated with a variable in a specified Dockerfile. This is the basis for comparison 106 | # e.g newVersion vs currentVersion or an entire string, URL, etc that may need to be replaced 107 | # 108 | ### 109 | 110 | generateSearchTerms () { 111 | local searchFor=$1 112 | local searchFile=$2 113 | local trimCharacters=$3 114 | 115 | currVer=$(grep -m 1 "$searchFor" "$searchFile" | head -1) 116 | 117 | if [[ "$currVer" =~ = ]]; then 118 | currVer=$(cut -d "=" -f2 <<< "$currVer") 119 | else 120 | currVer=$(awk -F ' ' '{print $3}' <<< "$currVer") 121 | fi 122 | 123 | SEARCH_TERM=$(trimmer "$trimCharacters" <<< "$currVer") 124 | export SEARCH_TERM 125 | } 126 | 127 | # just in case a variable needs to be trimmed. space separated list of characters to be trimmed. 128 | 129 | trimmer() { 130 | tr -d "$@" 131 | } 132 | 133 | # some images, like clojure and android, require specific URLs parsed from the web 134 | 135 | getParsedURL() { 136 | local URL=$1 137 | local searchString=$2 138 | parsedURL=$(curl -sSL "$URL" | grep -m 1 "$searchString" | awk -F '/' '{ print $NF }' | tr -d "\"") 139 | export parsedURL 140 | } 141 | 142 | ### 143 | # replaceVersions, instead of tracking the version being parsed, simply gets the latest version/url for a specific software and 144 | # replaces what is in the Dockerfile by specifying the "search term", which should exist in the Dockerfile as an ENV 145 | # variable. The "software version" represents the actual version string of the software in a given direectory's Dockerfile 146 | ### 147 | 148 | replaceVersions() { 149 | local searchTerm=$1 150 | local softwareVersion=$2 151 | # isVersion is to differentiate between replacing a version string or a URL 152 | local isVersion=$3 153 | 154 | currentVersion=$searchTerm 155 | 156 | if [ "$isVersion" == true ]; then 157 | versionEqual "$newVersion" "$softwareVersion" 158 | if [[ $(eval echo $?) -eq 0 ]]; then 159 | # shellcheck disable=SC2154 160 | sed -i.bak "s!$softwareVersion!""$newVersion"'!g' "$templateFile" 161 | find . -name \*.bak -type f -delete 162 | fi 163 | else 164 | # shellcheck disable=SC2154 165 | sed -i.bak "s!$softwareVersion!""$newVersion"'!g' "$templateFile" 166 | find . -name \*.bak -type f -delete 167 | fi 168 | } 169 | 170 | declare -A quarters 171 | quarters["01"]="01" 172 | quarters["04"]="04" 173 | quarters["07"]="07" 174 | quarters["10"]="10" 175 | 176 | export quarters 177 | 178 | ### 179 | # generateDatedTags generates tags in the form '2023.03' 180 | ### 181 | generateDatedTags() { 182 | CURRENTMONTH=$(date +%m) 183 | CURRENTYEAR=$(date +%Y) 184 | RELEASE="$CURRENTYEAR.$CURRENTMONTH" 185 | 186 | export RELEASE 187 | } 188 | 189 | checkMonth() { 190 | if [[ ${quarters[${RELEASE##*.}]+exists} && $TEMPLATEMONTH != "${RELEASE##*.}" ]]; then 191 | STRING_TO_REPLACE="$TEMPLATEYEAR.$TEMPLATEMONTH" 192 | fi 193 | 194 | export STRING_TO_REPLACE 195 | } 196 | 197 | replaceDatedTags() { 198 | local templateFile=$1 199 | local interval=$2 200 | TEMPLATEYEAR=$(grep -m 1 "FROM" "$templateFile" | head -1 | cut -d : -f2 | cut -d . -f1) 201 | TEMPLATEMONTH=$(grep -m 1 "FROM" "$templateFile" | head -1 | cut -d : -f2 | cut -d . -f2 | cut -d - -f1) 202 | 203 | generateDatedTags 204 | checkMonth 205 | 206 | [[ $interval == "monthly" ]] && STRING_TO_REPLACE="$TEMPLATEYEAR.$TEMPLATEMONTH" 207 | [[ -n $STRING_TO_REPLACE ]] && sed -i.bak "s|$STRING_TO_REPLACE|$RELEASE|g" "$templateFile" 208 | rm -rf ./*.bak 209 | } 210 | 211 | # Only used for the deploy suite of cimgs: gcp, azure, aws. namespace and parent are sourced from the repo's manifest 212 | releaseDeployImage() { 213 | local version=$1 214 | 215 | if docker buildx imagetools inspect "$namespace/$parent:$RELEASE-node" &> /dev/null; then 216 | ./shared/release.sh "$version.1" 217 | else 218 | echo "$namespace/$parent:$RELEASE-node does not exist" 219 | exit 0 220 | fi 221 | } 222 | -------------------------------------------------------------------------------- /gen-dockerfiles.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # A Docker image is a combination of REGISTRY/NAMESPACE/REPOSITORY[:TAG]. 4 | # Registry will be ignored for now unless we move off Docker Hub. 5 | # Import repo-specific image information 6 | source ./manifest 7 | tagless_image=${namespace}/${repository} 8 | 9 | # Prepare the build and push files. Originally we only needed a build file but 10 | # with modern versions of Docker, a push file became neccesary as well. 11 | echo "#!/usr/bin/env bash" > ./build-images.sh 12 | echo "# Do not edit by hand; please use build scripts/templates to make changes" >> ./build-images.sh 13 | echo "set -eo pipefail" >> ./build-images.sh 14 | chmod +x ./build-images.sh 15 | echo "" >> ./build-images.sh 16 | 17 | if [[ $arm64 == "1" ]]; then 18 | echo "docker context create cimg" >> ./build-images.sh 19 | echo "docker buildx create --use cimg" >> ./build-images.sh 20 | fi 21 | 22 | touch push-images-temp.sh 23 | echo "#!/usr/bin/env bash" > ./push-images.sh 24 | echo "# Do not edit by hand; please use build scripts/templates to make changes" >> ./push-images.sh 25 | echo "set -eo pipefail" >> ./push-images.sh 26 | chmod +x ./push-images.sh 27 | 28 | while getopts "m:" flag; do 29 | case $flag in 30 | m) # Handle the -m flag 31 | echo "lacking minor versions ignored" 32 | MAJOR_ONLY=1 33 | ;; 34 | \?) 35 | echo "invalid flag" 36 | exit 1 37 | ;; 38 | esac 39 | done 40 | 41 | 42 | export CREATE_VERSIONS=("$@") 43 | 44 | # A version can be a major.minor or major.minor.patch version string. 45 | # An alias can be passed right after the version with an equal sign (=). 46 | # An additional parameter can be passed with a hash (#) sign. 47 | # Additionally versions/version groups are separated by spaces. 48 | # 49 | # Examples: 50 | # 51 | # 1.13.1 v1.14.2 52 | # v1.13.1#sha256abcfabdbc674bcg 53 | # v13.0.1=lts 54 | # v20.04 55 | # v8.0.252=lts=https://example.com/download/item.tar-gz 56 | # 57 | # Template variables exists in the `Dockerfile.template` files. The start and 58 | # end with two percent symbles `%%`. During Dockerfile generation, they get 59 | # replaced with actual valuables. Here's what's available to use: 60 | # 61 | # %%VERSION_FULL%% - the complete version passed to the script such as `1.2.3` 62 | # %%MAIN_VERSION%% - deprecated, please use %%VERSION_FULL%% instead 63 | # %%VERSION_MAJOR%% - just the major integer of the version such as `1` 64 | # %%VERSION_MINOR%% - the major and minor integers of the version with a decimal in the middle such as `1.2` 65 | # %%ALIAS1%% - what's passed as the alias when passing version strings to the build script (see above) 66 | # %%PARAM1%% - what's passed as the paramater when passing version strings to the build script (see above) 67 | # %%MAIN_SHA%% - deprecated, please use %%PARAM1%% 68 | 69 | ##### 70 | # Helper functions. 71 | ##### 72 | 73 | # Parses all template variables, regardless of if it's a main or variant image 74 | parse_template_variables () { 75 | 76 | local variantPath=${1} 77 | local parent=${2} 78 | local fileTemplate=${3} 79 | local parentTag=${4} 80 | local directory=${5} 81 | 82 | [[ -d "$directory" ]] || mkdir "$directory" 83 | 84 | sed -e 's!%%PARENT%%!'"${parent}"'!g' "${fileTemplate}" > "./${versionShort}/${variantPath}Dockerfile" 85 | sed -i.bak 's/%%PARENT_TAG%%/'"${parentTag}"'/g' "./${versionShort}/${variantPath}Dockerfile" 86 | sed -i.bak 's/%%NAMESPACE%%/'"${namespace}"'/g' "./${versionShort}/${variantPath}Dockerfile" 87 | sed -i.bak 's/%%MAIN_VERSION%%/'"${vgVersion}"'/g' "./${versionShort}/${variantPath}Dockerfile" # will be deprecated in the future 88 | sed -i.bak 's/%%VERSION_FULL%%/'"${vgVersion}"'/g' "./${versionShort}/${variantPath}Dockerfile" 89 | sed -i.bak 's/%%VERSION_MINOR%%/'"${versionShort}"'/g' "./${versionShort}/${variantPath}Dockerfile" 90 | sed -i.bak 's/%%VERSION_MAJOR%%/'"${vgVersionMajor}"'/g' "./${vgVersionMinor}/${variantPath}Dockerfile" 91 | sed -i.bak 's!%%MAIN_SHA%%!'"$vgParam1"'!g' "./$versionShort/${variantPath}Dockerfile" # will be deprecated in the future 92 | sed -i.bak 's!%%PARAM1%%!'"${vgParam1}"'!g' "./${versionShort}/${variantPath}Dockerfile" 93 | sed -i.bak 's!%%ALIAS1%%!'"${vgAlias1}"'!g' "./${versionShort}/${variantPath}Dockerfile" 94 | } 95 | 96 | build_and_push() { 97 | local pathing=${1} 98 | local versionString=${2} 99 | local versionShortString=${3} 100 | local defaultString=${4} 101 | local defaultShortString=${5} 102 | 103 | # every version loop will generate these basic docker tags 104 | # if parentTags are enabled, then additional tags will be generated in the parentTag loop 105 | # the defaultString is referenced as the tag that should be given by default for either a parent Tag or an alias 106 | 107 | if [[ -z "$arm64" ]]; then 108 | echo "docker push $tagless_image:$versionShortString" >> ./push-images-temp.sh 109 | echo "docker push $tagless_image:$versionString" >> ./push-images-temp.sh 110 | echo "docker build --file $pathing/Dockerfile -t $tagless_image:$versionString -t $tagless_image:$versionShortString --platform linux/amd64 --push ." >> ./build-images-temp.sh 111 | elif [[ $pathing == *"browsers"* ]]; then 112 | echo "docker buildx build --platform=linux/amd64 --file $pathing/Dockerfile -t $tagless_image:$versionString -t $tagless_image:$versionShortString --push ." >> ./build-images-temp.sh 113 | else 114 | echo "docker buildx build --platform=linux/amd64,linux/arm64 --file $pathing/Dockerfile -t $tagless_image:$versionString -t $tagless_image:$versionShortString --push ." >> ./build-images-temp.sh 115 | fi 116 | 117 | if [[ -n $defaultParentTag ]] && [[ "$defaultParentTag" == "$parentTag" ]]; then 118 | if [[ -z "$arm64" ]]; then 119 | { 120 | echo "docker tag $tagless_image:$versionString $tagless_image:$defaultString" 121 | echo "docker tag $tagless_image:$versionShortString $tagless_image:$defaultShortString" 122 | echo "docker push $tagless_image:$defaultShortString" 123 | echo "docker push $tagless_image:$defaultString" 124 | } >> ./push-images-temp.sh 125 | fi 126 | fi 127 | 128 | if [[ -n $vgAlias1 ]] && [[ "$vgVersion" = "$aliasGroup" ]]; then 129 | if [[ -z "$arm64" ]]; then 130 | { 131 | echo "docker tag $tagless_image:$versionString $tagless_image:$defaultString" 132 | echo "docker push $tagless_image:$defaultString" 133 | } >> ./push-images-temp.sh 134 | else 135 | { 136 | echo "docker buildx imagetools create -t $tagless_image:$defaultString $tagless_image:$versionString" 137 | } >> ./push-images-temp.sh 138 | fi 139 | fi 140 | } 141 | 142 | filepath_templating () { 143 | if [[ -f "./variants/${variant}.Dockerfile.template" ]]; then 144 | fileTemplate="./variants/${variant}.Dockerfile.template" 145 | elif [[ -f "./shared/variants/${variant}.Dockerfile.template" ]]; then 146 | fileTemplate="./shared/variants/${variant}.Dockerfile.template" 147 | else 148 | echo "Error: Variant ${variant} doesn't exist. Exiting." 149 | exit 2 150 | fi 151 | } 152 | 153 | ##### 154 | # Starting version loop. 155 | ##### 156 | for versionGroup in "$@"; do 157 | # Process the version group(s) that were passed to this script. 158 | if [[ "$versionGroup" != "-m" ]]; then 159 | if [[ "$versionGroup" == *"#"* ]]; then 160 | vgParam1=$(cut -d "#" -f2- <<< "$versionGroup") 161 | versionGroup="${versionGroup//$vgParam1}" 162 | versionGroup="${versionGroup//\#}" 163 | fi 164 | 165 | if [[ "$versionGroup" == *"="* ]]; then 166 | vgAlias1=$(cut -d "=" -f2- <<< "$versionGroup") 167 | versionGroup="${versionGroup//$vgAlias1}" 168 | versionGroup="${versionGroup//=}" 169 | aliasGroup="${versionGroup}" 170 | fi 171 | 172 | vgVersionFull=$(cut -d "v" -f2- <<< "$versionGroup") 173 | vgVersion=$vgVersionFull # will be deprecated in the future 174 | 175 | if [[ $MAJOR_ONLY -ne 1 ]]; then 176 | if [[ $vgVersionFull =~ ^[0-9]+\.[0-9]+ ]]; then 177 | vgVersionMinor=${BASH_REMATCH[0]} 178 | versionShort=$vgVersionMinor # will be deprecated in the future 179 | else 180 | echo "Version matching (minor) failed." >&2 181 | exit 1 182 | fi 183 | 184 | if [[ $vgVersionFull =~ ^[0-9]+ ]]; then 185 | vgVersionMajor=${BASH_REMATCH[0]} 186 | else 187 | echo "Version matching (major) failed." >&2 188 | exit 1 189 | fi 190 | [[ -d "$versionShort" ]] || mkdir "$versionShort" 191 | else 192 | vgVersionMajor="$vgVersionFull.0" 193 | vgVersionMinor="$vgVersionFull.0" 194 | versionShort="$vgVersionMinor" 195 | vgVersion="$versionShort.0" 196 | [[ -d "$versionShort" ]] || mkdir "$versionShort" 197 | fi 198 | 199 | 200 | 201 | # no parentTag loop; creates Dockerfiles and variants 202 | if [[ -z "${parentTags[0]}" ]]; then 203 | parse_template_variables "" "$parent" "./Dockerfile.template" "$vgVersion" "$versionShort" 204 | build_and_push "$versionShort" "$vgVersion" "$versionShort" "$vgAlias1" 205 | for variant in "${variants[@]}"; do 206 | filepath_templating 207 | parse_template_variables "$variant/" "$repository" "$fileTemplate" "$vgVersion" "$versionShort/$variant" 208 | build_and_push "$versionShort/$variant" "$vgVersion-$variant" "$versionShort-$variant" "$vgAlias1-$variant" 209 | done 210 | else 211 | 212 | # parentTag loop; one Dockerfile will be created along with however many variants there are for each parentTag 213 | for parentTag in "${parentTags[@]}"; do 214 | if [[ -n $parentTag ]]; then 215 | parse_template_variables "$parentTag/" "$parent" "./Dockerfile.template" "$parentTag" "$versionShort/$parentTag" 216 | build_and_push "$versionShort/$parentTag" "$vgVersion-$parentSlug-$parentTag" "$versionShort-$parentSlug-$parentTag" "$vgVersion" "$versionShort" 217 | 218 | for variant in "${variants[@]}"; do 219 | filepath_templating 220 | parse_template_variables "$parentTag/$variant/" "$repository" "$fileTemplate" "$vgVersion-$parentSlug-$parentTag" "$versionShort/$parentTag/$variant" 221 | build_and_push "$versionShort/$parentTag/$variant" "$vgVersion-$parentSlug-$parentTag-$variant" "$versionShort-$parentSlug-$parentTag-$variant" "$vgVersion-$variant" "$versionShort-$variant" 222 | done 223 | fi 224 | done 225 | fi 226 | # Build out the ALIASES file. Keeps track of aliases that have been set 227 | # without losing old versions. 228 | if [[ -n $vgAlias1 ]] && [[ $aliasGroup = "$versionGroup" ]]; then 229 | if [[ -f ALIASES ]]; then 230 | # Make sure the current alias isn't in the file. 231 | grep -v "${vgAlias1}" ./ALIASES > ./TEMP && mv ./TEMP ./ALIASES 232 | fi 233 | 234 | echo "${vgAlias1}=${vgVersion}" >> ALIASES 235 | fi 236 | 237 | # This .bak thing fixes a Linux/macOS compatibility issue, but the files are cleaned up 238 | find . -name \*.bak -type f -delete 239 | fi 240 | done 241 | 242 | if [[ -n "${CREATE_VERSIONS}" ]]; then 243 | # Make sure the current alias isn't in the file. 244 | if [[ $CREATE_VERSIONS != "-m" ]]; then 245 | if [[ -f GEN-CHECK ]]; then 246 | grep -v "${CREATE_VERSIONS}" ./GEN-CHECK > ./TEMP2 && mv ./TEMP2 ./GEN-CHECK 247 | fi 248 | 249 | echo "GEN_CHECK=($@)" > GEN-CHECK 250 | if [[ -f TEMP2 ]]; then 251 | rm ./TEMP2 252 | fi 253 | fi 254 | fi 255 | 256 | cat -n push-images-temp.sh | sort -uk2 | sort -nk1 | cut -f2- >> push-images.sh 257 | cat -n build-images-temp.sh | sort -uk2 | sort -nk1 | cut -f2- >> build-images.sh 258 | rm push-images-temp.sh build-images-temp.sh 259 | -------------------------------------------------------------------------------- /manifest: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This file exists solely to get `cimg-shared` to pass shellcheck. 4 | # It's not actually used for real image builds. 5 | 6 | repository=nothing 7 | parent=nothing 8 | variants=(nothing) 9 | namespace=nothing 10 | parentTags=(nothing) 11 | defaultParentTag=nothing 12 | parentSlug=nothing -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Much of the version processing logic is repeated from gen-dockerfiles.sh 4 | # This should be de-duped sometime in the future when this logic is solidified 5 | versions=() 6 | 7 | for versionGroup in "$@"; do 8 | 9 | # Process the version group(s) that were passed to this script. 10 | if [[ "$versionGroup" == *"#"* ]]; then 11 | vgParam1=$(cut -d "#" -f2- <<< "$versionGroup") 12 | versionGroup="${versionGroup//$vgParam1}" 13 | versionGroup="${versionGroup//\#}" 14 | fi 15 | 16 | if [[ "$versionGroup" == *"="* ]]; then 17 | vgAlias1=$(cut -d "=" -f2- <<< "$versionGroup") 18 | versionGroup="${versionGroup//$vgAlias1}" 19 | versionGroup="${versionGroup//=}" 20 | fi 21 | 22 | vgVersion=$(cut -d "v" -f2- <<< "$versionGroup") 23 | versions+=( "$vgVersion" ) 24 | done 25 | 26 | branchName="" 27 | commitMSG="" 28 | 29 | if [[ ${#versions[@]} == 0 ]]; then 30 | echo "Error, no versions detected." 31 | exit 1 32 | elif [[ ${#versions[@]} == 1 ]]; then 33 | branchName="release-v${versions[0]}" 34 | commitMSG="Publish v${versions[0]}. [release]" 35 | elif [[ ${#versions[@]} == 2 ]]; then 36 | branchName="release-v${versions[0]}-and-v${versions[1]}" 37 | commitMSG="Publish v${versions[0]} and v${versions[1]}. [release]" 38 | elif [[ ${#versions[@]} == 3 ]]; then 39 | branchName="release-v${versions[0]}-v${versions[1]}-and-more" 40 | commitMSG="Publish v${versions[0]}, v${versions[1]}, and v${versions[2]}. [release]" 41 | elif [[ ${#versions[@]} == 4 ]]; then 42 | branchName="release-v${versions[0]}-v${versions[1]}-and-more" 43 | commitMSG="Pub: v${versions[0]}, v${versions[1]}, v${versions[2]}, and more. [release]" 44 | elif [[ ${#versions[@]} -gt 4 ]]; then 45 | branchName="release-v${versions[0]}-v${versions[1]}-and-more" 46 | commitMSG="Pub: ${versions[0]},${versions[1]},${versions[2]},${versions[3]}, and more. [release]" 47 | fi 48 | 49 | defaultBranch=$(git remote show origin | grep 'HEAD branch' | cut -d' ' -f5) 50 | 51 | git checkout -b "${branchName}" "${defaultBranch}" 52 | shared/gen-dockerfiles.sh "$@" 53 | git add . 54 | git commit -m "${commitMSG}" 55 | git push -u origin "${branchName}" 56 | gh pr create --title "$commitMSG" --head "$branchName" --body "$commitMSG" 57 | -------------------------------------------------------------------------------- /variants/browsers.Dockerfile.template: -------------------------------------------------------------------------------- 1 | # vim:set ft=dockerfile: 2 | 3 | FROM %%NAMESPACE%%/%%PARENT%%:%%PARENT_TAG%%-node 4 | 5 | LABEL maintainer="CircleCI Community & Partner Engineering Team " 6 | 7 | # Install Selenium 8 | ENV SELENIUM_VER=3.141.59 9 | RUN curl -sSL -o selenium-server-standalone-${SELENIUM_VER}.jar "https://selenium-release.storage.googleapis.com/${SELENIUM_VER%.*}/selenium-server-standalone-${SELENIUM_VER}.jar" && \ 10 | sudo cp selenium-server-standalone-${SELENIUM_VER}.jar /usr/local/bin/selenium.jar && \ 11 | rm selenium-server-standalone-${SELENIUM_VER}.jar 12 | 13 | RUN sudo apt-get update && \ 14 | sudo apt-get install --yes --no-install-recommends \ 15 | xvfb \ 16 | && \ 17 | # Install Java only if it's not already available 18 | # Java is installed for Selenium 19 | if ! command -v java > /dev/null; then \ 20 | echo "Java not found in parent image, installing..." && \ 21 | sudo apt-get install -y --no-install-recommends --no-upgrade openjdk-11-jre; \ 22 | fi && \ 23 | sudo rm -rf /var/lib/apt/lists/* 24 | 25 | # Below is setup to allow xvfb to start when the container starts up. 26 | # The label in particular allows this image to override what CircleCI does 27 | # when booting the image. 28 | LABEL com.circleci.preserve-entrypoint=true 29 | ENV DISPLAY=":99" 30 | #RUN printf '#!/bin/sh\nXvfb :99 -screen 0 1280x1024x24 &\nexec "$@"\n' > /tmp/entrypoint && \ 31 | # chmod +x /tmp/entrypoint && \ 32 | # sudo mv /tmp/entrypoint /docker-entrypoint.sh 33 | RUN printf '#!/bin/sh\nXvfb :99 -screen 0 1280x1024x24 &\nexec "$@"\n' | sudo tee /docker-entrypoint.sh && \ 34 | sudo chmod +x /docker-entrypoint.sh 35 | 36 | # Install a single version of Firefox. This isn't intended to be a regularly 37 | # updated thing. Instead, if this version of Firefox isn't what the end user 38 | # wants they should install a different version via the Browser Tools Orb. 39 | # 40 | # Canonical made a major technology change in how Firefox is installed from 41 | # Ubuntu 21.10 and up. The general CI space doesn't seem to be ready for a snap 42 | # based Firefox right now so we are installing it from the Mozilla PPA. 43 | RUN echo 'Package: *' | sudo tee -a /etc/apt/preferences.d/firefox.pref && \ 44 | echo 'Pin: release o=LP-PPA-mozillateam' | sudo tee -a /etc/apt/preferences.d/firefox.pref && \ 45 | echo 'Pin-Priority: 1001' | sudo tee -a /etc/apt/preferences.d/firefox.pref && \ 46 | sudo add-apt-repository --yes ppa:mozillateam/ppa && \ 47 | sudo apt-get install --no-install-recommends --yes firefox && \ 48 | sudo rm -rf /var/lib/apt/lists/* && \ 49 | firefox --version 50 | 51 | # Install a single version of Google Chrome Stable. This isn't intended to be a 52 | # regularly updated thing. Instead, if this version of Chrome isn't what the 53 | # end user wants they should install a different version via the Browser Tools 54 | # Orb. 55 | RUN wget -q -O - "https://dl.google.com/linux/linux_signing_key.pub" | sudo apt-key add - && \ 56 | echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list && \ 57 | sudo apt-get update && \ 58 | sudo apt-get install google-chrome-stable && \ 59 | sudo rm -rf /var/lib/apt/lists/* 60 | 61 | ENTRYPOINT ["/docker-entrypoint.sh"] 62 | CMD ["/bin/sh"] 63 | -------------------------------------------------------------------------------- /variants/node.Dockerfile.template: -------------------------------------------------------------------------------- 1 | # vim:set ft=dockerfile: 2 | 3 | FROM %%NAMESPACE%%/%%PARENT%%:%%PARENT_TAG%% 4 | 5 | LABEL maintainer="Community & Partner Engineering Team " 6 | 7 | # Dockerfile will pull the latest LTS release from cimg-node. 8 | RUN curl -sSL "https://raw.githubusercontent.com/CircleCI-Public/cimg-node/main/ALIASES" -o nodeAliases.txt && \ 9 | NODE_VERSION=$(grep "lts" ./nodeAliases.txt | cut -d "=" -f 2-) && \ 10 | [[ $(uname -m) == "x86_64" ]] && ARCH="x64" || ARCH="arm64" && \ 11 | curl -L -o node.tar.xz "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-${ARCH}.tar.xz" && \ 12 | sudo tar -xJf node.tar.xz -C /usr/local --strip-components=1 && \ 13 | rm node.tar.xz nodeAliases.txt && \ 14 | sudo ln -s /usr/local/bin/node /usr/local/bin/nodejs 15 | 16 | ENV YARN_VERSION="1.22.19" 17 | RUN curl -L -o yarn.tar.gz "https://yarnpkg.com/downloads/${YARN_VERSION}/yarn-v${YARN_VERSION}.tar.gz" && \ 18 | sudo tar -xzf yarn.tar.gz -C /opt/ && \ 19 | rm yarn.tar.gz && \ 20 | sudo ln -s /opt/yarn-v${YARN_VERSION}/bin/yarn /usr/local/bin/yarn && \ 21 | sudo ln -s /opt/yarn-v${YARN_VERSION}/bin/yarnpkg /usr/local/bin/yarnpkg 22 | --------------------------------------------------------------------------------