Add stable regression test

This tests stable maintenance branches, to ensure that build directories
created with older versions of Meson continue to work without wiping,
after updating to a bugfix release.
diff --git a/.github/workflows/stable_builddir.yml b/.github/workflows/stable_builddir.yml
new file mode 100644
index 0000000..5da321d
--- /dev/null
+++ b/.github/workflows/stable_builddir.yml
@@ -0,0 +1,35 @@
+name: stable build directories
+
+on:
+  push:
+    branches:
+      - '[0-9]+.[0-9]+'
+
+permissions:
+  contents: read
+
+jobs:
+  regression:
+    runs-on: ubuntu-latest
+    env:
+      TESTDIR: "manual tests/13 builddir upgrade"
+    steps:
+      - uses: actions/checkout@v3
+      - name: install ninja
+        run: sudo apt-get -y install build-essential ninja-build
+      - name: Fetch tags and unshallow
+        run: git fetch --unshallow --tags
+      - name: Checkout latest release on this branch
+        run: |
+          cp -r "$TESTDIR" "$TESTDIR"-temp
+          git checkout "$(git describe --abbrev=0)"
+      - name: Configure with most recent tag
+        run: ./meson.py setup "$TESTDIR"-temp builddir
+      - name: Return to testing commit
+        run: git checkout $GITHUB_SHA
+      - name: check that everything still works
+        run: |
+          ./meson.py compile -C builddir
+          ninja -C builddir test
+          DESTDIR=pkg ninja -C builddir install
+          ./meson.py introspect builddir --all
diff --git a/manual tests/13 builddir upgrade/data/foo.dat b/manual tests/13 builddir upgrade/data/foo.dat
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manual tests/13 builddir upgrade/data/foo.dat
diff --git a/manual tests/13 builddir upgrade/foo.1 b/manual tests/13 builddir upgrade/foo.1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/manual tests/13 builddir upgrade/foo.1
diff --git a/manual tests/13 builddir upgrade/foo.c b/manual tests/13 builddir upgrade/foo.c
new file mode 100644
index 0000000..f8edd23
--- /dev/null
+++ b/manual tests/13 builddir upgrade/foo.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+    printf("Hello world!\n");
+    return 0;
+}
diff --git a/manual tests/13 builddir upgrade/lib.c b/manual tests/13 builddir upgrade/lib.c
new file mode 100644
index 0000000..2ea9c7d
--- /dev/null
+++ b/manual tests/13 builddir upgrade/lib.c
@@ -0,0 +1,9 @@
+#if defined _WIN32 || defined __CYGWIN__
+#define DLL_PUBLIC __declspec(dllexport)
+#else
+#define DLL_PUBLIC
+#endif
+
+int DLL_PUBLIC foo(void) {
+  return 0;
+}
diff --git a/manual tests/13 builddir upgrade/meson.build b/manual tests/13 builddir upgrade/meson.build
new file mode 100644
index 0000000..34ae39c
--- /dev/null
+++ b/manual tests/13 builddir upgrade/meson.build
@@ -0,0 +1,21 @@
+project('check old builddirs in a stable release', 'c')
+
+lib = both_libraries('lib', 'lib.c')
+exe = executable('foo', 'foo.c', link_with: lib, install: true)
+test('exe', exe)
+
+install_data('data/foo.dat', install_dir: get_option('datadir') / 'foo')
+install_man('foo.1')
+
+py = import('python').find_installation()
+py.install_sources('mod.py', subdir: 'foo')
+install_subdir('data', install_dir: py.get_install_dir())
+
+custom_target(
+  input: 'mod.py',
+  output: 'hello.dat',
+  command: [py, '@INPUT@'],
+  capture: true,
+  install: true,
+  install_dir: get_option('localstatedir') / 'foo',
+)
diff --git a/manual tests/13 builddir upgrade/mod.py b/manual tests/13 builddir upgrade/mod.py
new file mode 100644
index 0000000..60f08aa
--- /dev/null
+++ b/manual tests/13 builddir upgrade/mod.py
@@ -0,0 +1 @@
+print('Hello world!')