Skip to content

Commit 3d8ea65

Browse files
jason-rlclaude
andcommitted
Add content-type input to override auto-detection
When uploading objects for file/tar agents, the content type was always inferred from the file extension. This caused .tgz files uploaded via source-type=file to be tagged as tgz, making rage extract them as archives instead of placing them as single files. The new content-type input lets callers explicitly set the object content type (e.g., binary) to control how rage handles the file. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 09ceb41 commit 3d8ea65

6 files changed

Lines changed: 50 additions & 18 deletions

File tree

action.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ inputs:
5656
description: 'Path to file or tar archive (required if source-type=tar/file)'
5757
required: false
5858

59+
content-type:
60+
description: 'Object content type override (text, binary, gzip, tar, tgz). If omitted, auto-detected from file extension and content.'
61+
required: false
62+
5963
# Common inputs
6064
setup-commands:
6165
description: 'Newline-separated setup commands to run after agent installation'

dist/index.js

Lines changed: 18 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/agent-deployer.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ async function deployTarAgent(
126126
const tarPath = resolvePath(inputs.path);
127127

128128
// Upload tar file
129-
const uploadResult = await uploadTarFile(client, tarPath, inputs.objectTtlDays, inputs.isPublic);
129+
const uploadResult = await uploadTarFile(client, tarPath, inputs.objectTtlDays, inputs.isPublic, inputs.contentType);
130130

131131
// Create agent with object source
132132
// Using client.api.post because SDK v1.0.0 types are missing 'version' field in AgentCreateParams
@@ -173,7 +173,8 @@ async function deployFileAgent(
173173
client,
174174
filePath,
175175
inputs.objectTtlDays,
176-
inputs.isPublic
176+
inputs.isPublic,
177+
inputs.contentType,
177178
);
178179

179180
// Create agent with object source

src/object-uploader.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as core from '@actions/core';
22
import * as fs from 'fs';
33
import * as path from 'path';
44
import { RunloopSDK } from '@runloop/api-client';
5+
import { ContentType } from './validators';
56

67
export interface UploadResult {
78
objectId: string;
@@ -15,16 +16,18 @@ export async function uploadTarFile(
1516
client: RunloopSDK,
1617
filePath: string,
1718
ttlDays?: number,
18-
isPublic?: boolean
19+
isPublic?: boolean,
20+
contentTypeOverride?: ContentType
1921
): Promise<UploadResult> {
2022
core.info(`Uploading tar file: ${filePath}`);
2123

2224
const fileBuffer = fs.readFileSync(filePath);
2325
const fileName = path.basename(filePath);
2426

25-
// Determine content type based on file extension
26-
let contentType: 'tgz' | 'tar' | 'gzip';
27-
if (fileName.endsWith('.tar.gz') || fileName.endsWith('.tgz')) {
27+
let contentType: ContentType;
28+
if (contentTypeOverride) {
29+
contentType = contentTypeOverride;
30+
} else if (fileName.endsWith('.tar.gz') || fileName.endsWith('.tgz')) {
2831
contentType = 'tgz';
2932
} else if (fileName.endsWith('.tar')) {
3033
contentType = 'tar';
@@ -44,15 +47,15 @@ export async function uploadSingleFile(
4447
client: RunloopSDK,
4548
filePath: string,
4649
ttlDays?: number,
47-
isPublic?: boolean
50+
isPublic?: boolean,
51+
contentTypeOverride?: ContentType
4852
): Promise<UploadResult> {
4953
core.info(`Uploading single file: ${filePath}`);
5054

5155
const fileBuffer = fs.readFileSync(filePath);
5256
const fileName = path.basename(filePath);
5357

54-
// Determine content type based on file
55-
const contentType = determineContentType(fileName, fileBuffer);
58+
const contentType = contentTypeOverride ?? determineContentType(fileName, fileBuffer);
5659

5760
return uploadBuffer(client, fileBuffer, fileName, contentType, ttlDays, isPublic);
5861
}

src/validators.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,21 @@ export interface ActionInputs {
1616
pipPackage?: string;
1717
pipIndexUrl?: string;
1818
setupCommands?: string[];
19+
contentType?: ContentType;
1920
isPublic?: boolean;
2021
apiUrl: string;
2122
objectTtlDays?: number;
2223
}
2324

2425
export type SourceType = 'git' | 'tar' | 'file' | 'npm' | 'pip';
26+
export type ContentType = 'text' | 'binary' | 'gzip' | 'tar' | 'tgz';
2527

2628
export function getInputs(): ActionInputs {
2729
// Get all inputs
2830
const sourceType = core.getInput('source-type', { required: true }) as SourceType;
2931
const setupCommandsRaw = core.getInput('setup-commands');
3032
const objectTtlDaysRaw = core.getInput('object-ttl-days');
33+
const contentTypeRaw = core.getInput('content-type') || undefined;
3134

3235
const inputs: ActionInputs = {
3336
apiKey: core.getInput('api-key', { required: true }),
@@ -47,6 +50,7 @@ export function getInputs(): ActionInputs {
4750
.map(cmd => cmd.trim())
4851
.filter(cmd => cmd.length > 0)
4952
: undefined,
53+
contentType: contentTypeRaw as ContentType | undefined,
5054
apiUrl: core.getInput('api-url') || 'https://api.runloop.ai',
5155
objectTtlDays: objectTtlDaysRaw ? parseInt(objectTtlDaysRaw, 10) : undefined,
5256
};
@@ -72,6 +76,16 @@ export function validateInputs(inputs: ActionInputs): void {
7276
);
7377
}
7478

79+
// Validate content-type if provided
80+
if (inputs.contentType) {
81+
const validContentTypes: ContentType[] = ['text', 'binary', 'gzip', 'tar', 'tgz'];
82+
if (!validContentTypes.includes(inputs.contentType)) {
83+
throw new Error(
84+
`Invalid content-type: ${inputs.contentType}. Must be one of: ${validContentTypes.join(', ')}`
85+
);
86+
}
87+
}
88+
7589
// Validate source-specific inputs
7690
switch (inputs.sourceType) {
7791
case 'tar':

0 commit comments

Comments
 (0)