Break-out early if the image already exists (#23)

diff --git a/.github/workflows/promote.yml b/.github/workflows/promote.yml
new file mode 100644
index 0000000..36752c0
--- /dev/null
+++ b/.github/workflows/promote.yml
@@ -0,0 +1,32 @@
+name: promote
+on:
+  push:
+    branches:
+      - main
+
+jobs:
+  build-image-strategy:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3.0.2
+      - id: set-strategy
+        run: echo "::set-output name=strategy::$(./ci/build-image-strategy all)"
+    outputs:
+      strategy: ${{ steps.set-strategy.outputs.strategy }}
+
+  promote-openstack-images:
+    runs-on: ubuntu-latest
+    needs:
+      - build-image-strategy
+    strategy: ${{ fromJSON(needs.build-image-strategy.outputs.strategy) }}
+    steps:
+      - run: ./ci/openstack-image-build-env ${{ matrix.project }} ${{ matrix.release }} >> $GITHUB_ENV
+      - uses: docker/login-action@v2.0.0
+        with:
+          registry: quay.io
+          username: ${{ secrets.QUAY_USERNAME }}
+          password: ${{ secrets.QUAY_ROBOT_TOKEN }}
+      - uses: akhilerm/tag-push-action@v2.0.0
+        with:
+          src: quay.io/vexxhost/${{ matrix.project }}:${{ env.PROJECT_REF }}
+          dst: quay.io/vexxhost/${{ matrix.project }}:${{ matrix.release }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e608af3..7034c29 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -6,22 +6,21 @@
       - main
 
 jobs:
-  build-matrix:
+  build-image-strategy:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3.0.2
-      - id: set-matrix
-        run: echo "::set-output name=matrix::$(./ci/build-matrix)"
+      - id: set-strategy
+        run: echo "::set-output name=strategy::$(./ci/build-image-strategy)"
     outputs:
-      matrix: ${{ steps.set-matrix.outputs.matrix }}
+      strategy: ${{ steps.set-strategy.outputs.strategy }}
 
   build-openstack-images:
+    if: needs.build-image-strategy.outputs.strategy != '{}'
     runs-on: ubuntu-latest
     needs:
-      - build-matrix
-    strategy:
-      fail-fast: false
-      matrix: ${{ fromJSON(needs.build-matrix.outputs.matrix) }}
+      - build-image-strategy
+    strategy: ${{ fromJSON(needs.build-image-strategy.outputs.strategy) }}
     steps:
       - uses: actions/checkout@v3.0.2
       - uses: docker/setup-qemu-action@v2.0.0
@@ -50,24 +49,3 @@
             quay.io/vexxhost/${{ matrix.project }}:${{ env.PROJECT_REF }}
 
   # TODO(mnaser): Molecule
-
-  promote-openstack-images:
-    if: ${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
-    runs-on: ubuntu-latest
-    needs:
-      - build-matrix
-      - build-openstack-images
-    strategy:
-      fail-fast: false
-      matrix: ${{ fromJSON(needs.build-matrix.outputs.matrix) }}
-    steps:
-      - run: ./ci/openstack-image-build-env ${{ matrix.project }} ${{ matrix.release }} >> $GITHUB_ENV
-      - uses: docker/login-action@v2.0.0
-        with:
-          registry: quay.io
-          username: ${{ secrets.QUAY_USERNAME }}
-          password: ${{ secrets.QUAY_ROBOT_TOKEN }}
-      - uses: akhilerm/tag-push-action@v2.0.0
-        with:
-          src: quay.io/vexxhost/${{ matrix.project }}:${{ env.PROJECT_REF }}
-          dst: quay.io/vexxhost/${{ matrix.project }}:${{ matrix.release }}
diff --git a/ci/build-image-strategy b/ci/build-image-strategy
new file mode 100755
index 0000000..495bced
--- /dev/null
+++ b/ci/build-image-strategy
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+
+import glob
+import json
+import requests
+import sys
+
+MATRIX = []
+
+RELEASES = sorted([r.split("/")[-1] for r in glob.glob("images/openstack/releases/*")])
+PROJECTS = sorted([r.split("/")[-1] for r in glob.glob("images/openstack/projects/*")])
+
+DATA = {}
+
+if len(sys.argv) > 1 and sys.argv[1] == "all":
+    DATA = {
+        "fail-fast": False,
+        "matrix": {
+            "release": RELEASES,
+            "project": PROJECTS,
+        },
+    }
+else:
+    for release in RELEASES:
+        for project in PROJECTS:
+            ref = (
+                open(f"images/openstack/projects/{project}/{release}/ref", "r")
+                .read()
+                .strip()
+            )
+
+            r = requests.get(
+                f"https://quay.io/api/v1/repository/vexxhost/{project}/tag/?specificTag={ref}"
+            )
+
+            if r.json().get("tags") == []:
+                MATRIX += [
+                    {
+                        "release": release,
+                        "project": project,
+                    }
+                ]
+
+    if len(MATRIX) != 0:
+        DATA = {
+            "fail-fast": False,
+            "matrix": {
+                "include": MATRIX,
+            },
+        }
+
+json.dump(DATA, sys.stdout, separators=(",", ":"))
diff --git a/ci/build-matrix b/ci/build-matrix
deleted file mode 100755
index a2dde5e..0000000
--- a/ci/build-matrix
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env python3
-
-import glob
-import sys
-import json
-
-releases = sorted([r.split("/")[-1] for r in glob.glob("images/openstack/releases/*")])
-projects = sorted([r.split("/")[-1] for r in glob.glob("images/openstack/projects/*")])
-
-matrix = {
-    "release": releases,
-    "project": projects,
-}
-
-json.dump(
-    matrix,
-    sys.stdout,
-    separators=(",", ":"),
-)