Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .circleci/test-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,15 @@ workflows:
requires:
- orb-tools/pack
filters: *filters
- <orb-name>/await-maven-central-package:
name: test-await-maven-central-package
coordinates: |
com.revenuecat.purchases:purchases:8.12.0
com.revenuecat.purchases:purchases-ui:8.12.0
timeout: "60"
requires:
- orb-tools/pack
filters: *filters
- orb-tools/publish:
orb-name: revenuecat/sdks-common-config
vcs-type: << pipeline.project.type >>
Expand All @@ -146,6 +155,7 @@ workflows:
- test-install-xcodes
- test-install-xcbeautify
- test-install-xcbeautify-from-mise-toml
- test-await-maven-central-package
context: orb-publishing
filters:
branches:
Expand Down
31 changes: 31 additions & 0 deletions src/jobs/await-maven-central-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
description: >
Waits for one or more Maven artifacts to become available on Maven Central.
Lightweight job that polls until all specified coordinates are reachable or the timeout is exceeded.
parameters:
coordinates:
type: string
description: >
Newline or space-separated Maven coordinates to wait for.
Each entry must be a full groupId:artifactId:version triple
(e.g. "com.revenuecat.purchases:purchases:8.0.0").
poll_interval:
type: string
default: "30"
description: "Seconds between availability checks"
timeout:
type: string
default: "1800"
description: "Maximum seconds to wait before failing"
docker:
- image: cimg/node:current
resource_class: small
steps:
- run:
name: Wait for Maven Central availability
environment:
COORDINATES: << parameters.coordinates >>
POLL_INTERVAL: << parameters.poll_interval >>
TIMEOUT: << parameters.timeout >>
no_output_timeout: << parameters.timeout >>s
shell: node
command: <<include(scripts/await-maven-central-package.js)>>
103 changes: 103 additions & 0 deletions src/scripts/await-maven-central-package.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const https = require("https");

const POLL_INTERVAL = parseInt(process.env.POLL_INTERVAL || "30", 10);
const TIMEOUT = parseInt(process.env.TIMEOUT || "1800", 10);
const COORDINATES = process.env.COORDINATES || "";

function buildUrl(groupId, artifactId, version) {
const groupPath = groupId.replace(/\./g, "/");
return `https://repo1.maven.org/maven2/${groupPath}/${artifactId}/${version}/${artifactId}-${version}.pom`;
}

function checkAvailable(url) {
return new Promise((resolve) => {
const req = https.request(url, { method: "HEAD" }, (res) => {
resolve(res.statusCode >= 200 && res.statusCode < 400);
});
req.on("error", () => resolve(false));
req.end();
});
}

function sleep(seconds) {
return new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}

function parseCoordinates(raw) {
const coords = [];
for (const line of raw.split(/[\n\s]+/)) {
const trimmed = line.trim();
if (!trimmed) continue;
const parts = trimmed.split(":");
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2]) {
console.error(
`Error: Invalid coordinate '${trimmed}'. Expected format groupId:artifactId:version`
);
process.exit(1);
}
coords.push({ groupId: parts[0], artifactId: parts[1], version: parts[2], raw: trimmed });
}
return coords;
}

async function main() {
if (!COORDINATES.trim()) {
console.error("Error: COORDINATES is not set or empty.");
process.exit(1);
}

let pending = parseCoordinates(COORDINATES);

if (pending.length === 0) {
console.error("Error: No valid coordinates provided.");
process.exit(1);
}

console.log(`Waiting for ${pending.length} artifact(s) to appear on Maven Central:`);
for (const coord of pending) {
console.log(` - ${coord.raw}`);
}
console.log("");

let elapsed = 0;

while (pending.length > 0) {
if (elapsed >= TIMEOUT) {
console.log("");
console.error(
`Error: Timed out after ${TIMEOUT}s. The following artifacts are still not available:`
);
for (const coord of pending) {
console.error(` - ${coord.raw}`);
}
process.exit(1);
}

const stillPending = [];

for (const coord of pending) {
const url = buildUrl(coord.groupId, coord.artifactId, coord.version);
if (await checkAvailable(url)) {
console.log(` Available: ${coord.raw}`);
} else {
stillPending.push(coord);
}
}

pending = stillPending;

if (pending.length === 0) break;

console.log(`[${elapsed}s/${TIMEOUT}s] Still waiting for ${pending.length} artifact(s)...`);
await sleep(POLL_INTERVAL);
elapsed += POLL_INTERVAL;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NABD but I guess this does not count the request time itself

}

console.log("");
console.log("All artifacts are available on Maven Central.");
}

main().then(() => process.exit(0)).catch((err) => {
console.error(err);
process.exit(1);
});