mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-02 09:00:59 +02:00
fix: reactivate repositories with future expiration (#781)
This commit is contained in:
@@ -190,15 +190,32 @@ router.post(
|
|||||||
const newExpiration = extendExpirationDate(
|
const newExpiration = extendExpirationDate(
|
||||||
repo.model.options.expirationDate
|
repo.model.options.expirationDate
|
||||||
);
|
);
|
||||||
|
const reactivating = repo.status === RepositoryStatus.EXPIRED;
|
||||||
|
const updates: Record<string, Date> = {
|
||||||
|
"options.expirationDate": newExpiration,
|
||||||
|
};
|
||||||
repo.model.options.expirationDate = newExpiration;
|
repo.model.options.expirationDate = newExpiration;
|
||||||
|
if (reactivating) {
|
||||||
|
repo.model.anonymizeDate = new Date();
|
||||||
|
updates.anonymizeDate = repo.model.anonymizeDate;
|
||||||
|
}
|
||||||
await AnonymizedRepositoryModel.updateOne(
|
await AnonymizedRepositoryModel.updateOne(
|
||||||
{ _id: repo.model._id },
|
{ _id: repo.model._id },
|
||||||
{ $set: { "options.expirationDate": newExpiration } }
|
{ $set: updates }
|
||||||
).exec();
|
).exec();
|
||||||
|
|
||||||
// Re-anonymize so an expired repository comes back online, mirroring the
|
if (reactivating) {
|
||||||
// refresh flow.
|
// Expiration removes the cached files. Rebuild the saved commit
|
||||||
await repo.updateIfNeeded({ force: true });
|
// directly instead of asking GitHub for the latest branch head first;
|
||||||
|
// that lookup can fail after the new date has already been persisted
|
||||||
|
// and leave the repository stuck in the expired state.
|
||||||
|
await repo.updateStatus(RepositoryStatus.PREPARING);
|
||||||
|
await downloadQueue.add(
|
||||||
|
repo.repoId,
|
||||||
|
{ repoId: repo.repoId },
|
||||||
|
{ jobId: `repo-${repo.repoId}`, attempts: 3 }
|
||||||
|
);
|
||||||
|
}
|
||||||
res.json({ status: repo.status, expirationDate: newExpiration });
|
res.json({ status: repo.status, expirationDate: newExpiration });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error, res, req);
|
handleError(error, res, req);
|
||||||
@@ -424,9 +441,9 @@ function updateRepoModel(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
export function hasRepositorySourceChanged(
|
export function hasRepositorySourceChanged(
|
||||||
model: IAnonymizedRepositoryDocument,
|
model: IAnonymizedRepositoryDocument,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
repoUpdate: any
|
repoUpdate: any
|
||||||
): boolean {
|
): boolean {
|
||||||
return (
|
return (
|
||||||
@@ -436,6 +453,25 @@ export function hasRepositorySourceChanged(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An expired repository has had its cached files removed, so saving a valid
|
||||||
|
* future expiration must rebuild it even when its GitHub source is unchanged.
|
||||||
|
*/
|
||||||
|
export function shouldReactivateExpiredRepository(
|
||||||
|
model: IAnonymizedRepositoryDocument,
|
||||||
|
now = new Date()
|
||||||
|
): boolean {
|
||||||
|
if (model.status !== RepositoryStatus.EXPIRED) return false;
|
||||||
|
if (model.options.expirationMode === "never") return true;
|
||||||
|
|
||||||
|
const expirationDate = model.options.expirationDate;
|
||||||
|
return (
|
||||||
|
!!expirationDate &&
|
||||||
|
!isNaN(expirationDate.getTime()) &&
|
||||||
|
expirationDate > now
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// update a repository
|
// update a repository
|
||||||
router.post(
|
router.post(
|
||||||
"/:repoId/",
|
"/:repoId/",
|
||||||
@@ -461,6 +497,11 @@ router.post(
|
|||||||
const sourceChanged = hasRepositorySourceChanged(repo.model, repoUpdate);
|
const sourceChanged = hasRepositorySourceChanged(repo.model, repoUpdate);
|
||||||
|
|
||||||
updateRepoModel(repo.model, repoUpdate);
|
updateRepoModel(repo.model, repoUpdate);
|
||||||
|
const reactivating = shouldReactivateExpiredRepository(repo.model);
|
||||||
|
|
||||||
|
if (reactivating) {
|
||||||
|
repo.model.anonymizeDate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
if (sourceChanged) {
|
if (sourceChanged) {
|
||||||
const parsedRepository = gh(repoUpdate.fullName);
|
const parsedRepository = gh(repoUpdate.fullName);
|
||||||
@@ -553,7 +594,7 @@ router.post(
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
).exec();
|
).exec();
|
||||||
if (!sourceChanged) {
|
if (!sourceChanged && !reactivating) {
|
||||||
return res.json({ status: repo.status });
|
return res.json({ status: repo.status });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ const {
|
|||||||
} = require("../src/server/routes/conference");
|
} = require("../src/server/routes/conference");
|
||||||
const {
|
const {
|
||||||
hasRepositorySourceChanged,
|
hasRepositorySourceChanged,
|
||||||
|
shouldReactivateExpiredRepository,
|
||||||
} = require("../src/server/routes/repository-private");
|
} = require("../src/server/routes/repository-private");
|
||||||
const {
|
const {
|
||||||
processRemoveRepository,
|
processRemoveRepository,
|
||||||
@@ -79,6 +80,47 @@ describe("repository update source detection", function () {
|
|||||||
})
|
})
|
||||||
).to.equal(true);
|
).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("rebuilds an expired repository when its expiration is in the future", function () {
|
||||||
|
const now = new Date("2026-08-20T00:00:00.000Z");
|
||||||
|
expect(
|
||||||
|
shouldReactivateExpiredRepository(
|
||||||
|
{
|
||||||
|
status: "expired",
|
||||||
|
options: {
|
||||||
|
expirationMode: "redirect",
|
||||||
|
expirationDate: new Date("2027-05-01T03:57:53.395Z"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
now
|
||||||
|
)
|
||||||
|
).to.equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not rebuild an expired repository with a stale expiration", function () {
|
||||||
|
const now = new Date("2026-08-20T00:00:00.000Z");
|
||||||
|
expect(
|
||||||
|
shouldReactivateExpiredRepository(
|
||||||
|
{
|
||||||
|
status: "expired",
|
||||||
|
options: {
|
||||||
|
expirationMode: "redirect",
|
||||||
|
expirationDate: new Date("2026-01-01T00:00:00.000Z"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
now
|
||||||
|
)
|
||||||
|
).to.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rebuilds an expired repository configured never to expire", function () {
|
||||||
|
expect(
|
||||||
|
shouldReactivateExpiredRepository({
|
||||||
|
status: "expired",
|
||||||
|
options: { expirationMode: "never" },
|
||||||
|
})
|
||||||
|
).to.equal(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("removal workers", function () {
|
describe("removal workers", function () {
|
||||||
|
|||||||
Reference in New Issue
Block a user