Skip to content

Commit 116ce90

Browse files
committed
setup 2.9 build workflow
1 parent 83bbc89 commit 116ce90

File tree

4 files changed

+375
-3
lines changed

4 files changed

+375
-3
lines changed

.github/actions/determine-composer-version/action.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ runs:
1818
steps:
1919
- name: "Determine composer version from Dockerfile"
2020
run: |
21-
echo "COMPOSER_VERSION_MAJOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+' Dockerfile | cut -d '.' -f 1)" >> $GITHUB_ENV
22-
echo "COMPOSER_VERSION_MAJOR_MINOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+' Dockerfile | cut -d '.' -f 1,2)" >> $GITHUB_ENV
23-
echo "COMPOSER_VERSION_MAJOR_MINOR_PATCH=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+' Dockerfile)" >> $GITHUB_ENV
21+
echo "COMPOSER_VERSION_MAJOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(?:-RC\d+)' Dockerfile | cut -d '.' -f 1)" >> $GITHUB_ENV
22+
echo "COMPOSER_VERSION_MAJOR_MINOR=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(?:-RC\d+)' Dockerfile | cut -d '.' -f 1,2)" >> $GITHUB_ENV
23+
echo "COMPOSER_VERSION_MAJOR_MINOR_PATCH=$(grep -oP 'ENV COMPOSER_VERSION=\K\d+\.\d+\.\d+(?:-RC\d+)' Dockerfile)" >> $GITHUB_ENV
2424
shell: "bash"
2525
working-directory: "${{ inputs.working-directory }}"

.github/workflows/2.9.yaml

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
name: 2.9 (RC)
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
paths:
7+
- 2.9.yaml
8+
- 2.9/**
9+
push:
10+
branches:
11+
- main
12+
paths:
13+
- 2.9.yaml
14+
- 2.9/**
15+
16+
env:
17+
AWS_REGION: us-east-1
18+
DOCKERHUB_SLUG: composer/composer
19+
ECR_SLUG: public.ecr.aws/u0u1j5s3/composer
20+
GHCR_SLUG: ghcr.io/composer/docker
21+
DIRECTORY: '2.9'
22+
23+
jobs:
24+
25+
prepare:
26+
27+
runs-on: ubuntu-latest
28+
29+
outputs:
30+
full-annotations: ${{ steps.meta-full.outputs.annotations }}
31+
full-labels: ${{ steps.meta-full.outputs.labels }}
32+
full-json: ${{ steps.meta-full.outputs.json }}
33+
bin-annotations: ${{ steps.meta-bin.outputs.annotations }}
34+
bin-labels: ${{ steps.meta-bin.outputs.labels }}
35+
bin-json: ${{ steps.meta-bin.outputs.json }}
36+
37+
steps:
38+
39+
- name: Checkout
40+
uses: actions/checkout@v5
41+
42+
- name: Determine Composer version from Dockerfile
43+
uses: ./.github/actions/determine-composer-version
44+
with:
45+
working-directory: ${{ env.DIRECTORY }}
46+
47+
- name: Docker metadata (full image)
48+
id: meta-full
49+
uses: docker/metadata-action@v5
50+
with:
51+
images: |
52+
${{ env.DOCKERHUB_SLUG }}
53+
${{ env.ECR_SLUG }}
54+
${{ env.GHCR_SLUG }}
55+
flavor: |
56+
latest=false
57+
tags: |
58+
type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }}
59+
type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }}
60+
labels: |
61+
org.opencontainers.image.vendor=Composer
62+
org.opencontainers.image.title=Composer
63+
org.opencontainers.image.description=PHP runtime image with Composer
64+
65+
- name: Docker metadata (binary-only image)
66+
id: meta-bin
67+
uses: docker/metadata-action@v5
68+
with:
69+
images: |
70+
${{ env.DOCKERHUB_SLUG }}
71+
${{ env.ECR_SLUG }}
72+
${{ env.GHCR_SLUG }}
73+
flavor: |
74+
latest=false
75+
suffix=-bin
76+
tags: |
77+
type=semver,pattern={{version}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }}
78+
type=semver,pattern={{major}}.{{minor}},value=${{ env.COMPOSER_VERSION_MAJOR_MINOR_PATCH }}
79+
labels: |
80+
org.opencontainers.image.vendor=Composer
81+
org.opencontainers.image.title=Composer
82+
org.opencontainers.image.description=Image with Composer binary only
83+
84+
build:
85+
86+
runs-on: ubuntu-latest
87+
timeout-minutes: 20
88+
89+
needs:
90+
- prepare
91+
92+
strategy:
93+
matrix:
94+
platform:
95+
- linux/amd64
96+
- linux/arm/v6
97+
- linux/arm/v7
98+
- linux/arm64/v8
99+
- linux/i386
100+
- linux/ppc64le
101+
- linux/riscv64
102+
- linux/s390x
103+
104+
defaults:
105+
run:
106+
working-directory: ${{ env.DIRECTORY }}
107+
108+
steps:
109+
110+
- name: Checkout
111+
uses: actions/checkout@v5
112+
113+
- name: Prepare
114+
run: |
115+
platform=${{ matrix.platform }}
116+
echo "PLATFORM_SLUG=${platform//\//-}" >> $GITHUB_ENV
117+
118+
- name: Set up QEMU
119+
uses: docker/setup-qemu-action@v3
120+
with:
121+
platforms: ${{ matrix.platform }}
122+
123+
- name: Set up Docker Buildx
124+
uses: docker/setup-buildx-action@v3
125+
126+
- name: Login to Docker Hub
127+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
128+
uses: docker/login-action@v3
129+
with:
130+
username: ${{ secrets.DOCKERHUB_USERNAME }}
131+
password: ${{ secrets.DOCKERHUB_PASSWORD }}
132+
133+
- name: Login to Amazon Public ECR
134+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
135+
uses: docker/login-action@v3
136+
with:
137+
registry: public.ecr.aws
138+
username: ${{ secrets.AWS_ECR_ACCESS_KEY }}
139+
password: ${{ secrets.AWS_ECR_SECRET_KEY }}
140+
141+
- name: Login to Github Container Registry
142+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
143+
uses: docker/login-action@v3
144+
with:
145+
registry: ghcr.io
146+
username: ${{ github.repository_owner }}
147+
password: ${{ secrets.GITHUB_TOKEN }}
148+
149+
- name: Build full image
150+
id: build-full
151+
uses: docker/build-push-action@v6
152+
with:
153+
context: ${{ env.DIRECTORY }}
154+
target: binary-with-runtime
155+
annotations: ${{ needs.prepare.outputs.full-annotations }}
156+
platforms: ${{ matrix.platform }}
157+
outputs: type=image,"name=${{ env.DOCKERHUB_SLUG }},${{ env.ECR_SLUG }},${{ env.GHCR_SLUG }}",push-by-digest=true,name-canonical=true,push=${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }}
158+
159+
- name: Build binary-only image
160+
id: build-bin
161+
uses: docker/build-push-action@v6
162+
with:
163+
context: ${{ env.DIRECTORY }}
164+
target: standalone-binary
165+
annotations: ${{ needs.prepare.outputs.bin-annotations }}
166+
platforms: ${{ matrix.platform }}
167+
outputs: type=image,"name=${{ env.DOCKERHUB_SLUG }},${{ env.ECR_SLUG }},${{ env.GHCR_SLUG }}",push-by-digest=true,name-canonical=true,push=${{ github.ref == 'refs/heads/main' && github.event_name != 'pull_request' }}
168+
169+
- name: Export digests
170+
run: |
171+
mkdir -p /tmp/digests/{full,bin}
172+
digest="${{ steps.build-full.outputs.digest }}"
173+
touch "/tmp/digests/full/${digest#sha256:}"
174+
digest="${{ steps.build-bin.outputs.digest }}"
175+
touch "/tmp/digests/bin/${digest#sha256:}"
176+
177+
- name: Upload digests
178+
uses: actions/upload-artifact@v5
179+
with:
180+
name: digests-${{ env.PLATFORM_SLUG }}
181+
path: |
182+
/tmp/digests/full/*
183+
/tmp/digests/bin/*
184+
if-no-files-found: error
185+
retention-days: 1
186+
187+
merge:
188+
189+
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
190+
191+
runs-on: ubuntu-latest
192+
193+
needs:
194+
- prepare
195+
- build
196+
197+
steps:
198+
199+
- name: Download digests
200+
uses: actions/download-artifact@v6
201+
with:
202+
path: /tmp/digests
203+
pattern: digests-*
204+
merge-multiple: true
205+
206+
- name: Set up Docker Buildx
207+
uses: docker/setup-buildx-action@v3
208+
209+
- name: Login to Docker Hub
210+
uses: docker/login-action@v3
211+
with:
212+
username: ${{ secrets.DOCKERHUB_USERNAME }}
213+
password: ${{ secrets.DOCKERHUB_PASSWORD }}
214+
215+
- name: Login to Amazon Public ECR
216+
uses: docker/login-action@v3
217+
with:
218+
registry: public.ecr.aws
219+
username: ${{ secrets.AWS_ECR_ACCESS_KEY }}
220+
password: ${{ secrets.AWS_ECR_SECRET_KEY }}
221+
222+
- name: Login to Github Container Registry
223+
uses: docker/login-action@v3
224+
with:
225+
registry: ghcr.io
226+
username: ${{ github.repository_owner }}
227+
password: ${{ secrets.GITHUB_TOKEN }}
228+
229+
- name: Create manifest list for full image and push
230+
working-directory: /tmp/digests/full
231+
env:
232+
JSON: ${{ needs.prepare.outputs.full-json }}
233+
run: |
234+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
235+
$(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *)
236+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
237+
$(printf '${{ env.ECR_SLUG }}@sha256:%s ' *)
238+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
239+
$(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *)
240+
241+
- name: Create manifest list for binary-only image and push
242+
working-directory: /tmp/digests/bin
243+
env:
244+
JSON: ${{ needs.prepare.outputs.bin-json }}
245+
run: |
246+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.DOCKERHUB_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
247+
$(printf '${{ env.DOCKERHUB_SLUG }}@sha256:%s ' *)
248+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.ECR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
249+
$(printf '${{ env.ECR_SLUG }}@sha256:%s ' *)
250+
docker buildx imagetools create $(jq -cr '.tags | map(select(startswith("${{ env.GHCR_SLUG }}")) | "--tag " + .) | join(" ")' <<< "$JSON") \
251+
$(printf '${{ env.GHCR_SLUG }}@sha256:%s ' *)

2.9/Dockerfile

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
FROM php:8-alpine AS binary-with-runtime
2+
3+
RUN set -eux ; \
4+
apk add --no-cache --virtual .composer-rundeps \
5+
7zip \
6+
bash \
7+
coreutils \
8+
git \
9+
make \
10+
mercurial \
11+
openssh-client \
12+
patch \
13+
subversion \
14+
tini \
15+
unzip \
16+
zip
17+
18+
RUN printf "# composer php cli ini settings\n\
19+
date.timezone=UTC\n\
20+
memory_limit=-1\n\
21+
" > $PHP_INI_DIR/php-cli.ini
22+
23+
ENV COMPOSER_ALLOW_SUPERUSER=1
24+
ENV COMPOSER_HOME=/tmp
25+
ENV COMPOSER_VERSION=2.9.0-RC1
26+
27+
RUN set -eux ; \
28+
# install https://github.com/mlocati/docker-php-extension-installer
29+
curl \
30+
--silent \
31+
--fail \
32+
--location \
33+
--retry 3 \
34+
--output /usr/local/bin/install-php-extensions \
35+
--url https://github.com/mlocati/docker-php-extension-installer/releases/download/1.2.58/install-php-extensions \
36+
; \
37+
echo 182011b3dca5544a70fdeb587af44ed1760aa9a2ed37d787d0f280a99f92b008e638c37762360cd85583830a097665547849cb2293c4a0ee32c2a36ef7a349e2 /usr/local/bin/install-php-extensions | sha512sum --strict --check ; \
38+
chmod +x /usr/local/bin/install-php-extensions ; \
39+
# install necessary/useful extensions not included in base image
40+
install-php-extensions \
41+
bz2 \
42+
zip \
43+
; \
44+
# install public keys for snapshot and tag validation, see https://composer.github.io/pubkeys.html
45+
curl \
46+
--silent \
47+
--fail \
48+
--location \
49+
--retry 3 \
50+
--output /tmp/keys.dev.pub \
51+
--url https://raw.githubusercontent.com/composer/composer.github.io/e7f28b7200249f8e5bc912b42837d4598c74153a/snapshots.pub \
52+
; \
53+
echo 572b963c4b7512a7de3c71a788772440b1996d918b1d2b5354bf8ba2bb057fadec6f7ac4852f2f8a8c01ab94c18141ce0422aec3619354b057216e0597db5ac2 /tmp/keys.dev.pub | sha512sum --strict --check ; \
54+
curl \
55+
--silent \
56+
--fail \
57+
--location \
58+
--retry 3 \
59+
--output /tmp/keys.tags.pub \
60+
--url https://raw.githubusercontent.com/composer/composer.github.io/e7f28b7200249f8e5bc912b42837d4598c74153a/releases.pub \
61+
; \
62+
echo 47f374b8840dcb0aa7b2327f13d24ab5f6ae9e58aa630af0d62b3d0ea114f4a315c5d97b21dcad3c7ffe2f0a95db2edec267adaba3f4f5a262abebe39aed3a28 /tmp/keys.tags.pub | sha512sum --strict --check ; \
63+
# download installer.php, see https://getcomposer.org/download/
64+
curl \
65+
--silent \
66+
--fail \
67+
--location \
68+
--retry 3 \
69+
--output /tmp/installer.php \
70+
--url https://raw.githubusercontent.com/composer/getcomposer.org/f24b8f860b95b52167f91bbd3e3a7bcafe043038/web/installer \
71+
; \
72+
echo 3137ad86bd990524ba1dedc2038309dfa6b63790d3ca52c28afea65dcc2eaead16fb33e9a72fd2a7a8240afaf26e065939a2d472f3b0eeaa575d1e8648f9bf19 /tmp/installer.php | sha512sum --strict --check ; \
73+
# install composer phar binary
74+
php /tmp/installer.php \
75+
--no-ansi \
76+
--install-dir=/usr/bin \
77+
--filename=composer \
78+
--version=${COMPOSER_VERSION} \
79+
; \
80+
composer --ansi --version --no-interaction ; \
81+
rm -f /tmp/installer.php ; \
82+
find /tmp -type d -exec chmod -v 1777 {} +
83+
84+
COPY docker-entrypoint.sh /docker-entrypoint.sh
85+
86+
WORKDIR /app
87+
88+
ENTRYPOINT ["/docker-entrypoint.sh"]
89+
90+
CMD ["composer"]
91+
92+
FROM scratch AS standalone-binary
93+
94+
COPY --from=binary-with-runtime /usr/bin/composer /composer
95+
96+
# This is defined as last target to be backward compatible with build without explicit --target option
97+
FROM binary-with-runtime AS default

2.9/docker-entrypoint.sh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/sh
2+
3+
isCommand() {
4+
# Retain backwards compatibility with common CI providers,
5+
# see: https://github.com/composer/docker/issues/107
6+
if [ "$1" = "sh" ]; then
7+
return 1
8+
fi
9+
10+
composer help --no-interaction "$1" > /dev/null 2>&1
11+
}
12+
13+
# check if the first argument passed in looks like a flag
14+
if [ "${1#-}" != "$1" ]; then
15+
set -- /sbin/tini -- composer "$@"
16+
# check if the first argument passed in is composer
17+
elif [ "$1" = 'composer' ]; then
18+
set -- /sbin/tini -- "$@"
19+
# check if the first argument passed in matches a known command
20+
elif isCommand "$1"; then
21+
set -- /sbin/tini -- composer "$@"
22+
fi
23+
24+
exec "$@"

0 commit comments

Comments
 (0)