Skip to content
Open
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Fixed

- various issues with issue list: --team, --sort flags work now, workspace doesn't need to be set (useful when running unconfigured)

### Changed

- removed uneccessary double prompt around adding labels
Expand Down
9 changes: 6 additions & 3 deletions src/commands/issue/issue-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export const listCommand = new Command()
) => {
const usePager = pager !== false
if (web || app) {
await openTeamAssigneeView({ app: app })
await openTeamAssigneeView({ app: app, team })
return
}

Expand All @@ -110,8 +110,10 @@ export const listCommand = new Command()
Deno.exit(1)
}

const sort = sortFlag ||
getOption("issue_sort") as "manual" | "priority" | undefined
const sort = getOption("issue_sort", sortFlag) as
| "manual"
| "priority"
| undefined
if (!sort) {
console.error(
"Sort must be provided via command line flag, configuration file, or LINEAR_ISSUE_SORT environment variable",
Expand Down Expand Up @@ -142,6 +144,7 @@ export const listCommand = new Command()
assignee,
unassigned,
allAssignees,
sort,
)
spinner?.stop()
const issues = result.issues?.nodes || []
Expand Down
27 changes: 20 additions & 7 deletions src/utils/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,34 @@ export async function openProjectPage(
await open(url, options.app ? { app: { name: "Linear" } } : undefined)
}

export async function openTeamAssigneeView(options: { app?: boolean } = {}) {
const teamId = getTeamKey()
export async function openTeamAssigneeView(
options: { app?: boolean; team?: string } = {},
) {
const teamId = options.team || getTeamKey()
if (!teamId) {
console.error(
"Could not determine team id from configuration or directory name.",
)
Deno.exit(1)
}

const workspace = getOption("workspace")
let workspace = getOption("workspace")
if (!workspace) {
console.error(
"workspace is not set via command line, configuration file, or environment.",
)
Deno.exit(1)
// Get workspace from viewer if not configured
const { gql } = await import("../__codegen__/gql.ts")
const { getGraphQLClient } = await import("./graphql.ts")
const client = getGraphQLClient()
const viewerQuery = gql(`
query GetViewer {
viewer {
organization {
urlKey
}
}
}
`)
const result = await client.request(viewerQuery)
workspace = result.viewer.organization.urlKey
}

const filterObj = {
Expand Down
10 changes: 6 additions & 4 deletions src/utils/linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,11 @@ export async function fetchIssuesForState(
assignee?: string,
unassigned = false,
allAssignees = false,
sort?: "manual" | "priority",
) {
const sort = getOption("issue_sort") as "manual" | "priority" | undefined
if (!sort) {
const sortValue = sort ||
getOption("issue_sort") as "manual" | "priority" | undefined
if (!sortValue) {
console.error(
"Sort must be provided via configuration file or LINEAR_ISSUE_SORT environment variable",
)
Expand Down Expand Up @@ -369,7 +371,7 @@ export async function fetchIssuesForState(
`)

let sortPayload: Array<IssueSortInput>
switch (sort) {
switch (sortValue) {
case "manual":
sortPayload = [
{ workflowState: { order: "Descending" } },
Expand All @@ -383,7 +385,7 @@ export async function fetchIssuesForState(
]
break
default:
throw new Error(`Unknown sort type: ${sort}`)
throw new Error(`Unknown sort type: ${sortValue}`)
}

const client = getGraphQLClient()
Expand Down
4 changes: 2 additions & 2 deletions test/commands/issue/__snapshots__/issue-view.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ stderr:

snapshot[`Issue View Command - With Issue ID 1`] = `
stdout:
"Error: error sending request for url (http://127.0.0.1:3000/graphql): client error (Connect): tcp connect error: Connection refused: Connection refused
"
'Error: GraphQL Error (Code: 401): {"response":{"status":401,"headers":{}},"request":{"query":"query GetIssueDetailsWithComments(\$id: String!) {\\\\n issue(id: \$id) {\\\\n title\\\\n description\\\\n url\\\\n branchName\\\\n comments(first: 50, orderBy: createdAt) {\\\\n nodes {\\\\n id\\\\n body\\\\n createdAt\\\\n user {\\\\n name\\\\n displayName\\\\n }\\\\n externalUser {\\\\n name\\\\n displayName\\\\n }\\\\n parent {\\\\n id\\\\n }\\\\n }\\\\n }\\\\n }\\\\n}","variables":{"id":"TEST-123"}}}
'
stderr:
"✗ Failed to fetch issue details
"
Expand Down
19 changes: 19 additions & 0 deletions test/commands/issue/issue-list.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { snapshotTest } from "@cliffy/testing"
import { assertEquals } from "@std/assert"
import { listCommand } from "../../../src/commands/issue/issue-list.ts"
import { commonDenoArgs } from "../../utils/test-helpers.ts"

Expand All @@ -13,3 +14,21 @@ await snapshotTest({
await listCommand.parse()
},
})

Deno.test("Issue List Command - sort flag should work", async () => {
const args = ["--team", "pre", "-A", "--sort", "priority"]

// This should not throw an error about sort being required
try {
await listCommand.parse(args)
} catch (error) {
// We expect it to fail for other reasons (like API calls), but not for sort validation
if (error instanceof Error) {
assertEquals(
error.message.includes("Sort must be provided"),
false,
"Sort flag was provided but validation still failed",
)
}
}
})
7 changes: 3 additions & 4 deletions test/commands/issue/issue-view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ await snapshotTest({
// Expected to fail with mock endpoint, capture the error for snapshot
// Normalize error message to be consistent across platforms
const message = (error as Error).message
const normalizedMessage = message.replace(
/Connection refused \(os error \d+\)/g,
"Connection refused",
)
const normalizedMessage = message
.replace(/Connection refused \(os error \d+\)/g, "Connection refused")
.replace(/: Connection refused$/g, "")
console.log(`Error: ${normalizedMessage}`)
} finally {
// Clean up environment
Expand Down
Loading