-
Notifications
You must be signed in to change notification settings - Fork 7
146 lines (122 loc) · 5 KB
/
bdk-ffi-release-watch.yml
File metadata and controls
146 lines (122 loc) · 5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
name: bdk-ffi Release Watch
on:
schedule:
# Run every Monday at 09:30 UTC.
- cron: "30 9 * * 1"
workflow_dispatch:
permissions:
contents: read
issues: write
concurrency:
group: bdk-ffi-release-watch
cancel-in-progress: false
jobs:
open-update-issue:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check latest bdk-ffi release and open issue
uses: actions/github-script@v7
env:
UPSTREAM_REPO: bitcoindevkit/bdk-ffi
DEPENDENCY_FILE: native/Cargo.toml
with:
script: |
const fs = require('node:fs');
const dependencyFile = process.env.DEPENDENCY_FILE;
const upstreamRepo = process.env.UPSTREAM_REPO;
const [upstreamOwner, upstreamName] = upstreamRepo.split('/');
if (!upstreamOwner || !upstreamName) {
core.setFailed(`Invalid UPSTREAM_REPO: ${upstreamRepo}`);
return;
}
const cargoToml = fs.readFileSync(dependencyFile, 'utf8');
const pinMatch = cargoToml.match(/^\s*bdk-ffi\s*=\s*\{[^}]*\btag\s*=\s*"([^"]+)"/ms);
if (!pinMatch) {
core.setFailed(`Could not find a tag-pinned bdk-ffi dependency in ${dependencyFile}`);
return;
}
const currentTag = pinMatch[1];
function parseSemver(tag) {
const match = String(tag).trim().match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.*)?$/);
if (!match) return null;
return {
major: Number(match[1]),
minor: Number(match[2]),
patch: Number(match[3]),
prerelease: match[4] ?? null,
};
}
function compareSemver(aTag, bTag) {
const a = parseSemver(aTag);
const b = parseSemver(bTag);
if (!a || !b) return null;
for (const key of ['major', 'minor', 'patch']) {
if (a[key] > b[key]) return 1;
if (a[key] < b[key]) return -1;
}
if (a.prerelease && !b.prerelease) return -1;
if (!a.prerelease && b.prerelease) return 1;
if (!a.prerelease && !b.prerelease) return 0;
if (a.prerelease > b.prerelease) return 1;
if (a.prerelease < b.prerelease) return -1;
return 0;
}
let latestRelease;
try {
latestRelease = await github.rest.repos.getLatestRelease({
owner: upstreamOwner,
repo: upstreamName,
});
} catch (error) {
if (error.status === 404) {
core.info(`No stable GitHub release found for ${upstreamRepo}; skipping.`);
return;
}
throw error;
}
const latestTag = latestRelease.data.tag_name;
const cmp = compareSemver(latestTag, currentTag);
core.info(`Current pinned bdk-ffi tag: ${currentTag}`);
core.info(`Latest upstream bdk-ffi release: ${latestTag}`);
if (currentTag === latestTag) {
core.info('Pinned tag is already at the latest release.');
return;
}
if (cmp !== null && cmp <= 0) {
core.info('Pinned tag is not older than the latest stable release; skipping.');
return;
}
const issueTitle = `chore: update bdk-ffi to ${latestTag}`;
const searchQuery = `repo:${context.repo.owner}/${context.repo.repo} is:open "${issueTitle}"`;
const existing = await github.rest.search.issuesAndPullRequests({
q: searchQuery,
per_page: 10,
});
const existingMatch = existing.data.items.find((item) => item.title === issueTitle);
if (existingMatch) {
core.info(`Open issue or PR already exists: #${existingMatch.number}`);
return;
}
const issueBody = [
'<!-- bdk-ffi-release-watch -->',
'',
'A new upstream `bdk-ffi` release is available.',
'',
`- Current pinned tag in \`${dependencyFile}\`: \`${currentTag}\``,
`- Latest upstream release: \`${latestTag}\``,
`- Release notes: ${latestRelease.data.html_url}`,
'',
'Suggested follow-up:',
'1. Update the `bdk-ffi` tag in `native/Cargo.toml`.',
'2. Regenerate bindings with `./scripts/generate_bindings.sh`.',
'3. Run `dart test` (and CI) before merging.',
].join('\n');
const created = await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: issueTitle,
body: issueBody,
});
core.info(`Created issue #${created.data.number}: ${created.data.html_url}`);