diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1c3aa21..2bfbddd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,3 +1,5 @@ +name: Publish + on: release: types: [published] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..3afb065 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,24 @@ +name: Update + +on: workflow_dispatch + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Install dependencies + run: yarn + + - name: Create release.json + run: yarn node ./scripts/release.mjs + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/package.json b/package.json index 5d4ee41..5856a6e 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "vue-router": "^4.0.14" }, "devDependencies": { + "@actions/github": "^5.0.3", "@babel/core": "^7.17.12", "@breejs/api": "^1.0.2", "@commitlint/cli": "^17.0.3", diff --git a/scripts/release.mjs b/scripts/release.mjs new file mode 100644 index 0000000..6e8d705 --- /dev/null +++ b/scripts/release.mjs @@ -0,0 +1,117 @@ +import process from 'node:process'; +import request from 'superagent'; +import { getOctokit, context } from '@actions/github'; + +const UPDATER_TAG = 'updater'; +const UPDATER_FILE = 'release.json'; + +if (process.env.GITHUB_TOKEN === undefined) { + throw new Error('GITHUB_TOKEN not found.'); +} + +const getSignature = async (url) => { + const response = await request.get(url).type('application/octet-stream'); + + return response.text; +}; + +const github = getOctokit(process.env.GITHUB_TOKEN); +const { repos } = github.rest; +const repoMetaData = { + owner: context.repo.owner, + repo: context.repo.repo +}; + +const { data: latestRelease } = await repos.getLatestRelease(repoMetaData); + +const releaseData = { + version: latestRelease.tag_name, + notes: `https://github.com/${repoMetaData.owner}/${repoMetaData.repo}/releases/tag/${latestRelease.tag_name}`, + pub_date: new Date().toISOString(), + platforms: { + 'darwin-aarch64': { + signature: '', + url: '' + }, + 'darwin-x86_64': { + signature: '', + url: '' + }, + 'linux-x86_64': { + signature: '', + url: '' + }, + 'windows-x86_64': { + signature: '', + url: '' + } + } +}; + +const promises = latestRelease.assets.map( + async ({ name, browser_download_url }) => { + const signature = await getSignature(browser_download_url); + + if (name.endsWith('.app.tar.gz')) { + releaseData.platforms['darwin-aarch64'].url = browser_download_url; + releaseData.platforms['darwin-x86_64'].url = browser_download_url; + } + + if (name.endsWith('.app.tar.gz.sig')) { + releaseData.platforms['darwin-aarch64'].signature = signature; + releaseData.platforms['darwin-x86_64'].signature = signature; + } + + if (name.endsWith('.AppImage.tar.gz')) { + releaseData.platforms['linux-x86_64'].url = browser_download_url; + } + + if (name.endsWith('.AppImage.tar.gz.sig')) { + releaseData.platforms['linux-x86_64'].signature = signature; + } + + if (name.endsWith('.msi.zip')) { + releaseData.platforms['windows-x86_64'].url = browser_download_url; + } + + if (name.endsWith('.msi.zip.sig')) { + releaseData.platforms['windows-x86_64'].signature = signature; + } + } +); + +await Promise.allSettled(promises); + +if (!releaseData.platforms['darwin-aarch64'].url) { + throw new Error('Failed to get release for MacOS'); +} + +if (!releaseData.platforms['linux-x86_64'].url) { + throw new Error('Failed to get release for Linux'); +} + +if (!releaseData.platforms['windows-x86_64'].url) { + throw new Error('Failed to get release for Windows'); +} + +const { data: updater } = await repos.getReleaseByTag({ + ...repoMetaData, + tag: UPDATER_TAG +}); + +const prevReleaseAsset = updater.assets.find( + (asset) => asset.name === UPDATER_FILE +); +if (prevReleaseAsset) { + await repos.deleteReleaseAsset({ + ...repoMetaData, + asset_id: prevReleaseAsset.id + }); +} + +await repos.uploadReleaseAsset({ + ...repoMetaData, + release_id: updater.id, + name: UPDATER_FILE, + data: JSON.stringify(releaseData) +}); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index ef88700..4a78312 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -44,7 +44,9 @@ } }, "updater": { - "active": false + "active": true, + "endpoints": ["https://github.com/breejs/bree-desktop/releases/download/updater/release.json"], + "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IERFMkYwMUE2REE5MjhCOTgKUldTWWk1TGFwZ0V2M2lVekc1Y0drOUJhdkdwbnJ6WjIvR0NJaXNpeHhwRG9oczNMbW0rMGY3TkIK" }, "allowlist": { "shell": { @@ -65,4 +67,4 @@ "csp": null } } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index cf2482b..e981a59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,23 @@ # yarn lockfile v1 +"@actions/github@^5.0.3": + version "5.0.3" + resolved "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz#b305765d6173962d113451ea324ff675aa674f35" + integrity sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A== + dependencies: + "@actions/http-client" "^2.0.1" + "@octokit/core" "^3.6.0" + "@octokit/plugin-paginate-rest" "^2.17.0" + "@octokit/plugin-rest-endpoint-methods" "^5.13.0" + +"@actions/http-client@^2.0.1": + version "2.0.1" + resolved "https://registry.npmjs.org/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" + integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== + dependencies: + tunnel "^0.0.6" + "@ampproject/remapping@^2.1.0": version "2.2.0" resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" @@ -1782,6 +1799,92 @@ resolved "https://registry.npmjs.org/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz#77ecd0a4fcb772ba6fe927e2e2e155fbec2e6b1a" integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA== +"@octokit/auth-token@^2.4.4": + version "2.5.0" + resolved "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz#27c37ea26c205f28443402477ffd261311f21e36" + integrity sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g== + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/core@^3.6.0": + version "3.6.0" + resolved "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz#3376cb9f3008d9b3d110370d90e0a1fcd5fe6085" + integrity sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q== + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.6.3" + "@octokit/request-error" "^2.0.5" + "@octokit/types" "^6.0.3" + before-after-hook "^2.2.0" + universal-user-agent "^6.0.0" + +"@octokit/endpoint@^6.0.1": + version "6.0.12" + resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz#3b4d47a4b0e79b1027fb8d75d4221928b2d05658" + integrity sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA== + dependencies: + "@octokit/types" "^6.0.3" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^4.5.8": + version "4.8.0" + resolved "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz#664d9b11c0e12112cbf78e10f49a05959aa22cc3" + integrity sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg== + dependencies: + "@octokit/request" "^5.6.0" + "@octokit/types" "^6.0.3" + universal-user-agent "^6.0.0" + +"@octokit/openapi-types@^12.10.0": + version "12.10.1" + resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.1.tgz#57b5cc6c7b4e55d8642c93d06401fb1af4839899" + integrity sha512-P+SukKanjFY0ZhsK6wSVnQmxTP2eVPPE8OPSNuxaMYtgVzwJZgfGdwlYjf4RlRU4vLEw4ts2fsE2icG4nZ5ddQ== + +"@octokit/plugin-paginate-rest@^2.17.0": + version "2.21.2" + resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.2.tgz#070be9bb18cb78e52b471ddc3551d28355e2d5e2" + integrity sha512-S24H0a6bBVreJtoTaRHT/gnVASbOHVTRMOVIqd9zrJBP3JozsxJB56TDuTUmd1xLI4/rAE2HNmThvVKtIdLLEw== + dependencies: + "@octokit/types" "^6.39.0" + +"@octokit/plugin-rest-endpoint-methods@^5.13.0": + version "5.16.2" + resolved "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz#7ee8bf586df97dd6868cf68f641354e908c25342" + integrity sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw== + dependencies: + "@octokit/types" "^6.39.0" + deprecation "^2.3.1" + +"@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": + version "2.1.0" + resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" + integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== + dependencies: + "@octokit/types" "^6.0.3" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.6.0", "@octokit/request@^5.6.3": + version "5.6.3" + resolved "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz#19a022515a5bba965ac06c9d1334514eb50c48b0" + integrity sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.1.0" + "@octokit/types" "^6.16.1" + is-plain-object "^5.0.0" + node-fetch "^2.6.7" + universal-user-agent "^6.0.0" + +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.39.0": + version "6.40.0" + resolved "https://registry.npmjs.org/@octokit/types/-/types-6.40.0.tgz#f2e665196d419e19bb4265603cf904a820505d0e" + integrity sha512-MFZOU5r8SwgJWDMhrLUSvyJPtVsqA6VnbVI3TNbsmw+Jnvrktzvq2fYES/6RiJA/5Ykdwq4mJmtlYUfW7CGjmw== + dependencies: + "@octokit/openapi-types" "^12.10.0" + "@popperjs/core@^2.11.5": version "2.11.5" resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64" @@ -4361,6 +4464,11 @@ basic-auth@^2.0.0: dependencies: safe-buffer "5.1.2" +before-after-hook@^2.2.0: + version "2.2.2" + resolved "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" + integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== + better-opn@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/better-opn/-/better-opn-2.1.1.tgz#94a55b4695dc79288f31d7d0e5f658320759f7c6" @@ -6062,6 +6170,11 @@ depd@~1.1.0, depd@~1.1.2: resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== +deprecation@^2.0.0, deprecation@^2.3.1: + version "2.3.1" + resolved "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + dequal@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" @@ -9319,6 +9432,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -16167,6 +16285,11 @@ tty-browserify@0.0.0: resolved "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" integrity sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw== +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -16604,6 +16727,11 @@ unist-util-visit@^4.0.0: unist-util-is "^5.0.0" unist-util-visit-parents "^5.0.0" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + universalify@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"