feat: release notes
Each release can carry notes in Markdown, written before or after it ships. A draft is generated from its finished tickets grouped by type, to edit and copy from the releases page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -140,6 +140,7 @@ fragment ReleaseFields on Release {
|
||||
targetDate
|
||||
status
|
||||
releasedAt
|
||||
notes
|
||||
}
|
||||
|
||||
fragment ActivityFields on Activity {
|
||||
|
||||
@@ -368,6 +368,7 @@ export type ReleaseFieldsFragment = {
|
||||
targetDate: string | null;
|
||||
status: ReleaseStatus;
|
||||
releasedAt: string | null;
|
||||
notes: string | null;
|
||||
};
|
||||
|
||||
export type ActivityFieldsFragment = {
|
||||
@@ -1148,6 +1149,7 @@ export type ReleasesQuery = {
|
||||
targetDate: string | null;
|
||||
status: ReleaseStatus;
|
||||
releasedAt: string | null;
|
||||
notes: string | null;
|
||||
progress: { total: number; finished: number; percent: number };
|
||||
}>;
|
||||
};
|
||||
@@ -1208,6 +1210,7 @@ export type UpcomingReleasesQuery = {
|
||||
targetDate: string | null;
|
||||
status: ReleaseStatus;
|
||||
releasedAt: string | null;
|
||||
notes: string | null;
|
||||
progress: { total: number; finished: number; percent: number };
|
||||
}>;
|
||||
};
|
||||
@@ -1229,6 +1232,23 @@ export type ReleaseBurnupQuery = {
|
||||
};
|
||||
};
|
||||
|
||||
export type ReleaseNotesDraftQueryVariables = Exact<{
|
||||
id: string;
|
||||
}>;
|
||||
|
||||
export type ReleaseNotesDraftQuery = {
|
||||
release: { id: string; notesDraft: string };
|
||||
};
|
||||
|
||||
export type WriteReleaseNotesMutationVariables = Exact<{
|
||||
releaseId: string;
|
||||
notes?: string | null | undefined;
|
||||
}>;
|
||||
|
||||
export type WriteReleaseNotesMutation = {
|
||||
writeReleaseNotes: { id: string; key: string | null; version: number };
|
||||
};
|
||||
|
||||
export type SavedFilterFieldsFragment = {
|
||||
id: string;
|
||||
projectId: string;
|
||||
@@ -1489,6 +1509,7 @@ export type ReleaseChangedSubscription = {
|
||||
targetDate: string | null;
|
||||
status: ReleaseStatus;
|
||||
releasedAt: string | null;
|
||||
notes: string | null;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -2119,6 +2140,7 @@ export const ReleaseFieldsFragmentDoc = {
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'targetDate' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'releasedAt' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'notes' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -7298,6 +7320,7 @@ export const ReleasesDocument = {
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'targetDate' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'releasedAt' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'notes' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -7741,6 +7764,7 @@ export const UpcomingReleasesDocument = {
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'targetDate' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'releasedAt' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'notes' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -7814,6 +7838,141 @@ export const ReleaseBurnupDocument = {
|
||||
},
|
||||
],
|
||||
} as unknown as DocumentNode<ReleaseBurnupQuery, ReleaseBurnupQueryVariables>;
|
||||
export const ReleaseNotesDraftDocument = {
|
||||
kind: 'Document',
|
||||
definitions: [
|
||||
{
|
||||
kind: 'OperationDefinition',
|
||||
operation: 'query',
|
||||
name: { kind: 'Name', value: 'ReleaseNotesDraft' },
|
||||
variableDefinitions: [
|
||||
{
|
||||
kind: 'VariableDefinition',
|
||||
variable: { kind: 'Variable', name: { kind: 'Name', value: 'id' } },
|
||||
type: {
|
||||
kind: 'NonNullType',
|
||||
type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
|
||||
},
|
||||
},
|
||||
],
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{
|
||||
kind: 'Field',
|
||||
name: { kind: 'Name', value: 'release' },
|
||||
arguments: [
|
||||
{
|
||||
kind: 'Argument',
|
||||
name: { kind: 'Name', value: 'id' },
|
||||
value: {
|
||||
kind: 'Variable',
|
||||
name: { kind: 'Name', value: 'id' },
|
||||
},
|
||||
},
|
||||
],
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'notesDraft' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
} as unknown as DocumentNode<
|
||||
ReleaseNotesDraftQuery,
|
||||
ReleaseNotesDraftQueryVariables
|
||||
>;
|
||||
export const WriteReleaseNotesDocument = {
|
||||
kind: 'Document',
|
||||
definitions: [
|
||||
{
|
||||
kind: 'OperationDefinition',
|
||||
operation: 'mutation',
|
||||
name: { kind: 'Name', value: 'WriteReleaseNotes' },
|
||||
variableDefinitions: [
|
||||
{
|
||||
kind: 'VariableDefinition',
|
||||
variable: {
|
||||
kind: 'Variable',
|
||||
name: { kind: 'Name', value: 'releaseId' },
|
||||
},
|
||||
type: {
|
||||
kind: 'NonNullType',
|
||||
type: { kind: 'NamedType', name: { kind: 'Name', value: 'ID' } },
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'VariableDefinition',
|
||||
variable: {
|
||||
kind: 'Variable',
|
||||
name: { kind: 'Name', value: 'notes' },
|
||||
},
|
||||
type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } },
|
||||
},
|
||||
],
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{
|
||||
kind: 'Field',
|
||||
name: { kind: 'Name', value: 'writeReleaseNotes' },
|
||||
arguments: [
|
||||
{
|
||||
kind: 'Argument',
|
||||
name: { kind: 'Name', value: 'releaseId' },
|
||||
value: {
|
||||
kind: 'Variable',
|
||||
name: { kind: 'Name', value: 'releaseId' },
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'Argument',
|
||||
name: { kind: 'Name', value: 'notes' },
|
||||
value: {
|
||||
kind: 'Variable',
|
||||
name: { kind: 'Name', value: 'notes' },
|
||||
},
|
||||
},
|
||||
],
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{
|
||||
kind: 'FragmentSpread',
|
||||
name: { kind: 'Name', value: 'CommandResultFields' },
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: 'FragmentDefinition',
|
||||
name: { kind: 'Name', value: 'CommandResultFields' },
|
||||
typeCondition: {
|
||||
kind: 'NamedType',
|
||||
name: { kind: 'Name', value: 'CommandResult' },
|
||||
},
|
||||
selectionSet: {
|
||||
kind: 'SelectionSet',
|
||||
selections: [
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'id' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'key' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'version' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
} as unknown as DocumentNode<
|
||||
WriteReleaseNotesMutation,
|
||||
WriteReleaseNotesMutationVariables
|
||||
>;
|
||||
export const SavedFiltersDocument = {
|
||||
kind: 'Document',
|
||||
definitions: [
|
||||
@@ -9123,6 +9282,7 @@ export const ReleaseChangedDocument = {
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'targetDate' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'status' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'releasedAt' } },
|
||||
{ kind: 'Field', name: { kind: 'Name', value: 'notes' } },
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@@ -59,3 +59,16 @@ query ReleaseBurnup($id: ID!) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query ReleaseNotesDraft($id: ID!) {
|
||||
release(id: $id) {
|
||||
id
|
||||
notesDraft
|
||||
}
|
||||
}
|
||||
|
||||
mutation WriteReleaseNotes($releaseId: ID!, $notes: String) {
|
||||
writeReleaseNotes(releaseId: $releaseId, notes: $notes) {
|
||||
...CommandResultFields
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user