diff --git a/.github/workflows/Create_release.yml b/.github/workflows/Create_release.yml
new file mode 100644
index 000000000..bb91d9d04
--- /dev/null
+++ b/.github/workflows/Create_release.yml
@@ -0,0 +1,59 @@
+name: Create release
+
+on:
+  workflow_call:
+    inputs:
+      os:
+        required: true
+        type: string
+    secrets:
+      RELEASE_TOKEN:
+        required: true
+
+jobs:
+  release:
+    name: Release
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/download-artifact@main
+      - name: Release
+        env:
+          GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+          GH_REPO: ${{ github.repository_owner }}/xenia-canary-releases
+          notes: ${{ github.event.head_commit.message }}
+        run: |
+          rm -rf **/*.pdb
+          case ${{ inputs.os }} in
+            windows)
+              asset=xenia_canary_windows.zip
+              7z a $asset './xenia_canary_windows/*'
+              ;;
+            linux)
+              asset=xenia_canary_linux.tar.gz
+              cd xenia_canary_linux
+              chmod +x xenia_canary
+              tar -cvpf ../$asset *
+              cd -
+              ;;
+          esac
+          if [ ! -f $asset ]; then
+            echo "::error::$asset doesn't exist!"
+            exit 1
+          fi
+          if [ $(stat -c%s $asset) -lt 100000 ]; then
+            echo "::error::$asset is too small!"
+            exit 1
+          fi
+          create_or_edit_release() {
+            local tag=$1
+            local title=$2
+            if gh release view $tag; then
+              gh release edit $tag -n "$notes"
+              gh release upload $tag $asset --clobber
+            else
+              gh release create $tag $asset --target 925ed98d5dce604b651027c36fb522dc1ff0fa55 -t $title -n "$notes"
+            fi
+          }
+          tag=${GITHUB_SHA::7}
+          create_or_edit_release $tag ${tag}_$GITHUB_REF_NAME
+          create_or_edit_release $GITHUB_REF_NAME $tag
diff --git a/.github/workflows/Linux_build.yml b/.github/workflows/Linux_build.yml
index 2b2c42f34..f1acc7b89 100644
--- a/.github/workflows/Linux_build.yml
+++ b/.github/workflows/Linux_build.yml
@@ -89,9 +89,21 @@ jobs:
           cp -r build/bin/Linux/Release/xenia_canary LICENSE artifacts
       - name: Upload xenia canary artifacts
         if: steps.prepare_artifacts.outcome == 'success'
-        id: upload_artifacts
         uses: actions/upload-artifact@main
         with:
           name: xenia_canary_linux
           path: artifacts
           if-no-files-found: error
+
+  create-release:
+    name: Create release
+    needs: [lint, build]
+    if: |
+      github.repository == 'xenia-canary/xenia-canary' &&
+      github.event.action != 'pull_request' &&
+      github.ref == 'refs/heads/canary_experimental'
+    uses: ./.github/workflows/Create_release.yml
+    with:
+      os: linux
+    secrets:
+      RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
diff --git a/.github/workflows/Windows_build.yml b/.github/workflows/Windows_build.yml
index 31f02bef4..57d02110a 100644
--- a/.github/workflows/Windows_build.yml
+++ b/.github/workflows/Windows_build.yml
@@ -80,34 +80,21 @@ jobs:
           If ($LastExitCode -le 7) { echo "LastExitCode = $LastExitCode";$LastExitCode = 0 }
       - name: Upload xenia canary artifacts
         if: steps.prepare_artifacts.outcome == 'success'
-        id: upload_artifacts
         uses: actions/upload-artifact@main
         with:
           name: xenia_canary_windows
           path: artifacts\xenia_canary
           if-no-files-found: error
-      - name: Create release
-        if: |
-          github.repository == 'xenia-canary/xenia-canary' &&
-          github.event.action != 'pull_request' &&
-          github.ref == 'refs/heads/canary_experimental' &&
-          steps.upload_artifacts.outcome == 'success'
-        env:
-          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-        run: |
-          $asset="xenia_canary.zip"
-          rm -recurse -force artifacts\xenia_canary\*.pdb # Ideally this would use xr, but I can't get it to work
-          7z a $asset .\artifacts\xenia_canary\*
-          If ($(Get-Item $asset).length -le 100000) {
-            Throw "Error: Archive $asset too small!"
-          }
-          $tag=$env:GITHUB_SHA.SubString(0,7)
-          $branch=$($env:GITHUB_REF -replace 'refs/heads/')
-          $title="${tag}_$branch"
-          gh release create $tag $asset --target $env:GITHUB_SHA -t $title
-          # Remove canary_ to prevent conflicts from tag
-          $tag=$($branch -replace 'canary_')
-          gh release delete $tag -y
-          git push --delete origin $tag
-          git tag -d $tag
-          gh release create $tag $asset --target $env:GITHUB_SHA -t $branch
+
+  create-release:
+    name: Create release
+    needs: [lint, build]
+    if: |
+      github.repository == 'xenia-canary/xenia-canary' &&
+      github.event.action != 'pull_request' &&
+      github.ref == 'refs/heads/canary_experimental'
+    uses: ./.github/workflows/Create_release.yml
+    with:
+      os: windows
+    secrets:
+      RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
diff --git a/README.md b/README.md
index 346b67b7b..eb29e437c 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Discussing illegal activities will get you banned.
 
 Buildbot | Status | Releases
 -------- | ------ | --------
-Windows | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/cd506034fd8148309a45034925648499)](https://app.codacy.com/gh/xenia-canary/xenia-canary/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) | [Latest](https://github.com/xenia-canary/xenia-canary/releases/latest) ◦ [All](https://github.com/xenia-canary/xenia-canary/releases)
+Windows | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Windows_build.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/cd506034fd8148309a45034925648499)](https://app.codacy.com/gh/xenia-canary/xenia-canary/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) | [Latest](https://github.com/xenia-canary/xenia-canary-releases/releases/tag/canary_experimental_ci) ◦ [All](https://github.com/xenia-canary/xenia-canary-releases/releases) ◦ [Old](https://github.com/xenia-canary/xenia-canary/releases)
 Linux | [![CI](https://github.com/xenia-canary/xenia-canary/actions/workflows/Linux_build.yml/badge.svg?branch=canary_experimental)](https://github.com/xenia-canary/xenia-canary/actions/workflows/Linux_build.yml)
 Netplay Build | | [Latest](https://github.com/AdrianCassar/xenia-canary/releases/latest)