From 1f8c5d1c8f3c04646ce477338f0423563d0cf857 Mon Sep 17 00:00:00 2001
From: Martin Weinelt <martin@darmstadt.freifunk.net>
Date: Tue, 10 Aug 2021 16:10:10 +0200
Subject: [PATCH] actions: build targets conditionally

---
 .github/filters.yml                        | 180 +++++++++++++++++++++
 .github/workflows/build-gluon.yml          |  40 ++---
 Makefile                                   |   2 +
 contrib/actions/generate-actions.py        |  67 --------
 contrib/actions/generate-target-filters.py |  38 +++++
 scripts/update-ci.sh                       |   3 +
 6 files changed, 245 insertions(+), 85 deletions(-)
 create mode 100644 .github/filters.yml
 delete mode 100755 contrib/actions/generate-actions.py
 create mode 100755 contrib/actions/generate-target-filters.py
 create mode 100755 scripts/update-ci.sh

diff --git a/.github/filters.yml b/.github/filters.yml
new file mode 100644
index 00000000..bde1a69d
--- /dev/null
+++ b/.github/filters.yml
@@ -0,0 +1,180 @@
+{
+  "ath79-generic": [
+    "targets/ath79-generic",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ath79-nand": [
+    "targets/ath79-nand",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "bcm27xx-bcm2708": [
+    "targets/bcm27xx-bcm2708",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "bcm27xx-bcm2709": [
+    "targets/bcm27xx-bcm2709",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ipq40xx-generic": [
+    "targets/ipq40xx-generic",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ipq806x-generic": [
+    "targets/ipq806x-generic",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "lantiq-xrx200": [
+    "targets/lantiq-xrx200",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "lantiq-xway": [
+    "targets/lantiq-xway",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "mediatek-mt7622": [
+    "targets/mediatek-mt7622",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "mpc85xx-p1010": [
+    "targets/mpc85xx-p1010",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "mpc85xx-p1020": [
+    "targets/mpc85xx-p1020",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ramips-mt7620": [
+    "targets/ramips-mt7620",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ramips-mt7621": [
+    "targets/ramips-mt7621",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "ramips-mt76x8": [
+    "targets/ramips-mt76x8",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "rockchip-armv8": [
+    "targets/rockchip-armv8",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "sunxi-cortexa7": [
+    "targets/sunxi-cortexa7",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "x86-generic": [
+    "targets/x86-generic",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "x86-geode": [
+    "targets/x86-geode",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "x86-legacy": [
+    "targets/x86-legacy",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "x86-64": [
+    "targets/x86-64",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk",
+    "contrib/ci/minimal-site/**",
+    "package/**"
+  ],
+  "bcm27xx-bcm2710": [
+    "targets/bcm27xx-bcm2710",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ],
+  "mvebu-cortexa9": [
+    "targets/mvebu-cortexa9",
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk"
+  ]
+}
diff --git a/.github/workflows/build-gluon.yml b/.github/workflows/build-gluon.yml
index 944870aa..897e7744 100644
--- a/.github/workflows/build-gluon.yml
+++ b/.github/workflows/build-gluon.yml
@@ -9,43 +9,47 @@ on:
       - master
       - next*
       - v20*
-    paths:
-      - "modules"
-      - "Makefile"
-      - "scripts/**"
-      - "package/**"
-      - "patches/**"
-      - "targets/**"
-      - ".github/workflows/build-gluon.yml"
   pull_request:
     types: [opened, synchronize, reopened]
-    paths:
-      - "modules"
-      - "Makefile"
-      - "scripts/**"
-      - "package/**"
-      - "patches/**"
-      - "targets/**"
-      - ".github/workflows/build-gluon.yml"
+
 jobs:
+  changed:
+    runs-on: ubuntu-latest
+    outputs:
+      targets: ${{ steps.filter.outputs.changes }}
+    steps:
+      - uses: actions/checkout@v2
+
+      # Filter targets based on changed files
+      - uses: dorny/paths-filter@v2
+        id: filter
+        with:
+          filters: .github/filters.yml
+
   build_firmware:
+    needs: changed
     strategy:
       fail-fast: false
       matrix:
-        target: [ath79-generic, ath79-nand, bcm27xx-bcm2708, bcm27xx-bcm2709, ipq40xx-generic, ipq806x-generic, lantiq-xrx200, lantiq-xway, mediatek-mt7622, mpc85xx-p1010, mpc85xx-p1020, ramips-mt7620, ramips-mt7621, ramips-mt76x8, rockchip-armv8, sunxi-cortexa7, x86-generic, x86-geode, x86-legacy, x86-64, bcm27xx-bcm2710, mvebu-cortexa9]
+        # Read back changd targets to create build matrix
+        target: ${{ fromJSON(needs.changed.outputs.targets) }}
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v1
+      - uses: actions/checkout@v2
+
       - name: Install Dependencies
         run: sudo contrib/actions/install-dependencies.sh
+
       - name: Build
         run: contrib/actions/run-build.sh ${{ matrix.target }}
+
       - name: Archive build logs
         if: ${{ !cancelled() }}
         uses: actions/upload-artifact@v1
         with:
           name: ${{ matrix.target }}_logs
           path: openwrt/logs
+
       - name: Archive build output
         uses: actions/upload-artifact@v1
         with:
diff --git a/Makefile b/Makefile
index 4ff9f0c6..48069191 100644
--- a/Makefile
+++ b/Makefile
@@ -100,6 +100,8 @@ refresh-patches: FORCE
 update-feeds: FORCE
 	@$(GLUON_ENV) scripts/feeds.sh
 
+update-ci: FORCE
+	@scripts/update-ci.sh
 
 GLUON_TARGETS :=
 
diff --git a/contrib/actions/generate-actions.py b/contrib/actions/generate-actions.py
deleted file mode 100755
index 3b3ea8f2..00000000
--- a/contrib/actions/generate-actions.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python3
-
-import sys
-
-ACTIONS_HEAD = """
-# Update this file after adding/removing/renaming a target by running
-# `make list-targets BROKEN=1 | ./contrib/actions/generate-actions.py > ./.github/workflows/build-gluon.yml`
-
-name: Build Gluon
-on:
-  push:
-    branches:
-      - master
-      - next*
-      - v20*
-    paths:
-      - "modules"
-      - "Makefile"
-      - "scripts/**"
-      - "package/**"
-      - "patches/**"
-      - "targets/**"
-      - ".github/workflows/build-gluon.yml"
-  pull_request:
-    types: [opened, synchronize, reopened]
-    paths:
-      - "modules"
-      - "Makefile"
-      - "scripts/**"
-      - "package/**"
-      - "patches/**"
-      - "targets/**"
-      - ".github/workflows/build-gluon.yml"
-jobs:
-  build_firmware:
-    strategy:
-      fail-fast: false
-      matrix:
-        target: [{matrix}]
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v1
-      - name: Install Dependencies
-        run: sudo contrib/actions/install-dependencies.sh
-      - name: Build
-        run: contrib/actions/run-build.sh ${{{{ matrix.target }}}}
-      - name: Archive build logs
-        if: ${{{{ !cancelled() }}}}
-        uses: actions/upload-artifact@v1
-        with:
-          name: ${{{{ matrix.target }}}}_logs
-          path: openwrt/logs
-      - name: Archive build output
-        uses: actions/upload-artifact@v1
-        with:
-          name: ${{{{ matrix.target }}}}_output
-          path: output
-"""
-
-targets = []
-
-for target in sys.stdin:
-    targets.append(target.strip())
-
-output = ACTIONS_HEAD.format(matrix=", ".join(targets))
-
-print(output)
diff --git a/contrib/actions/generate-target-filters.py b/contrib/actions/generate-target-filters.py
new file mode 100755
index 00000000..084ce104
--- /dev/null
+++ b/contrib/actions/generate-target-filters.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+
+# Update target filters using
+#   make update-ci
+
+import sys
+import json
+
+# these changes trigger rebuilds on all targets
+common = [
+    "modules",
+    "Makefile",
+    "patches/**",
+    "targets/generic",
+    "targets/targets.mk",
+]
+
+# these changes are only built on x86-64
+extra = [
+    "contrib/ci/minimal-site/**",
+    "package/**"
+]
+
+_filter = dict()
+
+# construct filters map from stdin
+for target in sys.stdin:
+    target = target.strip()
+
+    _filter[target] = [
+        f"targets/{target}"
+    ] + common
+
+    if target == "x86-64":
+        _filter[target].extend(extra)
+
+# print filters to stdout in json format, because json is stdlib and yaml compatible.
+print(json.dumps(_filter, indent=2))
diff --git a/scripts/update-ci.sh b/scripts/update-ci.sh
new file mode 100755
index 00000000..cebc92dc
--- /dev/null
+++ b/scripts/update-ci.sh
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+
+make --no-print-directory list-targets BROKEN=1 | ./contrib/actions/generate-target-filters.py > .github/filters.yml
-- 
GitLab