Skip to content
Merged
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
9 changes: 9 additions & 0 deletions src/commands/gxgames/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ import { GG_API } from "../config";

export { LinkStorage, type GxGamesLink } from "./storage";

export const apiUserErrorMessage = (
errors: readonly { description: string }[],
): string =>
errors
.map(
(e) => e.description.slice(0, 1).toUpperCase() + e.description.slice(1),
)
.join(".\n");

export function getApiClient(
ctx: Context,
auth: {
Expand Down
8 changes: 4 additions & 4 deletions src/commands/gxgames/commands/link-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { KnownError } from "~/error";
import type { ProjectPath } from "~/project";

import { createAuthManager } from "../auth";
import { getApiClient } from "../api";
import { apiUserErrorMessage, getApiClient } from "../api";
import { LinkStorage } from "../api";

export default async function (
Expand All @@ -38,7 +38,7 @@ export default async function (
if (!studioId) {
const studiosRes = await api.getUserStudios({ pageSize: 999 });
if (!studiosRes.success) {
throw new KnownError(studiosRes.errors);
throw new KnownError(apiUserErrorMessage(studiosRes.errors));
}

const selected = await p.select({
Expand All @@ -61,7 +61,7 @@ export default async function (
gameEngine: ["game-maker"],
});
if (!gamesRes.success) {
throw new KnownError(gamesRes.errors);
throw new KnownError(apiUserErrorMessage(gamesRes.errors));
}

const selected = await p.select({
Expand Down Expand Up @@ -90,7 +90,7 @@ export default async function (
gameEngine: "game-maker",
});
if (!res.success) {
throw new KnownError(res.errors);
throw new KnownError(apiUserErrorMessage(res.errors));
}
gameId = res.data.gameId;
createLog.success(`Game created: ${gameId}`);
Expand Down
10 changes: 5 additions & 5 deletions src/commands/gxgames/commands/meta-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import type { Context } from "~/context";
import { KnownError } from "~/error";
import type { ProjectPath } from "~/project";

import { LinkStorage } from "../api";
import { apiUserErrorMessage, LinkStorage } from "../api";
import { createAuthManager } from "../auth";
import { getApiClient } from "../api";
import type {
Expand Down Expand Up @@ -47,7 +47,7 @@ export default async function (

const gameRes = await api.getGameDetails(link.gameId);
if (!gameRes.success) {
throw new KnownError(gameRes.errors);
throw new KnownError(apiUserErrorMessage(gameRes.errors));
}
const game = gameRes.data;

Expand Down Expand Up @@ -79,7 +79,7 @@ export default async function (
updateLog.success("Metadata unchanged");
} else {
updateLog.error("Failed");
throw new KnownError(updateRes.errors);
throw new KnownError(apiUserErrorMessage(updateRes.errors));
}
} else {
updateLog.success("Metadata updated");
Expand All @@ -97,7 +97,7 @@ export default async function (
);
if (!coverRes.success) {
coverLog.error("Failed");
throw new KnownError(coverRes.errors);
throw new KnownError(apiUserErrorMessage(coverRes.errors));
}
coverLog.success("Cover uploaded");
}
Expand All @@ -112,7 +112,7 @@ export default async function (
});
if (!graphicRes.success) {
graphicLog.error("Failed");
throw new KnownError(graphicRes.errors);
throw new KnownError(apiUserErrorMessage(graphicRes.errors));
}
graphicLog.success("Graphic uploaded");
}
Expand Down
4 changes: 2 additions & 2 deletions src/commands/gxgames/commands/publish-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import chalk from "chalk";
import { KnownError } from "~/error";
import type { ProjectPath } from "~/project";

import { LinkStorage } from "../api";
import { apiUserErrorMessage, LinkStorage } from "../api";
import { createAuthManager } from "../auth";
import { getApiClient } from "../api";

Expand All @@ -44,7 +44,7 @@ export default async function (
),
);
}
throw new KnownError(res.errors);
throw new KnownError(apiUserErrorMessage(res.errors));
}

publishLog.success("Game published!");
Expand Down
6 changes: 3 additions & 3 deletions src/commands/gxgames/commands/upload-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import type { Context } from "~/context";
import * as p from "@clack/prompts";
import chalk from "chalk";
import { getApiClient } from "../api";
import { apiUserErrorMessage, getApiClient } from "../api";
import { createAuthManager } from "../auth";
import { KnownError } from "~/error";
import type { ProjectPath } from "~/project";
Expand All @@ -40,7 +40,7 @@ export default async function (
gameEngine: ["game-maker"],
});
if (!gamesRes.success) {
throw new KnownError(gamesRes.errors);
throw new KnownError(apiUserErrorMessage(gamesRes.errors));
}

const previousVersion = gamesRes.data.games.find(
Expand Down Expand Up @@ -70,7 +70,7 @@ export default async function (
{ file: new File([fileBuffer], this.path.basename(flags.file)) },
);
if (!res.success) {
throw new KnownError(res.errors);
throw new KnownError(apiUserErrorMessage(res.errors));
}
uploadLog.success("Bundle uploaded");

Expand Down
5 changes: 1 addition & 4 deletions src/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
*/
export class KnownError extends Error {
constructor(cause: unknown) {
const message =
cause instanceof Error
? cause.message
: JSON.stringify(cause, undefined, 2);
const message = cause instanceof Error ? cause.message : String(cause);
super(message, cause instanceof Error ? { cause } : undefined);
this.name = "KnownError";
}
Expand Down
9 changes: 9 additions & 0 deletions test-game/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# Ignore .yy files for language statistics
*.yy linguist-generated=true

# force LF for metadata files for merge simplicity
*.gml text eol=lf
*.yy text eol=lf
*.yyp text eol=lf
*.json text eol=lf
52 changes: 52 additions & 0 deletions test-game/.github/workflows/compile.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Compile

# This job triggers when opening/updating a pull request or merging to the main branch
on:
pull_request:
types: [opened, synchronize, reopened]
push:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
# You can pin a particular version by replacing latest. E.g., @gamemaker/gm-cli@1.0.2
GM_COMMAND: "@gamemaker/gm-cli@latest"

jobs:
compile:
runs-on: ubuntu-latest

steps:
# Check out the git branch to build against
- name: Checkout
uses: actions/checkout@v6

# Save a cache that can be reused between runs.
# This will future runs faster, just like when you build the game locally
- name: Cache
uses: actions/cache@v5
with:
path: .gmcache
key: ${{ runner.os }}-gmcache

# ffmpeg is needed for linux: https://github.com/YoYoGames/GameMaker-Bugs/issues/4977
- name: Set up ffmpeg
if: ${{ runner.os == 'Linux' }}
uses: FedericoCarboni/setup-ffmpeg@v3
with:
ffmpeg-version: "6.1.0"

# You can create an access token at https://gamemaker.io/en/account/access-keys
# Then, in github, set a Repository Secret named GAMEMAKER_PAT with that value
# in you repository Settings/Secrets and Varibles/Actions/New repository secret
- run: npx "$GM_COMMAND" login "$GAMEMAKER_PAT"
if: ${{ env.GAMEMAKER_PAT != '' }}

# "Test compile" the game. Does not produce a bundle, but rather checks that it
# possible to compile the game
- run: npx "$GM_COMMAND" compile
env:
NO_COLOR: 1
67 changes: 67 additions & 0 deletions test-game/.github/workflows/package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Package
# This jobs start when the user trigger it manually from Github repository/Actions
on: [workflow_dispatch]

env:
GAME_NAME: "test-game"
# You can pin a particular version by replacing latest. E.g., @gamemaker/gm-cli@1.0.2
GM_COMMAND: "@gamemaker/gm-cli@latest"

jobs:
compile:
strategy:
matrix:
# Select any runner and targets you want to build with
# runner: The machine that builds your game. See https://docs.github.com/en/actions/how-tos/write-workflows/choose-where-workflows-run/choose-the-runner-for-a-job
# target: The platform the game will run on.
include:
- runner: ubuntu-latest
target: operagx
# - runner: ubuntu-latest
# target: linux
# - runner: ubuntu-latest
# target: windows
# - runner: macos-latest
# target: mac
runs-on: ${{ matrix.runner }}

steps:
# Check out the git branch to build against
- name: Checkout
uses: actions/checkout@v6

# Save a cache that can be reused between runs.
# This will future runs faster, just like when you build the game locally
- name: Cache
uses: actions/cache@v5
with:
path: .gmcache
key: ${{ runner.os }}-gmcache-${{ matrix.target }}

# ffmpeg is needed for linux: https://github.com/YoYoGames/GameMaker-Bugs/issues/4977
- name: Set up ffmpeg
if: ${{ runner.os == 'Linux' }}
uses: FedericoCarboni/setup-ffmpeg@v3
with:
ffmpeg-version: "6.1.0"

# You can create an access token at https://gamemaker.io/en/account/access-keys
# Then, in github, set a Repository Secret named GAMEMAKER_PAT with that value
# in you repository Settings/Secrets and Varibles/Actions/New repository secret
- run: npx "$GM_COMMAND" login "$GAMEMAKER_PAT"
if: ${{ env.GAMEMAKER_PAT != '' }}

# Build and package the game. Create a file called package.zip.
- run: npx "$GM_COMMAND" package --target ${{ matrix.target }} --output ./package.zip
env:
NO_COLOR: 1

# Create the final name on the format `name-target-commit.zip` For example `spacerocks-windows-5e0179f.zip`
- name: Create artifact name
run: echo "ARTIFACT_NAME=${GAME_NAME}-${{ matrix.target }}-${GITHUB_SHA::7}.zip" >> $GITHUB_ENV

# Upload the game. You can then find it in you github repo under Actions/<The workflow run>/Artifacts
- uses: actions/upload-artifact@v7
with:
name: ${{ env.ARTIFACT_NAME }}
path: ./package.zip
63 changes: 63 additions & 0 deletions test-game/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@

# Windows

# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

# Mac

## General
.DS_Store
.AppleDouble
.LSOverride

## Icon must end with two
Icon

## Thumbnails
._*

## Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

## Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# GameMaker temporary files
*.resource_order
*.old

# GMRT build directory
Build
10 changes: 10 additions & 0 deletions test-game/.mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"mcpServers": {
"gamemaker-resource-tool": {
"type": "stdio",
"command": "npx",
"args": ["@gamemaker/gm-cli@latest", "resourcetool", "mcp"],
"env": {}
}
}
}
Loading
Loading