Skip to content

Mergin Maps delivery #1714

Mergin Maps delivery

Mergin Maps delivery #1714

Workflow file for this run

name: Mergin Maps delivery
on:
workflow_run:
types:
- "completed"
workflows:
- "win64 Build"
- "macOS Build"
- "linux Build"
- "Android Build"
- "iOS Build"
permissions:
actions: read
pull-requests: write
jobs:
comment_on_pr:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- name: Check all builds completed and find artifacts
id: artifact_finder
uses: actions/github-script@v8
with:
script: |
const buildWorkflowNames = ['macOS Build', 'linux Build', 'win64 Build', 'Android Build', 'iOS Build'];
const headSha = context.payload.workflow_run.head_sha;
// 1. Fetch all runs for this commit
const runsResponse = await github.rest.actions.listWorkflowRunsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
head_sha: headSha,
per_page: 50
});
const allRuns = runsResponse.data.workflow_runs;
// 2. Check that every required workflow has a completed run on this commit.
// If any is still in progress (or missing), bail out — another workflow_run
// event will re-trigger this job once that workflow finishes.
for (const name of buildWorkflowNames) {
const run = allRuns.find(r => r.name === name);
if (!run || run.status !== 'completed') {
console.log(`Workflow "${name}" is not yet completed. Skipping comment until all builds are done.`);
core.setOutput('pr_number', '');
return;
}
}
console.log('All required workflows are completed. Building comment...');
// 3. Helper: find the check run created by the Android job for this commit
// and read the Play Store link from its output.summary field.
async function fetchPlayStoreLink(headSha) {
try {
const checkRuns = await github.rest.checks.listForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: headSha,
});
// There may be multiple check runs with the same name (e.g. matrix builds);
// find the one whose summary contains a URL (written by the deploy step).
let linkDict = [];
for (const run of checkRuns.data.check_runs) {
if (run.name.includes("android")) {
const buildType = run.output?.title.split(" ")[1];
const summary = run.output?.summary ?? '';
const match = summary.match(/https:\/\/[^\s)>\]"]+/);
if (match) {
linkDict.push({
type: buildType,
link: summary
});
}
}
}
if (linkDict.length > 0) return linkDict;
console.log('No Play Store link found in Android check run output.');
return [];
} catch (e) {
console.log(`Could not fetch Play Store link from check run: ${e.message}`);
return [];
}
}
// 4. Build the comment
let commentBody = '## 📦 Build Artifacts Ready\n\n|OS|Status|Build|Info|Workflow run|\n|-----|-----|-----|-----|-----|\n';
let artifactsFound = false;
for (const workflowName of buildWorkflowNames) {
const latestRun = allRuns.find(run => run.name === workflowName);
if (!latestRun || latestRun.conclusion !== 'success') {
commentBody += `|**${workflowName}**| ❌ | Build failed or not found. | | ${latestRun ? `[#${latestRun.run_number}](${latestRun.html_url})` : ''} |\n`;
continue;
}
if (workflowName !== 'iOS Build') {
const artifactsResponse = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: latestRun.id,
});
let artifacts = [];
let playStoreLinksDict = [];
if (workflowName === 'Android Build') {
artifacts = artifactsResponse.data.artifacts.filter(artifact => artifact.name.includes(' APK '));
// also let's fetch links to play store
playStoreLinksDict = await fetchPlayStoreLink(headSha);
} else {
artifacts = artifactsResponse.data.artifacts;
}
if (artifacts.length > 0) {
for (const artifact of artifacts) {
commentBody += `|**${workflowName}**| 📬 | [**${artifact.name}**](${artifact.archive_download_url}) | Expires: ${new Date(artifact.expires_at).toLocaleDateString('en-GB')} | [#${latestRun.run_number}](${latestRun.html_url}) |\n`;
artifactsFound = true;
if (workflowName === 'Android Build' && playStoreLinksDict.length > 0) {
const playStoreArtifact = playStoreLinksDict.find(playStoreLink => artifact.name.includes(playStoreLink.type));
commentBody += `|| 📬 | [**${artifact.name}**](${playStoreArtifact.link}) | Google Play Store | [#${latestRun.run_number}](${latestRun.html_url}) |\n`;
}
}
} else {
commentBody += `|**${workflowName}**| 📭 | | | [#${latestRun.run_number}](${latestRun.html_url}) |\n`;
}
} else {
const currentYear = String(new Date().getFullYear()).slice(-2);
const currentMonth = (new Date().getMonth() + 1).toLocaleString('en-US', { minimumIntegerDigits: 2, useGrouping: false });
const buildId = `${latestRun.run_number}1${latestRun.run_attempt}`;
commentBody += `|**${workflowName}**| 📬 | | Build number: ${currentYear}.${currentMonth}.${buildId} | [#${latestRun.run_number}](${latestRun.html_url}) |\n`;
artifactsFound = true;
}
}
core.setOutput('comment_body', artifactsFound ? commentBody : 'No artifacts found for this PR commit.');
// 5. Resolve PR number
const prsResponse = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
head: `${context.repo.owner}:${context.payload.workflow_run.head_branch}`,
per_page: 5
});
const pullRequest = prsResponse.data.find(pr => pr.head.sha === headSha);
if (!pullRequest) {
console.log(`No open Pull Request found for commit SHA: ${headSha}`);
core.setOutput('pr_number', '');
} else {
core.setOutput('pr_number', pullRequest.number);
}
- name: Update Comment
if: steps.artifact_finder.outputs.pr_number != ''
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ steps.artifact_finder.outputs.pr_number }}
body: ${{ steps.artifact_finder.outputs.comment_body }}