Skip to content

Commit

Permalink
Code refactoring for v2 (Hello, Jammy!)
Browse files Browse the repository at this point in the history
  • Loading branch information
shinsenter committed Jun 9, 2022
1 parent 5e494d0 commit a35928e
Show file tree
Hide file tree
Showing 189 changed files with 7,477 additions and 1,798 deletions.
13 changes: 13 additions & 0 deletions .bin/fix-attr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash
# This file belongs to the project https://code.shin.company/php
# Author: Shin <[email protected]>
# License: https://code.shin.company/php/blob/main/LICENSE
################################################################################

BASE_DIR="$(git rev-parse --show-toplevel)"
TARGET=${1:-$BASE_DIR}

echo -e "\n🗂 Fixing permission for ${TARGET/$BASE_DIR/.}/"
find $TARGET -type d | grep -v 'tests\?' | xargs -I {} chmod 755 {}
find $TARGET -type f | grep -v 'tests\?' | xargs -I {} chmod 644 {}
find $TARGET -type f | grep -v 'tests\?' | grep '\/\.\?bin\|\/command\/\|git-config\/hooks\|root\/startup\|s6-overlay\|cont-init\|services\.d\|\.sh' | xargs -I {} chmod +xr {}
147 changes: 147 additions & 0 deletions .bin/prebuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#!/bin/bash
# This file belongs to the project https://code.shin.company/php
# Author: Shin <[email protected]>
# License: https://code.shin.company/php/blob/main/LICENSE
################################################################################

[ -z "$1" ] && echo "Missing build target." && exit 1;

TARGET=$1
BASE_DIR="$(git rev-parse --show-toplevel)"
SRC_DIR="$BASE_DIR/src"
CACHE_DIR="/tmp/build-cache"
S6_VERSION="$(cat ${BASE_DIR}/S6_VERSION | sort -r | head -n1)"
OS_VERSIONS="$(cat ${BASE_DIR}/OS_VERSIONS | sort -r )"
PHP_VERSIONS="$(cat ${BASE_DIR}/PHP_VERSIONS | sort -r )"
LATEST_OS="$(echo "$OS_VERSIONS" | head -n1)"
LATEST_PHP="$(echo "$PHP_VERSIONS" | head -n1)"

BUILD_DATE="$(date +%Y-%m-%dT%T%z)"
BUILD_REVISION="$(git rev-parse HEAD)"

################################################################################
# Helper methods
################################################################################

tee_or_print () {
local file="$1" ; shift
if [ -f $file ]; then cat $file; else "$@" | tee $file; fi
}

basehash () { shasum -a1 "$@" 2>/dev/null | cut -c1-40; }

dirhash () {
find ${1:-$BASE_DIR} -type f \
| grep -v 'README\.md\|\.dockerignore\|.checksum' \
| sort -u \
| xargs -I {} shasum -a1 {} \
| basehash
}

imagehash () {
for image in "$@"; do
echo "$(docker manifest inspect --insecure "$@" 2>/dev/null | basehash) - $image"
done
}

linkhash () {
for url in "$@"; do
echo "$(curl -skL "$url" 2>/dev/null | basehash) - $url"
done
}

treehash() {
local target
local checksum
for path in "$@"; do
target="$BASE_DIR/$path"
if [ -d $target ]; then
checksum="$target/.checksum"
if [ -f $checksum ]; then cat $checksum; continue; fi
touch $checksum ; case "$path" in
src/base-s6 ) treehash S6_VERSION src/base | tee -a $checksum ;;
src/base-ubuntu ) treehash src/base-s6 | tee -a $checksum ;;
src/php/cli ) treehash src/base-ubuntu | tee -a $checksum ;;
src/php/fpm ) treehash src/php/cli | tee -a $checksum ;;
src/servers/* ) treehash src/php/fpm | tee -a $checksum ;;
src/webapps/* ) treehash src/servers/fpm-$(grep nginx $target/Dockerfile >/dev/null && echo 'nginx' || echo 'apache') | tee -a $checksum ;;
esac;
echo "$(dirhash ${target/$BASE_DIR/.}) - $path/" | tee -a $checksum
else
echo "$(basehash ${target/$BASE_DIR/.}) - $path"
fi
done
}

prebuild () {
local checksum
local desc
local context

context="$BASE_DIR/$1" ; [ -d $context ] || return 1
mkdir -p ${context}/root

if [ -f ${context}/README.md ] && [ -z "$(cat ${context}/README.md | grep SPONSOR\.md)" ]; then
echo -e "\n\n$(cat ${BASE_DIR}/SPONSOR.md)" >>${context}/README.md
desc="$(sed '3q;d' ${context}/README.md)"
fi

if [ -f ${context}/Dockerfile ]; then
cp -rpf $SRC_DIR/.dockerignore ${context}/.dockerignore
if [ "$2" != "nometa" ] && [ -z "$(cat ${context}/Dockerfile | grep Metafile)" ]; then
echo -e "\n\n$(cat $SRC_DIR/Metafile)" >>${context}/Dockerfile
fi
fi

$BASE_DIR/.bin/fix-attr $context
checksum="$(basehash $context/.checksum)"
echo " ${desc:-No description}"
echo " #️⃣ Checksum: $checksum"

echo -e "\n🖨 Making output for the next steps"
echo "::set-output name=BUILD_CACHE_DIR::$CACHE_DIR"
echo "::set-output name=BUILD_CACHE::shinsenter/php:build-cache"
echo "::set-output name=BUILD_DATE::$BUILD_DATE"
echo "::set-output name=BUILD_DESC::$desc"
echo "::set-output name=BUILD_PLATFORM::linux/amd64,linux/arm/v7,linux/arm64/v8,linux/ppc64le"
echo "::set-output name=BUILD_REVISION::$BUILD_REVISION"
echo "::set-output name=CHECKSUM::$checksum"
echo "::set-output name=LATEST_OS::$LATEST_OS"
echo "::set-output name=LATEST_PHP::$LATEST_PHP"
echo "::set-output name=S6_VERSION::$S6_VERSION"
# echo "::set-output name=OS_VERSIONS::$OS_VERSIONS"
# echo "::set-output name=PHP_VERSIONS::$PHP_VERSIONS"
}

################################################################################
# Prebuild steps
################################################################################

echo -e "\n🤖 Cheking dependencies for $TARGET"

mkdir -p $SRC_DIR/base/scratch

tee_or_print $SRC_DIR/base-s6/.source \
imagehash ubuntu

tee_or_print $SRC_DIR/php/cli/.source \
linkhash \
'http://ppa.launchpad.net/ondrej/php/ubuntu/dists/?C=M;O=D' \
'https://getcomposer.org/download/latest-stable/composer.phar.sha256sum'

tee_or_print $SRC_DIR/servers/fpm-apache/.source \
linkhash 'http://ppa.launchpadcontent.net/ondrej/apache2/ubuntu/dists/?C=M;O=D'

tee_or_print $SRC_DIR/servers/fpm-nginx/.source \
linkhash \
'http://ppa.launchpadcontent.net/ondrej/nginx-mainline/ubuntu/dists/?C=M;O=D'

tee_or_print $SRC_DIR/webapps/wordpress/.source \
linkhash \
'https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar.sha512'

echo -e "\n🤖 Preparing $TARGET"
treehash $TARGET
prebuild $TARGET $2
mkdir -p $CACHE_DIR
echo -e "\nCompleted."
169 changes: 169 additions & 0 deletions .bin/tidy-docker
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#!/bin/bash
# This file belongs to the project https://code.shin.company/php
# Author: Shin <[email protected]>
# License: https://code.shin.company/php/blob/main/LICENSE
################################################################################

[ ! -x "$(command -v docker)" ] && echo "Missing Docker." && exit 1

################################################################################

PARSE_CACHE=

# extracts docker repository name and tag
d_name_id () {
docker images --format "{{.Repository}}:{{.Tag}}\t{{.ID}}" \
| grep -F $1 \
| head -n1
}

# parses instruction from image
d_local_history () {
docker history --no-trunc --format "{{.CreatedBy}}" $1 \
| awk '{arr[i++]=$0}END{while(i>0)print arr[--i]}'
}

# parses instruction from docker hub
d_net_history () {
repo="$1"
tag="$2"
curl -skL 'https://hub.docker.com/v2/repositories/$repo/tags/$tag/images' \
| jq '.[1].layers' \
| jq '.[].instruction' -r
}

# parses instruction and replace all '/bin/sh -c #(nop)'
d_parse () {
if [ -z "$PARSE_CACHE" ]; then
PARSE_CACHE="$(d_local_history $1 \
| sed 's/^\/[^ ]* *-c */RUN /' \
| sed 's/^|[0-9]* */RUN /' \
| sed 's/^RUN \#[^ ]* *//' \
| sed 's#EXPOSE map\[\(.*\):.*\]#EXPOSE \1#g' \
| awk '
{
if($1=="SHELL"){
gsub("\\\[","[\"",$0); gsub("\\\]","\"]",$0)
i=1; printf("%s ",$i)
while(i++<NF){
if(i>2){printf("\", \"%s",$i)}else{printf("%s",$i)}
}
printf "\n"
} else print $0
}' 2>/dev/null \
| awk '
{
if(($1=="WORKDIR")||($1=="ENTRYPOINT")||($1=="CMD")||($1=="STOPSIGNAL"))
{cmd[$1]=$0;if($1=="ENTRYPOINT")delete cmd["CMD"]}
else print $0
} END {
if(cmd["WORKDIR"]) print cmd["WORKDIR"]
if(cmd["ENTRYPOINT"]) print cmd["ENTRYPOINT"]
if(cmd["CMD"]) print cmd["CMD"]
if(cmd["STOPSIGNAL"]) print cmd["STOPSIGNAL"]
}'
)"
fi
echo "$PARSE_CACHE"
}

# extracts given unique key-value instruction list
d_attr () {
d_parse $1 \
| grep "^${2:-ENV}" \
| awk -F= '
{p=index($0,"=");v=substr($0,p+1);a[$1]=v}
END{for(k in a)printf("%s=\"%s\"\n",k,a[k])}
' \
| sort
}

# extracts other instructions
ins_cmd () {
d_parse $1 | grep -v '^\(ADD\|ARG\|COPY\|ENV\|HEALTHCHECK\|LABEL\|ONBUILD\|RUN\)'
}

# aliases
ins_name () { d_name_id $1 | awk '{printf $1}'; }
ins_id () { d_name_id $1 | awk '{printf $2}'; }

# command aliases
ins_env () { d_attr $1 ENV; }
ins_labels () { d_attr $1 LABEL; }
ins_shell () { ins_cmd $1 | grep '^SHELL'; }
ins_others () { ins_cmd $1 | grep -v '^SHELL'; }

# builds minified image
# @param $output Output new Dockerfile (optional, must be a valid file path)
# @param $base The original image (ID or name:tag)
# @param $save Target image name
minify() {
PARSE_CACHE=
local output="$1" ; [ ! -z "$output" ] && [ -f "$output" ] && shift || output=""
local base="$1" ; [ ! -z "$base" ] && shift || return 1
local save="$1" ; [ ! -z "$save" ] && shift || save="${base}-tidy"
local repo="$(ins_name $base)" ; [ -z "$output" ] && [ -z "$repo" ] && echo "Invalid image ID $base" && return 1
local temp="$([ ! -z "$output" ] && echo "$base" || echo "tidy-docker:build-$(ins_id $base)")"
local command="$([ ! -z "$output" ] && echo "tee $output" || echo "docker build $@ --rm -t $save -")"

# make temporary tag name for building image
[ -z "$output" ] && docker tag $base $temp 2>/dev/null

# build the tidy
echo "🗜 Start minifying image '$repo'"
echo " Build arguments: $@"
DOCKER_BUILDKIT=${DOCKER_BUILDKIT:-1} $command <<Dockerfile
# Input Image: "${base}"
# (aka: "${repo}")
# Final Image: "${save}"
################################################################################
# CLEANING UP THE SOURCE IMAGE. ################################################
FROM shinsenter/scratch as scratch
FROM ${temp} as tidy
USER root
RUN [ -x "\$(command -v cleanup)" ] && cleanup || true
RUN [ -x "\$(command -v apt-get)" ] && apt-get -yq autoremove --purge || true
RUN [ -x "\$(command -v composer)" ] && composer clearcache -q --ansi || true
RUN [ -x "\$(command -v docker)" ] && docker system prune -af || true
RUN [ -x "\$(command -v npm)" ] && npm cache clean --force || true
RUN [ -x "\$(command -v yum)" ] && yum clean all -y || true
RUN [ -x "\$(command -v rm)" ] && rm -rf \\
~/.wp-cli/ ~/.git/ ~/.composer/ ~/.npm/ ~/.cache/ ~/.log/ ~/.tmp/ \\
/usr/share/doc/* /tmp/* /var/tmp/* \\
/var/cache/apk /var/cache/yum /var/lib/apt/lists/* \\
/var/cache/apt/archives/*.deb \\
/var/cache/apt/archives/partial/*.deb \\
/var/cache/apt/*.bin \\
|| true
RUN [ -x "\$(command -v find)" ] && find / \( \\
-name "._*" -or -name "*~" -or -name "*.swp" \\
-or -name ".git" -or -name ".svn" \\
-or -name ".DS_Store" \\
-or -name "Thumbs.db" -or -name "thumbs.db" \\
-or -name "*.pyc" -or -name "*.pyo" \\
-or -name "*pip*" -or -name "*__pycache__*" \\
-or -name "*easy_install*" -or -name "*dist-info*" \\
\) ! -path "/sys/*" ! -path "/proc/*" \\
-exec rm -rf {} + || true
################################################################################
# BUILDING OPTIMIZED IMAGE FROM SCRATCH. #####################################
FROM scratch
COPY --from=tidy / /
$(ins_shell $base)
$(ins_env $base)
$(ins_others $base)
LABEL org.opencontainers.image.title="$save"
LABEL org.opencontainers.image.description="A tidied image of $repo"
$(ins_labels $base)
# FINISH. ######################################################################
################################################################################
Dockerfile

# cleanup
if [ $? -eq 0 ] && [ -z "$output" ]; then docker rmi "$temp" >/dev/null; fi
}

################################################################################

echo ; date
minify $@ && echo "Done." || echo "Failed."
22 changes: 22 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
end_of_line = crlf

[.bin/*]
indent_size = 2

[*.{yml,yaml}]
indent_size = 2

[docker-compose.yml]
indent_size = 4
30 changes: 0 additions & 30 deletions .git-config/hooks/pre-build

This file was deleted.

Loading

0 comments on commit a35928e

Please sign in to comment.