chore: cleanup deprecated `IssueAssistantEventSourceDocument`

This commit is contained in:
insleker 2026-04-10 15:33:45 +08:00 committed by existedinnettw
parent 34330d9b7a
commit 0fb68c886b
17 changed files with 227 additions and 229 deletions

View File

@ -4,4 +4,4 @@
run `pnpx skills experimental_install`, `lefthook install` before development at first time.
- For any new or modified Dart test under `test/`, use the repo-local skill `dart-gherkin-tests`.
- For file more than 500 lines, consider to split it into multiple files for better maintainability.
- Keep refactoring e.g. `SOLID` principles
- Keep refactoring e.g. `SOLID` principles. Aggresively remove deprecated code and features. Don't be afraid to break backward compatibility.

View File

@ -3,16 +3,15 @@
The repo uses an Agent Orchestrator style YAML config with `defaults` and `projects`.
Project entries can override `issueAssistant` fields when a repo needs a
different prompt, mention triggers, responder chain, notification list, or
event source.
different prompt, mention triggers, responder chain, or notification list.
Each project also has separate tracker and SCM config. `issueTracker.provider`
selects the logical tracker family, `issueTracker.eventSource.type` selects the
concrete adapter used to receive updates, and `scm.provider` selects how
temporary repo workspaces are prepared for responders. Legacy top-level project
`provider` and legacy `issueAssistant.eventSource` are still accepted during
load for backward compatibility. When `scm` is omitted it defaults to a
matching provider for existing GitHub, GitLab, and Gitea configs.
`provider` is still accepted during load for backward compatibility. When `scm` is
omitted it defaults to a matching provider for existing GitHub, GitLab, and
Gitea configs.
GitHub projects default to `gh/polling`, GitLab projects default to
`glab/polling`, and Gitea projects default to `tea/polling`. OpenProject

View File

@ -142,10 +142,6 @@ class AppConfig {
defaults: AppConfigDefaultsDocument(
issueAssistant: IssueAssistantConfigDocument(
enabled: true,
eventSource: IssueAssistantEventSourceDocument(
type: IssueTrackerEventSourceKind.ghPolling,
pollInterval: '30s',
),
maxConcurrentIssues: 3,
maxResponsesAfterHuman: 1,
mentionTriggers: const ['@codex', '@helper'],
@ -155,6 +151,10 @@ class AppConfig {
'sample': ProjectConfigDocument(
issueTracker: IssueTrackerConfigDocument(
provider: IssueTrackerProvider.github,
eventSource: EventSourceDocument(
type: IssueTrackerEventSourceKind.ghPolling,
pollInterval: '30s',
),
),
scm: ScmConfigDocument(provider: ScmProvider.github),
repo: 'owner/repo',
@ -207,15 +207,12 @@ class ProjectConfig {
);
}
final resolvedIssueAssistantDocument =
_resolveProjectIssueAssistantDocument(
key: key,
issueTracker: document.issueTracker,
issueAssistant: document.issueAssistant,
final eventSourceDocument = document.issueTracker?.eventSource;
final hasExplicitEventSourceType = eventSourceDocument?.type != null;
var issueAssistant = defaultAssistant.merge(
document.issueAssistant,
eventSourceOverlay: eventSourceDocument,
);
final hasExplicitEventSourceType =
resolvedIssueAssistantDocument?.eventSource?.type != null;
var issueAssistant = defaultAssistant.merge(resolvedIssueAssistantDocument);
final configuredProvider =
document.issueTracker?.provider ?? document.provider;
final inferredProvider = _issueTrackerProviderForEventSource(
@ -225,7 +222,7 @@ class ProjectConfig {
configuredProvider != null &&
configuredProvider != inferredProvider) {
throw FormatException(
'projects.$key.issueAssistant.eventSource '
'projects.$key.issueTracker.eventSource '
'${_eventSourceConfigValue(issueAssistant.eventSource.type)} '
'implies issue tracker provider ${inferredProvider.name}, '
'but the legacy configured provider is ${configuredProvider.name}.',
@ -329,50 +326,6 @@ class ProjectConfig {
}
}
IssueAssistantConfigDocument? _resolveProjectIssueAssistantDocument({
required String key,
required IssueTrackerConfigDocument? issueTracker,
required IssueAssistantConfigDocument? issueAssistant,
}) {
final trackerEventSource = issueTracker?.eventSource;
final assistantEventSource = issueAssistant?.eventSource;
if (trackerEventSource != null &&
assistantEventSource != null &&
!_eventSourceDocumentsMatch(trackerEventSource, assistantEventSource)) {
throw FormatException(
'projects.$key.issueTracker.eventSource and '
'projects.$key.issueAssistant.eventSource must match when both are set.',
);
}
if (trackerEventSource == null) {
return issueAssistant;
}
return IssueAssistantConfigDocument(
enabled: issueAssistant?.enabled,
eventSource: trackerEventSource,
maxConcurrentIssues: issueAssistant?.maxConcurrentIssues,
maxResponsesAfterHuman: issueAssistant?.maxResponsesAfterHuman,
mentionTriggers: issueAssistant?.mentionTriggers,
prompt: issueAssistant?.prompt,
responders: issueAssistant?.responders,
capabilities: issueAssistant?.capabilities,
notifications: issueAssistant?.notifications,
commentTag: issueAssistant?.commentTag,
commentPrefixTemplate: issueAssistant?.commentPrefixTemplate,
commentFooterTemplate: issueAssistant?.commentFooterTemplate,
);
}
bool _eventSourceDocumentsMatch(
IssueAssistantEventSourceDocument left,
IssueAssistantEventSourceDocument right,
) {
return left.type == right.type &&
left.pollInterval == right.pollInterval &&
left.reconciliation == right.reconciliation &&
left.reconcileInterval == right.reconcileInterval;
}
class ScmConfig {
const ScmConfig({required this.provider});
@ -423,14 +376,18 @@ class IssueAssistantConfig {
IssueAssistantConfigDocument? document,
) {
return const _IssueAssistantConfigResolver()
.resolve(base: null, overlay: null)
.resolve(base: null, overlay: null, eventSourceOverlay: null)
.merge(document);
}
IssueAssistantConfig merge(IssueAssistantConfigDocument? overlay) {
IssueAssistantConfig merge(
IssueAssistantConfigDocument? overlay, {
EventSourceDocument? eventSourceOverlay,
}) {
return const _IssueAssistantConfigResolver().resolve(
base: this,
overlay: overlay,
eventSourceOverlay: eventSourceOverlay,
);
}
@ -589,6 +546,7 @@ class _IssueAssistantConfigResolver {
IssueAssistantConfig resolve({
required IssueAssistantConfig? base,
required IssueAssistantConfigDocument? overlay,
required EventSourceDocument? eventSourceOverlay,
}) {
final responders = overlay?.responders;
final notifications = overlay?.notifications;
@ -596,7 +554,7 @@ class _IssueAssistantConfigResolver {
enabled: overlay?.enabled ?? base?.enabled ?? true,
eventSource: _resolveEventSource(
base: base?.eventSource,
overlay: overlay?.eventSource,
overlay: eventSourceOverlay,
),
maxConcurrentIssues: _resolvePositiveInt(
value: overlay?.maxConcurrentIssues,
@ -643,7 +601,7 @@ class _IssueAssistantConfigResolver {
IssueEventSourceConfig _resolveEventSource({
required IssueEventSourceConfig? base,
required IssueAssistantEventSourceDocument? overlay,
required EventSourceDocument? overlay,
}) {
final type =
overlay?.type ?? base?.type ?? IssueTrackerEventSourceKind.ghPolling;
@ -873,13 +831,6 @@ void _assertCamelCaseConfigKeys(Map<String, dynamic> root) {
final issueAssistant = defaults['issueAssistant'];
if (issueAssistant is Map<String, dynamic>) {
_assertCamelCaseMap(issueAssistant, scope: 'defaults.issueAssistant');
final eventSource = issueAssistant['eventSource'];
if (eventSource is Map<String, dynamic>) {
_assertCamelCaseMap(
eventSource,
scope: 'defaults.issueAssistant.eventSource',
);
}
final responders = issueAssistant['responders'];
if (responders is List) {
for (final responder in responders) {
@ -937,13 +888,6 @@ void _assertCamelCaseConfigKeys(Map<String, dynamic> root) {
issueAssistant,
scope: 'projects.${entry.key}.issueAssistant',
);
final eventSource = issueAssistant['eventSource'];
if (eventSource is Map<String, dynamic>) {
_assertCamelCaseMap(
eventSource,
scope: 'projects.${entry.key}.issueAssistant.eventSource',
);
}
final responders = issueAssistant['responders'];
if (responders is List) {
for (final responder in responders) {
@ -996,6 +940,15 @@ IssueTrackerProvider _issueTrackerProviderForEventSource(
}
void _normalizeLegacyEventSourceConfig(Map<String, dynamic> root) {
IssueTrackerEventSourceKind providerDefaultEventSourceType(String? provider) {
return switch (provider) {
'gitlab' => IssueTrackerEventSourceKind.glabPolling,
'gitea' => IssueTrackerEventSourceKind.teaPolling,
'openproject' => IssueTrackerEventSourceKind.opPolling,
_ => IssueTrackerEventSourceKind.ghPolling,
};
}
void normalizeProjectTracker(Map<String, dynamic> project) {
final repo = project['repo'];
if (repo != null && repo is! String) {
@ -1040,58 +993,6 @@ void _normalizeLegacyEventSourceConfig(Map<String, dynamic> root) {
issueTracker['eventSource'] = normalizedEventSource;
}
void normalizeIssueAssistant(
Map<String, dynamic> issueAssistant, {
required IssueTrackerEventSourceKind? defaultType,
}) {
final rawEventSource = issueAssistant['eventSource'];
Map<String, dynamic>? normalizedEventSource;
if (rawEventSource is String) {
normalizedEventSource = <String, dynamic>{'type': rawEventSource};
} else if (rawEventSource is Map<String, dynamic>) {
normalizedEventSource = Map<String, dynamic>.from(rawEventSource);
} else if (rawEventSource == null) {
if (issueAssistant.containsKey('pollInterval') ||
issueAssistant.containsKey('reconciliation') ||
issueAssistant.containsKey('reconcileInterval')) {
normalizedEventSource = <String, dynamic>{};
}
}
if (normalizedEventSource == null) {
return;
}
if (defaultType != null && !normalizedEventSource.containsKey('type')) {
normalizedEventSource['type'] = _eventSourceConfigValue(defaultType);
}
for (final field in [
'pollInterval',
'reconciliation',
'reconcileInterval',
]) {
if (issueAssistant.containsKey(field) &&
!normalizedEventSource.containsKey(field)) {
normalizedEventSource[field] = issueAssistant.remove(field);
}
}
issueAssistant['eventSource'] = normalizedEventSource;
}
final defaults = root['defaults'];
if (defaults is Map<String, dynamic>) {
final issueAssistant = defaults['issueAssistant'];
if (issueAssistant is Map<String, dynamic>) {
normalizeIssueAssistant(
issueAssistant,
defaultType: IssueTrackerEventSourceKind.ghPolling,
);
}
}
final projects = root['projects'];
if (projects is Map<String, dynamic>) {
for (final entry in projects.entries) {
@ -1101,45 +1002,15 @@ void _normalizeLegacyEventSourceConfig(Map<String, dynamic> root) {
}
normalizeProjectTracker(project);
final issueTracker = project['issueTracker'];
final projectDefaultType = providerDefaultEventSourceType(
(project['issueTracker'] as Map<String, dynamic>?)?['provider']
as String? ??
project['provider'] as String?,
);
if (issueTracker is Map<String, dynamic>) {
normalizeIssueTrackerEventSource(
issueTracker,
defaultType: switch (issueTracker['provider'] as String?) {
'gitlab' => IssueTrackerEventSourceKind.glabPolling,
'gitea' => IssueTrackerEventSourceKind.teaPolling,
'openproject' => IssueTrackerEventSourceKind.opPolling,
_ => IssueTrackerEventSourceKind.ghPolling,
},
);
}
final issueAssistant = project['issueAssistant'];
if (issueAssistant is! Map<String, dynamic>) {
if (issueTracker is Map<String, dynamic> &&
issueTracker['eventSource'] is Map<String, dynamic>) {
project['issueAssistant'] = <String, dynamic>{
'eventSource': Map<String, dynamic>.from(
issueTracker['eventSource'] as Map<String, dynamic>,
),
};
}
continue;
}
normalizeIssueAssistant(
issueAssistant,
defaultType: switch ((project['issueTracker']
as Map<String, dynamic>?)?['provider']
as String?) {
'gitlab' => IssueTrackerEventSourceKind.glabPolling,
'gitea' => IssueTrackerEventSourceKind.teaPolling,
'openproject' => IssueTrackerEventSourceKind.opPolling,
_ => IssueTrackerEventSourceKind.ghPolling,
},
);
if (issueTracker is Map<String, dynamic> &&
issueTracker['eventSource'] == null &&
issueAssistant['eventSource'] is Map<String, dynamic>) {
issueTracker['eventSource'] = Map<String, dynamic>.from(
issueAssistant['eventSource'] as Map<String, dynamic>,
defaultType: projectDefaultType,
);
}
}

View File

@ -91,7 +91,7 @@ class IssueTrackerConfigDocument {
const IssueTrackerConfigDocument({this.provider, this.eventSource});
final IssueTrackerProvider? provider;
final IssueAssistantEventSourceDocument? eventSource;
final EventSourceDocument? eventSource;
factory IssueTrackerConfigDocument.fromJson(Map<String, dynamic> json) =>
_$IssueTrackerConfigDocumentFromJson(json);
@ -127,7 +127,6 @@ class ScmConfigDocument {
class IssueAssistantConfigDocument {
const IssueAssistantConfigDocument({
this.enabled,
this.eventSource,
this.maxConcurrentIssues,
this.maxResponsesAfterHuman,
this.mentionTriggers,
@ -141,7 +140,6 @@ class IssueAssistantConfigDocument {
});
final bool? enabled;
final IssueAssistantEventSourceDocument? eventSource;
final int? maxConcurrentIssues;
final int? maxResponsesAfterHuman;
final List<String>? mentionTriggers;
@ -166,8 +164,8 @@ class IssueAssistantConfigDocument {
explicitToJson: true,
includeIfNull: false,
)
class IssueAssistantEventSourceDocument {
const IssueAssistantEventSourceDocument({
class EventSourceDocument {
const EventSourceDocument({
this.type,
this.pollInterval,
this.reconciliation,
@ -179,12 +177,10 @@ class IssueAssistantEventSourceDocument {
final IssueTrackerReconciliationKind? reconciliation;
final String? reconcileInterval;
factory IssueAssistantEventSourceDocument.fromJson(
Map<String, dynamic> json,
) => _$IssueAssistantEventSourceDocumentFromJson(json);
factory EventSourceDocument.fromJson(Map<String, dynamic> json) =>
_$EventSourceDocumentFromJson(json);
Map<String, dynamic> toJson() =>
_$IssueAssistantEventSourceDocumentToJson(this);
Map<String, dynamic> toJson() => _$EventSourceDocumentToJson(this);
}
@JsonSerializable(

View File

@ -65,7 +65,6 @@ void main() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
maxResponsesAfterHuman: 2
mentionTriggers: ["@helper"]
prompt: "default {{repo}}"
@ -723,7 +722,7 @@ projects:
/// ```gherkin
/// Scenario: Keep the legacy issue tracker provider as a fallback
/// Given a config whose project still sets issueTracker.provider to gitea
/// And the project omits issueAssistant.eventSource.type
/// And the project omits issueTracker.eventSource.type
/// When loading the app config from disk
/// Then the project keeps the configured Gitea provider
/// And the polling event source is rewritten to tea/polling
@ -743,7 +742,7 @@ projects:
path: ${tempDir.path}
''');
// And the project omits issueAssistant.eventSource.type.
// And the project omits issueTracker.eventSource.type.
// When loading the app config from disk.
final config = await AppConfig.load(configFile.path);

View File

@ -1,11 +1,81 @@
import 'dart:io';
import 'dart:convert';
import 'package:code_work_spawner/code_work_spawner.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:yaml/yaml.dart';
import '../test_support.dart';
void expectEventSourceUnderIssueTrackerBlock(String yaml) {
final lines = const LineSplitter().convert(yaml);
final issueTrackerIndex = lines.indexWhere(
(line) => RegExp(r'^\s*issueTracker:\s*$').hasMatch(line),
);
expect(
issueTrackerIndex,
isNonNegative,
reason: 'Expected an issueTracker block in the emitted config.',
);
final issueTrackerIndent = _leadingSpaces(lines[issueTrackerIndex]);
var foundNestedEventSource = false;
for (var index = issueTrackerIndex + 1; index < lines.length; index++) {
final line = lines[index];
if (line.trim().isEmpty) {
continue;
}
final indent = _leadingSpaces(line);
if (indent <= issueTrackerIndent) {
break;
}
if (RegExp(r'^\s*eventSource:\s*$').hasMatch(line)) {
foundNestedEventSource = true;
break;
}
}
expect(
foundNestedEventSource,
isTrue,
reason: 'Expected eventSource to be nested under issueTracker.',
);
}
int _leadingSpaces(String value) => value.length - value.trimLeft().length;
Map<String, dynamic> parseYamlToMap(String yaml) {
final decoded = loadYaml(yaml);
if (decoded is! YamlMap) {
throw const FormatException('Expected YAML root map.');
}
return _normalizeYamlNode(decoded) as Map<String, dynamic>;
}
Object? _normalizeYamlNode(Object? value) {
if (value is YamlMap) {
return value.map(
(key, dynamicValue) =>
MapEntry(key.toString(), _normalizeYamlNode(dynamicValue)),
);
}
if (value is YamlList) {
return value.map(_normalizeYamlNode).toList(growable: false);
}
if (value is Map) {
return value.map(
(key, dynamicValue) =>
MapEntry(key.toString(), _normalizeYamlNode(dynamicValue)),
);
}
if (value is List) {
return value.map(_normalizeYamlNode).toList(growable: false);
}
return value;
}
void main() {
/// ```gherkin
/// Feature: Init-config CLI
@ -63,9 +133,20 @@ void main() {
expect(result.stdout, contains('# - type: desktop'));
expect(result.stdout, contains('issueTracker:'));
expect(result.stdout, contains('provider: github'));
expectEventSourceUnderIssueTrackerBlock(result.stdout);
expect(result.stdout, contains('scm:'));
expect(result.stdout, contains('projects:'));
final root = parseYamlToMap(result.stdout);
final project =
(root['projects'] as Map<String, dynamic>)['sample']
as Map<String, dynamic>;
final issueTracker = project['issueTracker'] as Map<String, dynamic>;
expect(issueTracker['eventSource'], isA<Map<String, dynamic>>());
final defaults = root['defaults'] as Map<String, dynamic>;
final issueAssistant = defaults['issueAssistant'] as Map<String, dynamic>;
expect(issueAssistant.containsKey('eventSource'), isFalse);
// And the printed config is valid when written to disk and loaded.
await configFile.writeAsString(result.stdout);
final config = await AppConfig.load(configFile.path);
@ -112,9 +193,20 @@ void main() {
expect(contents, contains('defaults:'));
expect(contents, contains('issueTracker:'));
expect(contents, contains('provider: github'));
expectEventSourceUnderIssueTrackerBlock(contents);
expect(contents, contains('# maxResponsesAfterHuman: 1'));
expect(contents, contains('scm:'));
expect(contents, contains('projects:'));
final root = parseYamlToMap(contents);
final project =
(root['projects'] as Map<String, dynamic>)['sample']
as Map<String, dynamic>;
final issueTracker = project['issueTracker'] as Map<String, dynamic>;
expect(issueTracker['eventSource'], isA<Map<String, dynamic>>());
final defaults = root['defaults'] as Map<String, dynamic>;
final issueAssistant = defaults['issueAssistant'] as Map<String, dynamic>;
expect(issueAssistant.containsKey('eventSource'), isFalse);
final config = await AppConfig.load(outputFile.path);
expect(config.projects['sample'], isNotNull);
expect(config.defaults.maxResponsesAfterHuman, 1);

View File

@ -129,7 +129,6 @@ void registerIssueAssistantAppRunOnceConcurrencyTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
maxConcurrentIssues: 3
mentionTriggers: ["@helper"]
responders:
@ -137,6 +136,9 @@ defaults:
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -267,13 +269,15 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');

View File

@ -84,7 +84,6 @@ void registerIssueAssistantAppRunOnceCoreTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -92,6 +91,9 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
defaultBranch: main
@ -192,13 +194,15 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -286,13 +290,15 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -401,7 +407,6 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
maxResponsesAfterHuman: 1
mentionTriggers: ["@helper"]
responders:
@ -409,6 +414,9 @@ defaults:
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -500,13 +508,15 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');

View File

@ -151,16 +151,21 @@ void registerIssueAssistantAppRunOnceMultiProjectTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 30s
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
repoOne:
issueTracker:
eventSource:
pollInterval: 30s
repo: owner/repo-one
path: ${repoOneDir.path}
repoTwo:
issueTracker:
eventSource:
pollInterval: 30s
repo: owner/repo-two
path: ${repoTwoDir.path}
''');
@ -288,7 +293,6 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -296,6 +300,9 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
provider: gitea
repo: owner/sample
path: ${repoDir.path}
@ -378,7 +385,6 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -387,6 +393,8 @@ defaults:
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
provider: openproject
scm:
provider: github

View File

@ -72,9 +72,11 @@ void registerIssueAssistantAppRunRetryTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 1s
projects:
sample:
issueTracker:
eventSource:
pollInterval: 1s
repo: owner/sample
path: ${repoDir.path}
''');

View File

@ -100,7 +100,6 @@ void registerIssueAssistantAppRunGitHubGosmeeTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -108,11 +107,13 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: github
eventSource:
pollInterval: 5m
type: gh/gosmee
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: gh/gosmee
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),

View File

@ -114,7 +114,6 @@ void registerIssueAssistantAppRunGitLabGosmeeTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -122,11 +121,13 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: gitlab
eventSource:
pollInterval: 5m
type: glab/gosmee
repo: group/subgroup/sample
path: ${repoDir.path}
issueAssistant:
eventSource: glab/gosmee
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),

View File

@ -142,7 +142,6 @@ exit 1
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -150,11 +149,13 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: gitea
eventSource:
pollInterval: 5m
type: tea/gosmee
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: tea/gosmee
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),
@ -357,13 +358,14 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: gitea
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: tea/gosmee
eventSource:
type: tea/gosmee
reconciliation: continuous
reconcileInterval: 1s
repo: owner/sample
path: ${repoDir.path}
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),

View File

@ -89,11 +89,12 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: github
eventSource:
type: gh/webhook-forward
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: gh/webhook-forward
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),
@ -188,11 +189,12 @@ defaults:
enabled: true
projects:
sample:
issueTracker:
provider: github
eventSource:
type: gh/webhook-forward
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: gh/webhook-forward
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),
@ -368,13 +370,14 @@ defaults:
timeout: 1m
projects:
sample:
issueTracker:
provider: github
repo: owner/sample
path: ${repoDir.path}
issueAssistant:
eventSource: gh/webhook-forward
eventSource:
type: gh/webhook-forward
reconciliation: continuous
reconcileInterval: 1s
repo: owner/sample
path: ${repoDir.path}
''');
final app = await IssueAssistantApp.open(
config: await AppConfig.load(configFile.path),

View File

@ -104,13 +104,15 @@ void registerIssueAssistantAppRunOnceNotificationTests() {
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -228,7 +230,6 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
@ -241,6 +242,9 @@ defaults:
username: code-work-spawner
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');

View File

@ -1,7 +1,7 @@
import 'dart:convert';
import 'dart:io';
import '../../bin/code_work_spawner.dart' as _cliEntry;
import '../../bin/code_work_spawner.dart' as cli_entry;
/// Result of a [runCli] invocation.
typedef CliResult = ({int exitCode, String stdout, String stderr});
@ -18,7 +18,7 @@ Future<CliResult> runCli(List<String> args) async {
exitCode = 0;
try {
await IOOverrides.runZoned<Future<void>>(
() => _cliEntry.main(args),
() => cli_entry.main(args),
stdout: () => out,
stderr: () => err,
);

View File

@ -94,13 +94,15 @@ JSON
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -216,13 +218,15 @@ worktreeDir: ${worktreeRoot.path}
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');
@ -311,13 +315,15 @@ projects:
defaults:
issueAssistant:
enabled: true
pollInterval: 5m
mentionTriggers: ["@helper"]
responders:
- id: primary
command: ${responderScript.path}
projects:
sample:
issueTracker:
eventSource:
pollInterval: 5m
repo: owner/sample
path: ${repoDir.path}
''');