Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,612 changes: 4,151 additions & 1,461 deletions .github/workflows/build.yaml

Large diffs are not rendered by default.

42 changes: 15 additions & 27 deletions build-local.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,42 +11,30 @@ PHP_VERSION=8.5

if [ "$#" -gt 0 ]; then
PHP_VERSION=$1
if [ ! -d "$ROOT_DIR/docker/php/$PHP_VERSION" ]; then
if [ ! -d "docker/php/$PHP_VERSION" ]; then
echo "PHP version $PHP_VERSION not found"
exit 1
fi
fi

# alpine
cd $ROOT_DIR/docker/php/$PHP_VERSION-alpine
docker build -t webdevops/php:$PHP_VERSION-alpine .
cd $ROOT_DIR/docker/php-dev/$PHP_VERSION-alpine
docker build -t webdevops/php-dev:$PHP_VERSION-alpine .
docker build -t webdevops/php:$PHP_VERSION-alpine docker/php/$PHP_VERSION-alpine
docker build -t webdevops/php-dev:$PHP_VERSION-alpine docker/php-dev/$PHP_VERSION-alpine

cd $ROOT_DIR/docker/php-nginx/$PHP_VERSION-alpine
docker build -t webdevops/php-nginx:$PHP_VERSION-alpine .
cd $ROOT_DIR/docker/php-nginx-dev/$PHP_VERSION-alpine
docker build -t webdevops/php-nginx-dev:$PHP_VERSION-alpine .
docker build -t webdevops/php-nginx:$PHP_VERSION-alpine docker/php-nginx/$PHP_VERSION-alpine
docker build -t webdevops/php-nginx-dev:$PHP_VERSION-alpine docker/php-nginx-dev/$PHP_VERSION-alpine

cd $ROOT_DIR/docker/php-apache/$PHP_VERSION-alpine
docker build -t webdevops/php-apache:$PHP_VERSION-alpine .
cd $ROOT_DIR/docker/php-apache-dev/$PHP_VERSION-alpine
docker build -t webdevops/php-apache-dev:$PHP_VERSION-alpine .
docker build -t webdevops/php-apache:$PHP_VERSION-alpine docker/php-apache/$PHP_VERSION-alpine
docker build -t webdevops/php-apache-dev:$PHP_VERSION-alpine docker/php-apache-dev/$PHP_VERSION-alpine

# debian
cd $ROOT_DIR/docker/php/$PHP_VERSION
docker build -t webdevops/php:$PHP_VERSION .
cd $ROOT_DIR/docker/php-dev/$PHP_VERSION
docker build -t webdevops/php-dev:$PHP_VERSION .

cd $ROOT_DIR/docker/php-nginx/$PHP_VERSION
docker build -t webdevops/php-nginx:$PHP_VERSION .
cd $ROOT_DIR/docker/php-nginx-dev/$PHP_VERSION
docker build -t webdevops/php-nginx-dev:$PHP_VERSION .

cd $ROOT_DIR/docker/php-apache/$PHP_VERSION
docker build -t webdevops/php-apache:$PHP_VERSION .
cd $ROOT_DIR/docker/php-apache-dev/$PHP_VERSION
docker build -t webdevops/php-apache-dev:$PHP_VERSION .
docker build -t webdevops/php:$PHP_VERSION docker/php/$PHP_VERSION
docker build -t webdevops/php-dev:$PHP_VERSION docker/php-dev/$PHP_VERSION

docker build -t webdevops/php-nginx:$PHP_VERSION docker/php-nginx/$PHP_VERSION
docker build -t webdevops/php-nginx-dev:$PHP_VERSION docker/php-nginx-dev/$PHP_VERSION

docker build -t webdevops/php-apache:$PHP_VERSION docker/php-apache/$PHP_VERSION
docker build -t webdevops/php-apache-dev:$PHP_VERSION docker/php-apache-dev/$PHP_VERSION

docker images | grep webdevops | grep $PHP_VERSION
6 changes: 5 additions & 1 deletion ci/src/Commands/GithubCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,16 @@ private function traverse(Node $node): void
if ($node->getLevel() > $this->deepestLevel) {
$this->deepestLevel = $node->getLevel();
}
$this->jobs[GithubJobBuilder::toJobId($node->getId())] = $this->jobBuilder->getJobDescription($nodeAr);
$this->jobs = [
...$this->jobs,
...$this->jobBuilder->getJobsDescription($nodeAr),
];
if ($this->isNameBlacklisted($nodeAr['id'])) {
// $this->jobs[GithubJobBuilder::toJobId($node->getId())] = array_merge($this->jobs[GithubJobBuilder::toJobId($node->getId())], ['when' => 'manual']);
$line .= ' *blacklisted*';
if ($node->get('tag') !== $this->_settings['docker']['autoLatestTag']) {
unset($this->jobs[GithubJobBuilder::toJobId($node->getId())]);
unset($this->jobs[GithubJobBuilder::toJobId($node->getId()) . '_publish']);
}
}
$this->output->write([str_pad('', $node->getLevel() - 1, "\t", STR_PAD_LEFT), $line, PHP_EOL]);
Expand Down
194 changes: 129 additions & 65 deletions ci/src/GithubJobBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,83 +2,148 @@

namespace Webdevops\Build;

use function array_filter;
use function array_values;
use function dirname;
use function implode;
use function str_replace;

class GithubJobBuilder
{

public function getJobDescription(array $node): array
/**
* @return array<string, array<string, mixed>>
*/
public function getJobsDescription(array $node): array
{
$serverSpec = $this->serverSpec($node);
$structuredTests = $this->structuredTests($node);

$jobId = GithubJobBuilder::toJobId($node['name']);
$needs = ($node['parent'] ?? null) ? GithubJobBuilder::toJobId($node['parent']) . '_publish' : 'validate-automation';

$pushTags = [];
$pushTags[] = '-t "' . $node['id'] . '"';
$pushTags[] = '-t "ghcr.io/' . $node['id'] . '"';
foreach ($node['aliases'] as $alias) {
$pushTags[] = '-t "' . $alias . '"';
$pushTags[] = '-t "ghcr.io/' . $alias . '"';
}
return [
'name' => $node['name'],
'needs' => [
($node['parent'] ?? null) ? GithubJobBuilder::toJobId($node['parent']) : 'validate-automation',
],
'runs-on' => 'ubuntu-latest',
'container' => 'webdevops/dockerfile-build-env',
'steps' => array_values(
array_filter(
[
['uses' => 'actions/checkout@v4'],
// ['uses' => 'docker/setup-qemu-action@v3'], // only needed for ARM builds
['uses' => 'docker/setup-buildx-action@v3'],
[
'name' => 'Build x64',
'uses' => 'docker/build-push-action@v6',
'with' => [
'context' => dirname(str_replace(__DIR__ . '/../../', '', $node['file'])),
'load' => true,
'tags' => 'ghcr.io/webdevops/' . $node['image'] . ':' . $node['tag'] . ',webdevops/' . $node['image'] . ':' . $node['tag'],
'platforms' => 'linux/amd64',
$jobId => [
'strategy' => [
'fail-fast' => false,
'matrix' => [
'include' => [
[
'arch' => 'amd64',
'runner' => 'ubuntu-24.04',
'platform' => 'linux/amd64',
],
],
$serverSpec ? [
'name' => 'run serverspec',
'run' => implode("\n", $serverSpec),
] : null,
$structuredTests ? [
'name' => 'run structure-test',
'run' => implode("\n", $structuredTests),
] : null,
[
'if' => '${{github.ref == \'refs/heads/master\'}}',
'name' => 'Login to ghcr.io',
'uses' => 'docker/login-action@v3',
'with' => [
'registry' => 'ghcr.io',
'username' => '${{ github.actor }}',
'password' => '${{ secrets.GITHUB_TOKEN }}',
[
'arch' => 'arm64',
'runner' => 'ubuntu-24.04-arm',
'platform' => 'linux/arm64',
],
],
],
],
'name' => $node['name'] . ' (${{ matrix.arch }})',
'needs' => $needs,
// even run if previous job skipped
'if' => '${{ !failure() }}',
'runs-on' => '${{ matrix.runner }}',
'container' => 'webdevops/dockerfile-build-env',
'steps' => array_values(
array_filter(
[
// login after the build so the rate limit of github is used and not from our login Token.
'if' => '${{github.ref == \'refs/heads/master\'}}',
'name' => 'Login to hub.docker.com',
'uses' => 'docker/login-action@v3',
'with' => [
'username' => '${{ secrets.DOCKERHUB_USERNAME }}',
'password' => '${{ secrets.DOCKERHUB_TOKEN }}',
['uses' => 'actions/checkout@v6'],
['uses' => 'docker/setup-buildx-action@v3'],
[
'name' => 'Build (load locally)',
'uses' => 'docker/build-push-action@v6',
'with' => [
'context' => dirname(str_replace(__DIR__ . '/../../', '', $node['file'])),
'platforms' => '${{ matrix.platform }}',
'load' => true,
'tags' => 'ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-${{ matrix.arch }}-' . $node['tag'],
'cache-from' => 'type=gha',
'cache-to' => 'type=gha,mode=max',
'build-args' => implode("\n", [
'TARGETARCH=${{ matrix.arch }}',
]),
],
],
],
[
'if' => '${{github.ref == \'refs/heads/master\'}}',
'name' => 'Push',
// 'name' => 'Build ARM + Push',
'uses' => 'docker/build-push-action@v6',
'with' => [
'context' => dirname(str_replace(__DIR__ . '/../../', '', $node['file'])),
'push' => true,
'tags' => 'ghcr.io/webdevops/' . $node['image'] . ':' . $node['tag'] . ',webdevops/' . $node['image'] . ':' . $node['tag'],
'platforms' => 'linux/amd64',
// 'platforms' => 'linux/amd64,linux/arm64', // ARM not ready yet
$serverSpec ? [
'name' => 'run serverspec',
'run' => implode("\n", $serverSpec),
] : null,
$structuredTests ? [
'name' => 'run structure-test',
'run' => implode("\n", $structuredTests),
] : null,
[
'if' => '${{github.ref == \'refs/heads/master\'}}',
'name' => 'Login to ghcr.io',
'uses' => 'docker/login-action@v3',
'with' => [
'registry' => 'ghcr.io',
'username' => '${{ github.actor }}',
'password' => '${{ secrets.GITHUB_TOKEN }}',
],
],
[
'name' => 'Push arch image',
'if' => '${{github.ref == \'refs/heads/master\'}}',
'run' => 'docker push "ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-${{ matrix.arch }}"-' . $node['tag'],
],
],
],
),
),
),
],
$jobId . '_publish' => [
'name' => $node['name'] . ' - Publish',
'runs-on' => 'ubuntu-latest',
'needs' => $jobId,
'if' => '${{github.ref == \'refs/heads/master\'}}',
'steps' => [
['uses' => 'docker/setup-buildx-action@v3'],
[
'name' => 'Login to ghcr.io',
'uses' => 'docker/login-action@v3',
'with' => [
'registry' => 'ghcr.io',
'username' => '${{ github.actor }}',
'password' => '${{ secrets.GITHUB_TOKEN }}',
],
],
[
'name' => 'Login to hub.docker.com',
'uses' => 'docker/login-action@v3',
'with' => [
'username' => '${{ secrets.DOCKERHUB_USERNAME }}',
'password' => '${{ secrets.DOCKERHUB_TOKEN }}',
],
],
[
'name' => 'Create and push multi-arch manifest',
'run' =>
// we need the retry loop here because sometimes docker hub returns errors when pushing manifests (especially if pushed to the same image multiple times in a short time frame)
implode("\n", [
'set -euo pipefail',
'for i in 1 2 3 4 5 6 7 8 9 10; do',
' ' . implode(" \\\n ", [
'docker buildx imagetools create',
...$pushTags,
'"ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-amd64-' . $node['tag'] . '"',
'"ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-arm64-' . $node['tag'] . '" && exit 0',
]),
' sleep $((i*i))',
'done',
'exit 1',
]),
],
],
],
];
}

Expand All @@ -98,14 +163,13 @@ private function serverSpec(array $node): array
return [];
}

// $testDockerfile = uniqid('Dockerfile_', true);
$testDockerfile = 'Dockerfile_test';
$specConfig = $node['serverspec'];
$specConfig['DOCKERFILE'] = $testDockerfile;
$encodedJsonConfig = base64_encode(json_encode($specConfig));
$script = [
'cd tests/serverspec',
'echo "FROM ' . $node['id'] . '" >> ' . $testDockerfile,
'echo "FROM ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-${{ matrix.arch }}"-' . $node['tag'] . ' >> ' . $testDockerfile,
'echo "COPY conf/ /" >> ' . $testDockerfile,
];
$script[] = 'bundle install';
Expand All @@ -119,9 +183,9 @@ private function structuredTests(array $node): array
if (file_exists(__DIR__ . '/../../tests/structure-test/' . $node['image'] . '/test.yaml')) {
$script[] = 'cd tests/structure-test';
if (file_exists(__DIR__ . '/../../tests/structure-test/' . $node['image'] . '/' . $node['tag'] . '/test.yaml')) {
$script[] = '/usr/local/bin/container-structure-test test --image ' . $node['name'] . ' --config ' . $node['image'] . '/test.yaml --config ' . $node['image'] . '/' . $node['tag'] . '/test.yaml';
$script[] = '/usr/local/bin/container-structure-test test --image ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-${{ matrix.arch }}-' . $node['tag'] . ' --config ' . $node['image'] . '/test.yaml --config ' . $node['image'] . '/' . $node['tag'] . '/test.yaml';
} else {
$script[] = '/usr/local/bin/container-structure-test test --image ' . $node['name'] . ' --config ' . $node['image'] . '/test.yaml';
$script[] = '/usr/local/bin/container-structure-test test --image ghcr.io/webdevops/' . $node['image'] . ':sha-${{ github.sha }}-${{ matrix.arch }}-' . $node['tag'] . ' --config ' . $node['image'] . '/test.yaml';
}
}
return $script;
Expand All @@ -133,7 +197,7 @@ public function getValidationConfig(): array
'name' => 'Validate Automation',
'runs-on' => 'ubuntu-latest',
'steps' => [
['uses' => 'actions/checkout@v4'],
['uses' => 'actions/checkout@v6'],
[
'name' => 'Validate that template/* are used to generate Dockerfiles',
'run' => implode("\n", [
Expand Down
11 changes: 7 additions & 4 deletions docker/dockerfile-build-env/latest/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#+++++++++++++++++++++++++++++++++++++++

FROM webdevops/base-app:ubuntu-22.04
ARG TARGETARCH

RUN apt-install \
build-essential \
Expand All @@ -19,18 +20,20 @@ RUN apt-install \
ruby \
ruby-dev \
ruby-bundler \
libyaml-dev \
&& curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py \
&& python2 get-pip.py \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \
&& add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& add-apt-repository "deb [arch=$TARGETARCH] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& apt-install docker-ce \
&& usermod -aG docker application \
&& curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 \
&& chmod +x container-structure-test-linux-amd64 \
&& mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test \
&& curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-$TARGETARCH \
&& chmod +x container-structure-test-linux-$TARGETARCH \
&& mv container-structure-test-linux-$TARGETARCH /usr/local/bin/container-structure-test \
&& pip install --upgrade pip \
&& hash -r pip \
&& pip install --upgrade setuptools \
&& pip install Cython==0.29.21 wheel \
&& git clone --depth 1 https://github.com/webdevops/Dockerfile.git /tmp/Dockerfile \
&& gem install bundler -v 2.1.4 --no-document \
&& cd /tmp/Dockerfile/tests/serverspec \
Expand Down
11 changes: 7 additions & 4 deletions docker/dockerfile-build-env/latest/Dockerfile.jinja2
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{{ docker.from("base-app","ubuntu-22.04") }}
ARG TARGETARCH

RUN apt-install \
build-essential \
Expand All @@ -14,18 +15,20 @@ RUN apt-install \
ruby \
ruby-dev \
ruby-bundler \
libyaml-dev \
&& curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output get-pip.py \
&& python2 get-pip.py \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - \
&& add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& add-apt-repository "deb [arch=$TARGETARCH] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& apt-install docker-ce \
&& usermod -aG docker application \
&& curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 \
&& chmod +x container-structure-test-linux-amd64 \
&& mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test \
&& curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-$TARGETARCH \
&& chmod +x container-structure-test-linux-$TARGETARCH \
&& mv container-structure-test-linux-$TARGETARCH /usr/local/bin/container-structure-test \
&& pip install --upgrade pip \
&& hash -r pip \
&& pip install --upgrade setuptools \
&& pip install Cython==0.29.21 wheel \
&& git clone --depth 1 https://github.com/webdevops/Dockerfile.git /tmp/Dockerfile \
&& gem install bundler -v 2.1.4 --no-document \
&& cd /tmp/Dockerfile/tests/serverspec \
Expand Down
Loading
Loading