Skip to content
Draft
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
16 changes: 16 additions & 0 deletions action-deploy/dist/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -34950,6 +34950,10 @@ var Manifest = object({
remix_of: object({
name: string2().nonempty().regex(/[a-zA-Z0-9_-]*/),
version: ZodSemverUnbranded
}).optional(),
deployment: object({
github_owner: string2().optional(),
github_repo: string2().optional()
}).optional()
});
var import_semver = __toESM2(require_semver2(), 1);
Expand Down Expand Up @@ -48076,6 +48080,18 @@ async function run() {
core5.info(`Found manifest for app ${manifest.name}`);
core5.info(JSON.stringify(manifest, null, 2));
core5.endGroup();
if (manifest.deployment) {
const githubRepo = process.env.GITHUB_REPOSITORY || "";
const [actualOwner, actualRepo] = githubRepo.split("/");
if (manifest.deployment.github_owner && manifest.deployment.github_owner !== actualOwner) {
core5.info(`⏭️ Deployment skipped: github_owner '${manifest.deployment.github_owner}' does not match '${actualOwner}'`);
return;
}
if (manifest.deployment.github_repo && manifest.deployment.github_repo !== actualRepo) {
core5.info(`⏭️ Deployment skipped: github_repo '${manifest.deployment.github_repo}' does not match '${actualRepo}'`);
return;
}
}
const absoluteArtifactPath = resolve(workspace, artifactPath);
if (!fs13.existsSync(`${absoluteArtifactPath}/index.html`)) {
throw new Error(`Artifact folder ${artifactPath} does not contain an index.html file`);
Expand Down
17 changes: 17 additions & 0 deletions action-deploy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@ export async function run(): Promise<void> {
core.info(`Found manifest for app ${manifest.name}`);
core.info(JSON.stringify(manifest, null, 2));
core.endGroup();

// Check deployment restrictions
if (manifest.deployment) {
const githubRepo = process.env.GITHUB_REPOSITORY || "";
const [actualOwner, actualRepo] = githubRepo.split("/");

if (manifest.deployment.github_owner && manifest.deployment.github_owner !== actualOwner) {
core.info(`⏭️ Deployment skipped: github_owner '${manifest.deployment.github_owner}' does not match '${actualOwner}'`);
return;
}

if (manifest.deployment.github_repo && manifest.deployment.github_repo !== actualRepo) {
core.info(`⏭️ Deployment skipped: github_repo '${manifest.deployment.github_repo}' does not match '${actualRepo}'`);
return;
}
}

const absoluteArtifactPath = resolve(workspace, artifactPath);

// ensure artfact folder has an index.html
Expand Down
4 changes: 4 additions & 0 deletions api/src/game/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export const Manifest = z.object({
.regex(/[a-zA-Z0-9_-]*/),
version: ZodSemverUnbranded,
}).optional(),
deployment: z.object({
github_owner: z.string().optional(),
github_repo: z.string().optional(),
}).optional(),
});

export type Manifest = z.infer<typeof Manifest>;
17 changes: 17 additions & 0 deletions web/src/routes/api/v1/deployments/[deployment_name]/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,23 @@ export const POST: RequestHandler = async ({ params, request, platform }) => {
return jsonResponse({ error: 'Deployment name does not match object name in manifest' }, 400);
}

// Check deployment restrictions
if (manifest.deployment) {
const [actualOwner, actualRepo] = auth.repository.split('/');

if (manifest.deployment.github_owner && manifest.deployment.github_owner !== actualOwner) {
return jsonResponse({
error: `Deployment restricted: github_owner '${manifest.deployment.github_owner}' does not match '${actualOwner}'`
}, 403);
}

if (manifest.deployment.github_repo && manifest.deployment.github_repo !== actualRepo) {
return jsonResponse({
error: `Deployment restricted: github_repo '${manifest.deployment.github_repo}' does not match '${actualRepo}'`
}, 403);
}
}

let game = await Game.byName(deploymentName);

if (game !== undefined && !game.matchesRepo(auth.repository)) {
Expand Down
15 changes: 15 additions & 0 deletions web/static/manifest.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@
"required": ["name", "version"],
"additionalProperties": false,
"description": "Reference to the original game if this is a remix"
},
"deployment": {
"type": "object",
"properties": {
"github_owner": {
"type": "string",
"description": "GitHub owner (user or org) to restrict deployments to"
},
"github_repo": {
"type": "string",
"description": "GitHub repository name to restrict deployments to"
}
},
"additionalProperties": false,
"description": "Optional deployment restrictions. If set, deployments will be skipped when the GitHub repository doesn't match"
}
},
"required": ["name", "description", "visibility", "authors"],
Expand Down