diff --git a/.github/workflows/public-release-with-apk.yml b/.github/workflows/public-release-with-apk.yml new file mode 100644 index 0000000..929b561 --- /dev/null +++ b/.github/workflows/public-release-with-apk.yml @@ -0,0 +1,25 @@ +name: Create or Update Release + +on: + workflow_dispatch: + repository_dispatch: + types: [publish-apk] + +jobs: + create-or-update-release: + runs-on: ubuntu-latest + steps: + - name: Checkout script in repo + uses: actions/checkout@v3 + + - name: Run publish-release + uses: actions/github-script@v7 + id: gh-script + env: + RELEASE_ID: ${{ github.event.client_payload.release_id }} + with: + github-token: ${{ secrets.SOURCE_GH_TOKEN }} + result-encoding: string + script: | + const script = require('./publish-release.js') + await script({github, context, core}) diff --git a/publish-release.js b/publish-release.js new file mode 100644 index 0000000..9f04915 --- /dev/null +++ b/publish-release.js @@ -0,0 +1,144 @@ +module.exports = async ({ github, context, core }) => { + const { RELEASE_ID } = process.env; + + const publish = async () => { + console.log('Starting the publish process.'); + + // Fetch release assets from the source repo + console.log(`Fetching release assets from the source repository`); + const assets = await github.rest.repos.listReleaseAssets({ + owner: context.repo.owner, + repo: 'fedi', + release_id: RELEASE_ID, + }); + + // Find the APK file + const apkAsset = assets.data.find((asset) => asset.name.endsWith('.apk')); + if (!apkAsset) { + throw new Error('APK file not found'); + } + + console.log(`APK file found: ${apkAsset.name}`); + + // Extract version and commit hash from the APK filename + const regex = /app-production-release-(\d+\.\d+\.\d+)-([0-9a-f]+)\.apk/; + const match = apkAsset.name.match(regex); + if (!match) { + throw new Error('Invalid APK filename format'); + } + + const [fullMatch, version, commitHash] = match; + + console.log( + `Extracted version: ${version} and commit hash: ${commitHash} from APK filename` + ); + + // Prepare new release details + const newTagName = `v${version}`; + const newTitle = `Fedi Alpha v${version.split('.').slice(0, 2).join('.')} - APK Download`; + const truncatedCommitHash = commitHash.substring(0, 6); + const newFileName = `app-production-release-${version}-${truncatedCommitHash}.apk`; + const newDescription = `Download & Test Fedi Alpha

Download: [${newFileName}](https://github.com/${context.repo.owner}/fedi-alpha/releases/download/${newTagName}/${newFileName})`; + + console.log(`New release details prepared. Tag: ${newTagName}, Title: ${newTitle}`); + + // Check if a release with the same title exists in the target repo + console.log('Checking for existing release in the target repository.'); + const releases = await github.rest.repos.listReleases({ + owner: context.repo.owner, + repo: 'fedi-alpha', + }); + + // Function to upload a new APK to a release + async function uploadNewApk(releaseId) { + // Download the APK from the source repository + const apkBuffer = await github.rest.repos.getReleaseAsset({ + owner: context.repo.owner, + repo: 'fedi', + asset_id: apkAsset.id, + headers: { + Accept: 'application/octet-stream', + }, + }); + + // Upload the APK to the target repository + await github.rest.repos.uploadReleaseAsset({ + url: `https://uploads.github.com/repos/${ + context.repo.owner + }/fedi-alpha/releases/${releaseId}/assets?name=${encodeURIComponent(newFileName)}`, + headers: { + 'content-type': 'application/vnd.android.package-archive', + 'content-length': apkBuffer.data.length, + }, + data: apkBuffer.data, + name: newFileName, + }); + } + + // Function to delete old APK from a release + async function deleteOldApk(releaseId) { + const assets = await github.rest.repos.listReleaseAssets({ + owner: context.repo.owner, + repo: 'fedi-alpha', + release_id: releaseId, + }); + + const oldApkAsset = assets.data.find((asset) => asset.name.endsWith('.apk')); + if (oldApkAsset) { + await github.rest.repos.deleteReleaseAsset({ + owner: context.repo.owner, + repo: 'fedi-alpha', + asset_id: oldApkAsset.id, + }); + } + } + + const existingRelease = releases.data.find((release) => release.name === newTitle); + + if (existingRelease) { + console.log('Existing release found, updating description & download link...'); + + // Update existing release + await github.rest.repos.updateRelease({ + owner: context.repo.owner, + repo: 'fedi-alpha', + release_id: existingRelease.id, + tag_name: newTagName, + name: newTitle, + body: newDescription, + }); + + console.log('Existing release updated, proceeding to update APK.'); + + // Upload new APK and delete old APK + await deleteOldApk(existingRelease.id); + await uploadNewApk(existingRelease.id); + console.log('Existing release updated with new APK.'); + } else { + console.log('No existing release found, creating a new one.'); + + // Create a new release + const newRelease = await github.rest.repos.createRelease({ + owner: context.repo.owner, + repo: 'fedi-alpha', + tag_name: newTagName, + name: newTitle, + body: newDescription, + }); + + console.log('New release created, proceeding to upload APK.'); + + // Upload APK + await uploadNewApk(newRelease.data.id); + console.log('New release created with uploaded APK.'); + } + }; + + try { + await publish(); + console.log('Publish process completed.'); + } catch (error) { + console.error('Error encountered during the publish process:', error); + process.exit(1); + } +};