📎 Backport .github and scripts/ci from develop

This commit is contained in:
Andrey Antukh 2026-10-08 19:24:58 +02:00
parent fad083314d
commit ff4c4a4a34
5 changed files with 297 additions and 6 deletions

View File

@ -13,8 +13,14 @@ permissions: {}
jobs:
triage:
# Dependabot PRs are labelled by dependabot.yml and do not need triage.
if: github.actor != 'dependabot[bot]'
# The Renovate Dependency Dashboard and Renovate's GitHub Actions PRs do
# not need triage. Other Renovate PRs (base images, Node.js, pnpm) do.
if: >-
!(github.event_name == 'issues'
&& github.event.issue.user.login == 'penpot-renovate[bot]')
&& !(github.event_name == 'pull_request_target'
&& github.event.pull_request.user.login == 'penpot-renovate[bot]'
&& github.event.pull_request.head.ref == 'renovate-github-actions')
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token

View File

@ -6,22 +6,34 @@ on:
permissions:
contents: read
concurrency:
group: build-docker-devenv
cancel-in-progress: false
jobs:
build-and-push:
name: Build and push DevEnv Docker image
runs-on: penpot-standar-runner
timeout-minutes: 90
env:
DOCKER_IMAGE: 'penpotapp/devenv'
steps:
- name: Set common environment variables
run: |
# Each job execution will use its own docker configuration.
echo "DOCKER_CONFIG=${{ runner.temp }}/.docker-${{ github.run_id }}-${{ github.job }}" >> $GITHUB_ENV
echo "DOCKER_CONFIG=${RUNNER_TEMP}/.docker-${GITHUB_RUN_ID}-${GITHUB_JOB}" >> "$GITHUB_ENV"
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up QEMU
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
@ -40,8 +52,6 @@ jobs:
- name: Build and push DevEnv Docker image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
env:
DOCKER_IMAGE: 'penpotapp/devenv'
with:
context: ./docker/devenv/
file: ./docker/devenv/Dockerfile
@ -61,4 +71,13 @@ jobs:
TEXT: |
🚀 *[PENPOT] New devenv available*
📄 You may want to update your devenv.
@alvaro
- name: Notify Mattermost (developers)
uses: mattermost/action-mattermost-notify@ae31bb6f9e26a54336e79696f108a2c91cf55b4e # v2.1.0
with:
MATTERMOST_WEBHOOK_URL: ${{ secrets.MATTERMOST_WEBHOOK }}
MATTERMOST_CHANNEL: penpotdev
TEXT: |
🚀 *[PENPOT] New devenv available*
📄 You may want to update your devenv.
(\cc @alvaro)

256
.github/workflows/build-renovate.yml vendored Normal file
View File

@ -0,0 +1,256 @@
name: Renovate Docker Image Check
# Triggered by pushes to Renovate branches, not by pull_request: this is a
# public repository and these jobs run on the self-hosted runners, so a PR
# from a fork must never be able to start them. Only users with write
# access can push here.
on:
push:
branches:
- 'renovate-*'
permissions: {}
concurrency:
group: renovate-image-check-${{ github.ref_name }}
cancel-in-progress: true
env:
BUNDLE_CACHE: /var/tmp/penpot-bundle-cache
jobs:
# ── 1. Pick an existing develop bundle and detect what changed ────────
prepare:
name: Prepare
runs-on: penpot-standar-runner
timeout-minutes: 10
permissions:
contents: read
outputs:
short_sha: ${{ steps.bundle.outputs.short_sha }}
images: ${{ steps.changes.outputs.images }}
devenv: ${{ steps.changes.outputs.devenv }}
imagemagick: ${{ steps.changes.outputs.imagemagick }}
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
fetch-depth: 0
- name: Find the develop commit this branch is based on
id: base
run: |
echo "sha=$(git merge-base HEAD origin/develop)" >> "$GITHUB_OUTPUT"
- name: Detect changed images
id: changes
env:
BASE_SHA: ${{ steps.base.outputs.sha }}
run: |
changed() {
git diff --quiet "$BASE_SHA" HEAD -- "$@" && echo false || echo true
}
{
# Anything outside .github can affect the production images.
echo "images=$(changed . ':!.github')"
echo "devenv=$(changed docker/devenv)"
echo "imagemagick=$(changed docker/imagemagick)"
} >> "$GITHUB_OUTPUT"
# Renovate only changes Dockerfiles and package manager versions, so
# the most recent develop bundle is enough to build the images.
- name: Find the latest develop bundle
id: bundle
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
BASE_SHA: ${{ steps.base.outputs.sha }}
run: |
for SHA in $(git rev-list --first-parent --max-count=50 "$BASE_SHA"); do
SHORT_SHA=$(git rev-parse --short=12 "$SHA")
if aws s3api head-object --bucket "$S3_BUCKET" \
--key "penpot-sha-${SHORT_SHA}.zip" > /dev/null 2>&1; then
echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT"
echo "Using bundle \`penpot-sha-${SHORT_SHA}.zip\`" >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
done
echo "::error::No bundle found for the last 50 develop commits"
exit 1
# ── 2. Production images, built from the PR Dockerfiles ───────────────
images:
name: Build ${{ matrix.image }}
runs-on: penpot-standar-runner
timeout-minutes: 60
needs: prepare
if: needs.prepare.outputs.images == 'true'
permissions:
contents: read
strategy:
fail-fast: false
max-parallel: 3
matrix:
image: [backend, frontend, exporter, storybook, mcp]
steps:
- name: Set common environment variables
env:
MATRIX_IMAGE: ${{ matrix.image }}
run: |
echo "DOCKER_CONFIG=${RUNNER_TEMP}/.docker-${GITHUB_RUN_ID}-${GITHUB_JOB}-${MATRIX_IMAGE}" >> "$GITHUB_ENV"
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Login to Docker Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to DockerHub Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Login to Docker Hardened Images registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: dhi.io
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Prepare Penpot bundle
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.AWS_REGION }}
S3_BUCKET: ${{ secrets.S3_BUCKET }}
SHORT_SHA: ${{ needs.prepare.outputs.short_sha }}
IMAGE: ${{ matrix.image }}
run: |
ZIP="$BUNDLE_CACHE/penpot-sha-${SHORT_SHA}.zip"
if [ ! -f "$ZIP" ]; then
mkdir -p "$BUNDLE_CACHE"
aws s3 cp "s3://${S3_BUCKET}/penpot-sha-${SHORT_SHA}.zip" "$ZIP.$$.tmp"
mv "$ZIP.$$.tmp" "$ZIP"
fi
pushd docker/images
unzip -q "$ZIP" "penpot/${IMAGE}/*"
mv "penpot/${IMAGE}" "bundle-${IMAGE}"
popd
- name: Set up QEMU
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- name: Build Docker image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: ./docker/images/
file: ./docker/images/Dockerfile.${{ matrix.image }}
platforms: linux/amd64,linux/arm64
push: false
cache-from: type=registry,ref=${{ secrets.DOCKER_REGISTRY }}/${{ matrix.image }}:buildcache
# ── 3. Devenv, only when the PR touches it ────────────────────────────
devenv:
name: Build devenv
runs-on: penpot-standar-runner
timeout-minutes: 90
needs: prepare
if: needs.prepare.outputs.devenv == 'true'
permissions:
contents: read
steps:
- name: Set common environment variables
run: |
echo "DOCKER_CONFIG=${RUNNER_TEMP}/.docker-${GITHUB_RUN_ID}-${GITHUB_JOB}" >> "$GITHUB_ENV"
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Login to DockerHub Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Login to Docker Hardened Images registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: dhi.io
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Set up QEMU
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- name: Build devenv image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: ./docker/devenv/
file: ./docker/devenv/Dockerfile
platforms: linux/amd64,linux/arm64
push: false
cache-from: type=registry,ref=penpotapp/devenv:buildcache
# ── 4. ImageMagick, only when the PR touches it ───────────────────────
# amd64 only: compiling ImageMagick under QEMU takes too long for a check.
imagemagick:
name: Build imagemagick
runs-on: penpot-standar-runner
timeout-minutes: 60
needs: prepare
if: needs.prepare.outputs.imagemagick == 'true'
permissions:
contents: read
steps:
- name: Set common environment variables
run: |
echo "DOCKER_CONFIG=${RUNNER_TEMP}/.docker-${GITHUB_RUN_ID}-${GITHUB_JOB}" >> "$GITHUB_ENV"
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Login to Docker Hardened Images registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: dhi.io
username: ${{ secrets.PUB_DOCKER_USERNAME }}
password: ${{ secrets.PUB_DOCKER_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- name: Build imagemagick image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: ./docker/imagemagick/
file: ./docker/imagemagick/Dockerfile
platforms: linux/amd64
push: false

View File

@ -80,6 +80,10 @@ jobs:
- name: Tests
working-directory: ./backend
env:
# `clojure.core/assert` is elided at compile time, so without this
# flag the precondition asserts do not exist in the compiled code
# and the suite silently stops checking them.
PENPOT_FLAGS: "enable-backend-asserts"
PENPOT_TEST_DATABASE_URI: "postgresql://postgres/penpot_test"
PENPOT_TEST_DATABASE_USERNAME: penpot_test
PENPOT_TEST_DATABASE_PASSWORD: penpot_test

View File

@ -8,6 +8,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
LOG_DIR="$PROJECT_ROOT/.ci-logs"
# `clojure.core/assert` is elided at compile time when `*assert*` is false,
# and `app.config` only sets that var from these flags. Without this the
# backend suite runs with every assertion compiled out, silently. Appending
# keeps whatever flags the caller already exported.
export PENPOT_FLAGS="${PENPOT_FLAGS:+$PENPOT_FLAGS } enable-backend-asserts"
# Color codes
RED='\033[0;31m'
GREEN='\033[0;32m'