Skip to content

Commit 2e99251

Browse files
committed
Limit rebuilds
Our build matrix will now only output images to be rebuild that had actual changes. Either because the DokuWiki branch changed, the Docker repo was updated or because the upstream PHP image changed.
1 parent 675e2c8 commit 2e99251

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

.github/matrix.php

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
/**
3+
* This script generates the matrix for the Docker image build job
4+
*
5+
* It checks if changes in the DokuWiki branch, the upstream PHP image or the docker repo have been made
6+
* since it ran last time (using the github action cache for persistence). This allows us to run this every
7+
* day to catch any updates to the upstream images, while avoiding unnecessary rebuilds.
8+
*/
9+
10+
11+
/**
12+
* Get the list of DokuWiki versions from the download server
13+
*
14+
* @return array
15+
*/
16+
function getVersions()
17+
{
18+
$data = file_get_contents('https://download.dokuwiki.org/version');
19+
return json_decode($data, true);
20+
}
21+
22+
/**
23+
* Get the last commit of a branch
24+
*
25+
* @param string $branch
26+
* @return string
27+
*/
28+
function getLastCommit($branch)
29+
{
30+
$opts = [
31+
'http' => [
32+
'method' => "GET",
33+
'header' => join("\r\n", [
34+
"Accept: application/vnd.github.v3+json",
35+
"User-Agent: PHP"
36+
])
37+
]
38+
];
39+
$context = stream_context_create($opts);
40+
41+
$data = file_get_contents('https://api.github.com/repos/dokuwiki/dokuwiki/commits/' . $branch, false, $context);
42+
$json = json_decode($data, true);
43+
return $json['sha'];
44+
}
45+
46+
/**
47+
* Get the image id of a given PHP image tag
48+
*
49+
* @param string $tag
50+
* @return string
51+
*/
52+
function getImageId($tag)
53+
{
54+
$repo = 'library/php';
55+
$data = file_get_contents('https://auth.docker.io/token?service=registry.docker.io&scope=repository:' . $repo . ':pull');
56+
$token = json_decode($data, true)['token'];
57+
58+
59+
$opts = [
60+
'http' => [
61+
'method' => "GET",
62+
'header' => join("\r\n", [
63+
"Authorization: Bearer $token",
64+
"Accept: application/vnd.docker.distribution.manifest.v2+json",
65+
])
66+
]
67+
];
68+
$context = stream_context_create($opts);
69+
70+
$data = file_get_contents('https://index.docker.io/v2/' . $repo . '/manifests/' . $tag, false, $context);
71+
$json = json_decode($data, true);
72+
return $json['config']['digest'];
73+
}
74+
75+
/**
76+
* Get the image tag used in the current Dockerfile
77+
*
78+
* @return string
79+
*/
80+
function getImageTag()
81+
{
82+
$df = file_get_contents('Dockerfile');
83+
preg_match('/FROM php:(?<tag>\S*)/', $df, $matches);
84+
return $matches['tag'];
85+
}
86+
87+
88+
$result = [];
89+
$self = $_ENV['GITHUB_SHA'] ?? 'unknown';
90+
$upstreamTag = getImageTag();
91+
$image = getImageId($upstreamTag);
92+
93+
foreach (getVersions() as $release => $info) {
94+
$branch = $release === 'oldstable' ? 'old-stable' : $release;
95+
$commit = getLastCommit($branch);
96+
$ident = join('-', [$release, $commit, $image, $self]);
97+
$cache = '.github/matrix.cache/' . $release;
98+
99+
fwrite(STDERR, "Ident: $ident\n");
100+
$last = @file_get_contents($cache);
101+
if ($last === $ident) {
102+
// this combination has been built before
103+
fwrite(STDERR, "No change. Skipping $release\n");
104+
continue;
105+
}
106+
107+
// this branch needs to be built
108+
$result[] = [
109+
'version' => $info['version'],
110+
'date' => $info['date'],
111+
'name' => $info['name'],
112+
'type' => $release,
113+
];
114+
// update the cache
115+
if (!is_dir('.github/matrix.cache')) {
116+
mkdir('.github/matrix.cache');
117+
}
118+
file_put_contents($cache, $ident);
119+
}
120+
121+
// output the result
122+
if ($result) {
123+
echo "matrix=" . json_encode(['release' => $result]);
124+
} else {
125+
echo "matrix=[]";
126+
}
127+

.github/workflows/docker.yml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,28 @@ jobs:
1111
outputs:
1212
matrix: ${{ steps.set-matrix.outputs.matrix }}
1313
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
- name: Set up PHP
17+
uses: shivammathur/setup-php@v2
18+
with:
19+
php-version: '8.2'
20+
- name: Cache Setup
21+
id: cache
22+
uses: actions/cache@v4
23+
with:
24+
path: .github/matrix.cache/
25+
key: ${{ runner.os }}-matrix-${{ hashFiles('.github/matrix.php') }}
1426
- name: Set up matrix
1527
id: set-matrix
1628
run: |
17-
echo "matrix=$(curl https://download.dokuwiki.org/version | jq -c '{release: [.[]]}')" >> $GITHUB_OUTPUT
29+
php .github/matrix.php >> $GITHUB_OUTPUT
1830
1931
build:
2032
needs: buildmatrix
2133
name: Build Docker Image for ${{ matrix.release.type }}
2234
runs-on: ubuntu-latest
35+
if: ${{ needs.buildmatrix.outputs.matrix != '[]' }}
2336
strategy:
2437
matrix: ${{fromJson(needs.buildmatrix.outputs.matrix)}}
2538
steps:

0 commit comments

Comments
 (0)