Skip to content

Commit

Permalink
SC-21584: Flow improvements + Security (#104)
Browse files Browse the repository at this point in the history
* SC-21584: Flow improvements + Security

* Remove Alpine 3.17 + Updated php to the latest + Fixed Blackifre issue

* Revert Alpine 3.20 instructions

* Delete alpine/.DS_Store

* Format the releae diff + Adjust the notification message

* Rename the file (remove space) + Change permissions

* Update ci.yml
  • Loading branch information
alexanderM91 authored Dec 9, 2024
1 parent 54de45e commit 337a2f4
Show file tree
Hide file tree
Showing 28 changed files with 532 additions and 632 deletions.
81 changes: 81 additions & 0 deletions .github/compare-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash

if [ -z "$1" ]; then
echo "Error: No tag provided. Usage: ./compare-image.sh <docker-tag>"
exit 1
fi

IMAGE_TAG=$1

if [[ "$IMAGE_TAG" == *"debian"* ]]; then
docker run -i --rm "$IMAGE_TAG" sh -s <<'EOF'
echo "=== PHP Version ==="
/usr/local/bin/php -v | awk 'NR==1 {print $1, $2}'
echo ""
echo "=== Debian Version ==="
echo -n "Debian " && cat /etc/debian_version
echo ""
echo "=== Installed PHP Extensions ==="
docker-php-source extract
for ext in `ls /usr/src/php/ext`; do
echo ' ' `php -r "if (extension_loaded('$ext' !== 'opcache' ? '$ext' : 'Zend OPcache')) { echo '[x] $ext'; } else { echo '[ ] $ext'; }"`;
done
echo ""
echo "=== Disabled PHP Extensions ==="
for f in /usr/local/etc/php/disabled/*.ini; do
disabled=$(basename $f | sed -e 's/\.ini$//');
echo " [ ] ${disabled} $(PHP_INI_SCAN_DIR=:/usr/local/etc/php/disabled php -r "echo phpversion('${disabled}');")";
done
echo ""
echo "=== PECL Extensions ==="
pear list -c pecl
echo ""
echo "=== Composer Version ==="
composer -V
echo ""
echo "=== Installed System Packages ==="
dpkg-query -W --showformat='${Package} ${Version}\n' | sort
EOF
else
docker run -i --rm "$IMAGE_TAG" sh -s <<'EOF'
echo "=== PHP Version ==="
/usr/local/bin/php -v | awk 'NR==1 {print $1, $2}'
echo ""
echo "=== Alpine Version ==="
echo -n "Alpine " && cat /etc/alpine-release
echo ""
echo "=== Installed PHP Extensions ==="
docker-php-source extract
for ext in `ls /usr/src/php/ext`; do
echo ' ' `php -r "if (extension_loaded('$ext' !== 'opcache' ? '$ext' : 'Zend OPcache')) { echo '[x] $ext'; } else { echo '[ ] $ext'; }"`;
done
echo ""
echo "=== Disabled PHP Extensions ==="
for f in /usr/local/etc/php/disabled/*.ini; do
disabled=$(basename $f | sed -e 's/\.ini$//');
echo " [ ] ${disabled} $(PHP_INI_SCAN_DIR=:/usr/local/etc/php/disabled php -r "echo phpversion('${disabled}');")";
done
echo ""
echo "=== PECL Extensions ==="
pear list -c pecl
echo ""
echo "=== Composer Version ==="
composer -V
echo ""
echo "=== Installed System Packages ==="
apk info -vv | sort
EOF
fi

73 changes: 73 additions & 0 deletions .github/format-output.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash

diff_section() {
section="$1"
current_file="current-image-report.txt"
previous_file="previous-image-report.txt"

current_section=$(sed -n "/=== $section ===/,/=== /p" "$current_file" | sed '1d;$d')
previous_section=$(sed -n "/=== $section ===/,/=== /p" "$previous_file" | sed '1d;$d')

if [[ "$section" == "Installed System Packages" ]]; then
diff_output=$(diff <(echo "$previous_section") <(echo "$current_section") | awk '
BEGIN { FS = " - "; OFS = ": "; }
function trim(s) { gsub(/^ +| +$/, "", s); return s }
function clean_marker(s) { gsub(/^< |^> /, "", s); return s }
function extract_pkg_and_description(line, pkg_version, description) {
line = clean_marker(line);
split(line, parts, " - ");
pkg_version = trim(parts[1]);
description = trim(parts[2]);
return pkg_version ":" description;
}
/^</ {
old_line = substr($0, 3);
pkg_desc = extract_pkg_and_description(old_line);
split(pkg_desc, parts, ":");
old_pkg = parts[1];
old_desc = parts[2];
old_versions[old_desc] = old_pkg;
}
/^>/ {
new_line = substr($0, 3);
pkg_desc = extract_pkg_and_description(new_line);
split(pkg_desc, parts, ":");
new_pkg = parts[1];
new_desc = parts[2];
if (new_desc in old_versions) {
print new_desc ": " old_versions[new_desc] " -> " new_pkg;
delete old_versions[new_desc];
} else {
print new_desc ": (new) -> " new_pkg;
}
}
END {
for (desc in old_versions) {
print desc ": " old_versions[desc] " -> (removed)";
}
}')
else
diff_output=$(diff <(echo "$previous_section") <(echo "$current_section") | awk '
/^</ { old_line = substr($0, 3); }
/^>/ { new_line = substr($0, 3); print old_line " -> " new_line; }')
fi

echo "$diff_output"
}

SECTIONS=("PHP Version" "Alpine Version" "Installed PHP Extensions" "Disabled PHP Extensions" "PECL Extensions" "Composer Version" "Installed System Packages")
FORMATTED_DIFF=""

for section in "${SECTIONS[@]}"; do
section_diff=$(diff_section "$section")
if [[ -n "$section_diff" ]]; then
FORMATTED_DIFF+="=== $section ===\\n"
FORMATTED_DIFF+="${section_diff//[$'\n']/\\n}\\n"
fi
done

echo -e "Formatted Diff Output:\n$FORMATTED_DIFF"

echo "FORMATTED_DIFF<<EOF" >> $GITHUB_ENV
echo -e "$FORMATTED_DIFF" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
94 changes: 78 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
name: CI
name: CI/CD

on: push

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -10,17 +14,6 @@ jobs:
matrix:
include:
## Alpine
### Alpine 3.17
- image: "alpine/3.17/8.1/Dockerfile"
tags: [ "spryker/php:8.1-alpine3.17" ]
platforms: [ "linux/amd64", "linux/arm64" ]
- image: "alpine/3.17/8.2/Dockerfile"
tags: [ "spryker/php:8.2-alpine3.17" ]
platforms: [ "linux/amd64", "linux/arm64" ]
- image: "alpine/3.17/8.3/Dockerfile"
tags: [ "spryker/php:8.3-alpine3.17" ]
platforms: [ "linux/amd64", "linux/arm64" ]

### Alpine 3.18
- image: "alpine/3.18/8.1/Dockerfile"
tags: [ "spryker/php:8.1-alpine3.18" ]
Expand Down Expand Up @@ -68,6 +61,7 @@ jobs:
- image: "debian/bullseye/8.3/Dockerfile"
tags: [ "spryker/php:8.3-debian" ]
platforms: [ "linux/amd64", "linux/arm64" ]

steps:
- name: Check out repository
uses: actions/checkout@v3
Expand All @@ -76,10 +70,23 @@ jobs:

- name: Get the previous commit hash
id: previous_commit
if: ${{ github.ref == 'refs/heads/master' }}
run: |
PREV_COMMIT_HASH=$(git rev-parse HEAD^1)
echo "PREV_COMMIT_HASH=$PREV_COMMIT_HASH" >> $GITHUB_ENV
if [ "${{ github.ref }}" == "refs/heads/master" ]; then
PREV_COMMIT_HASH=$(git rev-parse HEAD^1)
else
PREV_COMMIT_HASH=$(git rev-parse origin/master)
IMAGE_TAG="${{ matrix.tags[0] }}"
echo "Pulling image $IMAGE_TAG"
docker pull "$IMAGE_TAG"
NEW_TAG="${IMAGE_TAG}-${PREV_COMMIT_HASH}"
echo "Re-tagging image to $NEW_TAG"
docker tag "$IMAGE_TAG" "$NEW_TAG"
echo "Removing the pulled image $IMAGE_TAG"
docker rmi "$IMAGE_TAG" || true
fi
echo "PREV_COMMIT_HASH=$PREV_COMMIT_HASH" >> $GITHUB_ENV
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
Expand Down Expand Up @@ -111,6 +118,61 @@ jobs:
uses: docker/build-push-action@v2
with:
push: ${{ github.ref == 'refs/heads/master' }}
load: ${{ github.ref != 'refs/heads/master' }}
file: ${{ matrix.image }}
tags: ${{ join(matrix.tags) }}
platforms: ${{ join(matrix.platforms) }}
platforms: ${{ github.ref == 'refs/heads/master' && join(matrix.platforms) || 'linux/amd64' }}

- name: Current image report
id: manifest
run: |
CURRENT_TAG=${{ matrix.tags[0] }}
bash .github/compare-images.sh $CURRENT_TAG > current-image-report.txt || true
cat current-image-report.txt
- name: Previous image report
run: |
PREVIOUS_TAG="${{ matrix.tags[0] }}-${{ env.PREV_COMMIT_HASH }}"
bash .github/compare-images.sh $PREVIOUS_TAG > previous-image-report.txt || true
cat previous-image-report.txt
- name: Run the diff and format output
id: diff
run: bash .github/format-output.sh

- name: Fetch Job ID
id: fetch_job_id
if: ${{ github.ref == 'refs/heads/master' && env.DIFF_OUTPUT != '' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
JOBS_JSON=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/jobs")
echo "$JOBS_JSON" > jobs-response.json
cat jobs-response.json
JOB_ID=$(echo "$JOBS_JSON" | jq -r '.jobs[0].id')
echo "Extracted Job ID: $JOB_ID"
echo "::set-output name=job_id::$JOB_ID"
- name: Send Slack Notification
if: ${{ github.ref == 'refs/heads/master' && env.DIFF_OUTPUT != '' }}
uses: slackapi/[email protected]
with:
payload: |
{
"attachments": [
{
"color": "good",
"fields": [
{
"title": "New version of ${{ matrix.tags[0] }} has been published",
"value": "You can check the:\n- *Manifest*: <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.fetch_job_id.outputs.job_id }}#step:9:1|View Manifest>\n- *Diff*: <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/job/${{ steps.fetch_job_id.outputs.job_id }}#step:11:7|View Diff>\n\nThis version was built out of <https://github.com/${{ github.repository }}/commit/${{ github.sha }}|${{ github.sha }}>.",
"short": false
}
]
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_CE_RELEASE_WEBHOOK }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
103 changes: 103 additions & 0 deletions .github/workflows/cleanup-old-docker-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
name: Cleanup Old Docker Images > 6 months by the scheduler

on:
push:
branches:
- master

jobs:
cleanup:
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v2

- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: List Docker Hub images and delete ones matching the pattern
run: |
REPO="spryker/php"
curl -s "https://hub.docker.com/v2/repositories/${REPO}/tags?page_size=1000" > tags.json
TODAY=$(date +%s)
THRESHOLD=$((180 * 24 * 60 * 60)) # 180 days in seconds
# Regex pattern to match tags that end with a hash (40-character hexadecimal)
HASH_PATTERN=".*-[a-f0-9]{40}$"
IMAGES_DELETED=false
DELETED_IMAGES=""
for TAG in $(jq -r '.results[] | @base64' < tags.json); do
_jq() {
echo ${TAG} | base64 --decode | jq -r ${1}
}
TAG_NAME=$(_jq '.name')
LAST_UPDATED=$(_jq '.last_updated')
LAST_UPDATED_DATE=$(date -d "${LAST_UPDATED}" +%s)
AGE=$((TODAY - LAST_UPDATED_DATE))
if [[ ${AGE} -ge ${THRESHOLD} ]] && [[ ${TAG_NAME} =~ ${HASH_PATTERN} ]]; then
echo "Deleting image tag ${TAG_NAME} (last updated: ${LAST_UPDATED})"
IMAGES_DELETED=true
DELETED_IMAGES="${DELETED_IMAGES}\n${TAG_NAME}"
# Uncomment the following lines to enable image deletion
curl -X DELETE \
-u "${{ secrets.DOCKER_USERNAME }}:${{ secrets.DOCKER_PASSWORD }}" \
"https://hub.docker.com/v2/repositories/${REPO}/tags/${TAG_NAME}/"
fi
done
if [[ ${IMAGES_DELETED} == false ]]; then
echo "No images found for deletion" > deleted_images.txt
else
echo -e "Deleted images: ${DELETED_IMAGES}" > deleted_images.txt
fi
- name: Read Deleted Images
id: read_deleted_images
run: |
DELETED_IMAGES=$(cat deleted_images.txt)
echo "Deleted images: ${DELETED_IMAGES}"
echo "::set-output name=deleted_images::${DELETED_IMAGES}"
shell: bash

- name: Send Slack Notification
uses: slackapi/[email protected]
if: ${{ github.ref == 'refs/heads/master' }}
with:
payload: |
{
"attachments": [
{
"pretext": "Outdated docker images cleanup (180 days) for *${{ github.repository }} repository*",
"color": "good",
"fields": [
{
"title": "Images:",
"value": "${{ steps.read_deleted_images.outputs.deleted_images }}",
"short": false
},
{
"title": "Branch:",
"value": "${{ github.ref }}",
"short": true
},
{
"title": "Commit:",
"value": "${{ github.sha }}",
"short": true
}
]
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
Loading

0 comments on commit 337a2f4

Please sign in to comment.