diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a1a7c95 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +src/gql/schema.json linguist-generated=true diff --git a/src/commands/logs.rs b/src/commands/logs.rs index 5f7255a..4d6e264 100644 --- a/src/commands/logs.rs +++ b/src/commands/logs.rs @@ -27,7 +27,8 @@ use super::{ railway logs --service backend --environment production # Stream latest deployment logs from a specific service in a specific environment railway logs --lines 10 --filter \"@level:error\" # View 10 latest error logs railway logs --lines 10 --filter \"@level:warn AND rate limit\" # View 10 latest warning logs related to rate limiting - railway logs --json # Get logs in JSON format" + railway logs --json # Get logs in JSON format + railway logs --latest # Stream logs from the latest deployment (even if failed/building)" )] pub struct Args { /// Service to view logs from (defaults to linked service). Can be service name or service ID @@ -62,6 +63,10 @@ pub struct Args { /// Can be a text search ("error message" or "user signup"), attribute filters (@level:error, @level:warn), or a combination with the operators AND, OR, - (not). See https://docs.railway.com/guides/logs for full syntax. #[clap(long, short = 'f')] filter: Option, + + /// Always show logs from the latest deployment, even if it failed or is still building + #[clap(long)] + latest: bool, } pub async fn command(args: Args) -> Result<()> { @@ -123,11 +128,15 @@ pub async fn command(args: Args) -> Result<()> { .map(|deployment| deployment.node) .collect(); all_deployments.sort_by(|a, b| b.created_at.cmp(&a.created_at)); - let default_deployment = all_deployments - .iter() - .find(|d| d.status == DeploymentStatus::SUCCESS) - .or_else(|| all_deployments.first()) - .context("No deployments found")?; + let default_deployment = if args.latest { + all_deployments.first() + } else { + all_deployments + .iter() + .find(|d| d.status == DeploymentStatus::SUCCESS) + .or_else(|| all_deployments.first()) + } + .context("No deployments found")?; let deployment_id = if let Some(deployment_id) = args.deployment_id { // Use the provided deployment ID directly diff --git a/src/gql/queries/strings/Project.graphql b/src/gql/queries/strings/Project.graphql index 5cb338d..7593212 100644 --- a/src/gql/queries/strings/Project.graphql +++ b/src/gql/queries/strings/Project.graphql @@ -28,6 +28,12 @@ query Project($id: String!) { createdAt deploymentStopped } + activeDeployments { + id + status + createdAt + meta + } source { repo image diff --git a/src/gql/schema.json b/src/gql/schema.json index d427dd5..d992980 100644 --- a/src/gql/schema.json +++ b/src/gql/schema.json @@ -160,12 +160,6 @@ "isDeprecated": false, "name": "CONVERSATIONAL_UI" }, - { - "deprecationReason": null, - "description": null, - "isDeprecated": false, - "name": "HTTP_SERVICE_METRICS" - }, { "deprecationReason": null, "description": null, @@ -176,7 +170,7 @@ "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "MONOREPO_SUPPORT" + "name": "POSTGRES_HA" }, { "deprecationReason": null, @@ -253,13 +247,13 @@ "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "MONOREPO_SUPPORT" + "name": "SCYLLADB_ROUTING_ENABLED" }, { "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "SCYLLADB_ROUTING_ENABLED" + "name": "SERVICEINSTANCE_DATALOADER_FOR_STATIC_URL" }, { "deprecationReason": null, @@ -302,6 +296,18 @@ "isDeprecated": false, "name": "COPY_VOLUME_TO_ENVIRONMENT" }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "ENABLE_DOCKER_EXTENSION" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "ENABLE_ONLINE_VOLUME_RESIZING" + }, { "deprecationReason": null, "description": null, @@ -1153,6 +1159,267 @@ "name": "AppliedByMember", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "context", + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "createdAt", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "environment", + "type": { + "kind": "OBJECT", + "name": "Environment", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "environmentId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "eventType", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "payload", + "type": { + "kind": "SCALAR", + "name": "JSON", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "project", + "type": { + "kind": "OBJECT", + "name": "Project", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "projectId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "workspaceId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + ], + "inputFields": null, + "interfaces": [ + { + "kind": "INTERFACE", + "name": "Node", + "ofType": null + } + ], + "kind": "OBJECT", + "name": "AuditLog", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "description", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "eventType", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "AuditLogEventTypeInfo", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": null, + "inputFields": [ + { + "defaultValue": null, + "description": "Filter events created on or before this date", + "name": "endDate", + "type": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + }, + { + "defaultValue": null, + "description": "Filter events for a single environment", + "name": "environmentId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": "List of event types to filter by", + "name": "eventTypes", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + { + "defaultValue": null, + "description": "Filter events for a single project", + "name": "projectId", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": "Filter events created on or after this date", + "name": "startDate", + "type": { + "kind": "SCALAR", + "name": "DateTime", + "ofType": null + } + } + ], + "interfaces": null, + "kind": "INPUT_OBJECT", + "name": "AuditLogFilterInput", + "possibleTypes": null + }, { "description": null, "enumValues": null, @@ -15563,6 +15830,16 @@ }, { "args": [ + { + "defaultValue": null, + "description": "Optional name/label for the backup. Defaults to 'Manual' if not provided.", + "name": "name", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, { "defaultValue": null, "description": "The id of the volume instance to create a backup of", @@ -16258,6 +16535,11 @@ "name": "ApiToken", "ofType": null }, + { + "kind": "OBJECT", + "name": "AuditLog", + "ofType": null + }, { "kind": "OBJECT", "name": "Container", @@ -18658,13 +18940,13 @@ "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "MONOREPO_SUPPORT" + "name": "SCYLLADB_ROUTING_ENABLED" }, { "deprecationReason": null, "description": null, "isDeprecated": false, - "name": "SCYLLADB_ROUTING_ENABLED" + "name": "SERVICEINSTANCE_DATALOADER_FOR_STATIC_URL" }, { "deprecationReason": null, @@ -23945,6 +24227,166 @@ } } }, + { + "args": [ + { + "defaultValue": null, + "description": "The ID of the audit log entry", + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "defaultValue": null, + "description": "The ID of the workspace", + "name": "workspaceId", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "deprecationReason": null, + "description": "Get an audit log by ID", + "isDeprecated": false, + "name": "auditLog", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "AuditLog", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": "Get a list of all audit log event types and their description", + "isDeprecated": false, + "name": "auditLogEventTypeInfo", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "AuditLogEventTypeInfo", + "ofType": null + } + } + } + } + }, + { + "args": [ + { + "defaultValue": null, + "description": null, + "name": "after", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "before", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "filter", + "type": { + "kind": "INPUT_OBJECT", + "name": "AuditLogFilterInput", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "first", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "last", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "sort", + "type": { + "kind": "ENUM", + "name": "SortOrder", + "ofType": null + } + }, + { + "defaultValue": null, + "description": null, + "name": "workspaceId", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "deprecationReason": null, + "description": "Gets audit logs for a workspace.", + "isDeprecated": false, + "name": "auditLogs", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "QueryAuditLogsConnection", + "ofType": null + } + } + }, { "args": [ { @@ -27713,6 +28155,37 @@ } } }, + { + "args": [ + { + "defaultValue": null, + "description": null, + "name": "id", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + ], + "deprecationReason": null, + "description": "Get the metrics for a template.", + "isDeprecated": false, + "name": "templateMetrics", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "TemplateMetrics", + "ofType": null + } + } + }, { "args": [ { @@ -28739,6 +29212,100 @@ "name": "QueryApiTokensConnectionEdge", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "edges", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "QueryAuditLogsConnectionEdge", + "ofType": null + } + } + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "pageInfo", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "QueryAuditLogsConnection", + "possibleTypes": null + }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "cursor", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "node", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "AuditLog", + "ofType": null + } + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "QueryAuditLogsConnectionEdge", + "possibleTypes": null + }, { "description": null, "enumValues": null, @@ -32557,6 +33124,30 @@ "description": null, "enumValues": null, "fields": [ + { + "args": [], + "deprecationReason": null, + "description": "All currently active (deployed and running) deployments for this service instance", + "isDeprecated": false, + "name": "activeDeployments", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Deployment", + "ofType": null + } + } + } + } + }, { "args": [], "deprecationReason": null, @@ -32740,7 +33331,7 @@ { "args": [], "deprecationReason": null, - "description": null, + "description": "The most recent deployment for this service instance", "isDeprecated": false, "name": "latestDeployment", "type": { @@ -34037,6 +34628,29 @@ "name": "SimilarTemplate", "possibleTypes": null }, + { + "description": null, + "enumValues": [ + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "asc" + }, + { + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "desc" + } + ], + "fields": null, + "inputFields": null, + "interfaces": null, + "kind": "ENUM", + "name": "SortOrder", + "possibleTypes": null + }, { "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", "enumValues": null, @@ -34637,6 +35251,22 @@ "ofType": null } } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "couponName", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } } ], "inputFields": null, @@ -34665,6 +35295,18 @@ } } }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "priceDollars", + "type": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + }, { "args": [], "deprecationReason": null, @@ -34832,7 +35474,7 @@ "possibleTypes": null }, { - "description": null, + "description": "\nSupport Health Metrics for Template Support Bonus Calculation..\nContains metrics calculated from community support thread performance:\n- solved: Percentage (0-100) of solved threads\n- csat: Percentage (0-100) of threads with positive customer satisfaction\n- aggregateHealth: Average of solved and csat when both available, otherwise just solved percentage\nTemplates with aggregateHealth >= 80 qualify for support bonus (additional 10% kickback).\n", "enumValues": null, "fields": null, "inputFields": null, @@ -36836,6 +37478,161 @@ "name": "TemplateMetadata", "possibleTypes": null }, + { + "description": null, + "enumValues": null, + "fields": [ + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "activeDeployments", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "deploymentsLast90Days", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "earningsLast30Days", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "earningsLast90Days", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "eligibleForSupportBonus", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "supportHealth", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "templateHealth", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "totalDeployments", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + } + }, + { + "args": [], + "deprecationReason": null, + "description": null, + "isDeprecated": false, + "name": "totalEarnings", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Float", + "ofType": null + } + } + } + ], + "inputFields": null, + "interfaces": [], + "kind": "OBJECT", + "name": "TemplateMetrics", + "possibleTypes": null + }, { "description": null, "enumValues": null,