diff --git a/AGENTS.md b/AGENTS.md index 55e9ea3..d04e4ac 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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. diff --git a/examples/README.md b/examples/README.md index 73bf2f8..c75939b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -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 diff --git a/lib/src/config/config.dart b/lib/src/config/config.dart index e48c134..b49ee90 100644 --- a/lib/src/config/config.dart +++ b/lib/src/config/config.dart @@ -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 hasExplicitEventSourceType = - resolvedIssueAssistantDocument?.eventSource?.type != null; - var issueAssistant = defaultAssistant.merge(resolvedIssueAssistantDocument); + final eventSourceDocument = document.issueTracker?.eventSource; + final hasExplicitEventSourceType = eventSourceDocument?.type != null; + var issueAssistant = defaultAssistant.merge( + document.issueAssistant, + eventSourceOverlay: eventSourceDocument, + ); 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 root) { final issueAssistant = defaults['issueAssistant']; if (issueAssistant is Map) { _assertCamelCaseMap(issueAssistant, scope: 'defaults.issueAssistant'); - final eventSource = issueAssistant['eventSource']; - if (eventSource is Map) { - _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 root) { issueAssistant, scope: 'projects.${entry.key}.issueAssistant', ); - final eventSource = issueAssistant['eventSource']; - if (eventSource is Map) { - _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 root) { + IssueTrackerEventSourceKind providerDefaultEventSourceType(String? provider) { + return switch (provider) { + 'gitlab' => IssueTrackerEventSourceKind.glabPolling, + 'gitea' => IssueTrackerEventSourceKind.teaPolling, + 'openproject' => IssueTrackerEventSourceKind.opPolling, + _ => IssueTrackerEventSourceKind.ghPolling, + }; + } + void normalizeProjectTracker(Map project) { final repo = project['repo']; if (repo != null && repo is! String) { @@ -1040,58 +993,6 @@ void _normalizeLegacyEventSourceConfig(Map root) { issueTracker['eventSource'] = normalizedEventSource; } - void normalizeIssueAssistant( - Map issueAssistant, { - required IssueTrackerEventSourceKind? defaultType, - }) { - final rawEventSource = issueAssistant['eventSource']; - Map? normalizedEventSource; - - if (rawEventSource is String) { - normalizedEventSource = {'type': rawEventSource}; - } else if (rawEventSource is Map) { - normalizedEventSource = Map.from(rawEventSource); - } else if (rawEventSource == null) { - if (issueAssistant.containsKey('pollInterval') || - issueAssistant.containsKey('reconciliation') || - issueAssistant.containsKey('reconcileInterval')) { - normalizedEventSource = {}; - } - } - - 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) { - final issueAssistant = defaults['issueAssistant']; - if (issueAssistant is Map) { - normalizeIssueAssistant( - issueAssistant, - defaultType: IssueTrackerEventSourceKind.ghPolling, - ); - } - } - final projects = root['projects']; if (projects is Map) { for (final entry in projects.entries) { @@ -1101,45 +1002,15 @@ void _normalizeLegacyEventSourceConfig(Map root) { } normalizeProjectTracker(project); final issueTracker = project['issueTracker']; + final projectDefaultType = providerDefaultEventSourceType( + (project['issueTracker'] as Map?)?['provider'] + as String? ?? + project['provider'] as String?, + ); if (issueTracker is Map) { 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) { - if (issueTracker is Map && - issueTracker['eventSource'] is Map) { - project['issueAssistant'] = { - 'eventSource': Map.from( - issueTracker['eventSource'] as Map, - ), - }; - } - continue; - } - normalizeIssueAssistant( - issueAssistant, - defaultType: switch ((project['issueTracker'] - as Map?)?['provider'] - as String?) { - 'gitlab' => IssueTrackerEventSourceKind.glabPolling, - 'gitea' => IssueTrackerEventSourceKind.teaPolling, - 'openproject' => IssueTrackerEventSourceKind.opPolling, - _ => IssueTrackerEventSourceKind.ghPolling, - }, - ); - if (issueTracker is Map && - issueTracker['eventSource'] == null && - issueAssistant['eventSource'] is Map) { - issueTracker['eventSource'] = Map.from( - issueAssistant['eventSource'] as Map, + defaultType: projectDefaultType, ); } } diff --git a/lib/src/config/config_schema.dart b/lib/src/config/config_schema.dart index 25bc990..befe558 100644 --- a/lib/src/config/config_schema.dart +++ b/lib/src/config/config_schema.dart @@ -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 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? 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 json, - ) => _$IssueAssistantEventSourceDocumentFromJson(json); + factory EventSourceDocument.fromJson(Map json) => + _$EventSourceDocumentFromJson(json); - Map toJson() => - _$IssueAssistantEventSourceDocumentToJson(this); + Map toJson() => _$EventSourceDocumentToJson(this); } @JsonSerializable( diff --git a/test/config/app_config_test.dart b/test/config/app_config_test.dart index 3e8373a..ed34540 100644 --- a/test/config/app_config_test.dart +++ b/test/config/app_config_test.dart @@ -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); diff --git a/test/config/init_config_cli_test.dart b/test/config/init_config_cli_test.dart index f89efc6..5bd412b 100644 --- a/test/config/init_config_cli_test.dart +++ b/test/config/init_config_cli_test.dart @@ -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 parseYamlToMap(String yaml) { + final decoded = loadYaml(yaml); + if (decoded is! YamlMap) { + throw const FormatException('Expected YAML root map.'); + } + return _normalizeYamlNode(decoded) as Map; +} + +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)['sample'] + as Map; + final issueTracker = project['issueTracker'] as Map; + expect(issueTracker['eventSource'], isA>()); + final defaults = root['defaults'] as Map; + final issueAssistant = defaults['issueAssistant'] as Map; + 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)['sample'] + as Map; + final issueTracker = project['issueTracker'] as Map; + expect(issueTracker['eventSource'], isA>()); + final defaults = root['defaults'] as Map; + final issueAssistant = defaults['issueAssistant'] as Map; + expect(issueAssistant.containsKey('eventSource'), isFalse); final config = await AppConfig.load(outputFile.path); expect(config.projects['sample'], isNotNull); expect(config.defaults.maxResponsesAfterHuman, 1); diff --git a/test/core/concurrency_test.dart b/test/core/concurrency_test.dart index a587b53..71ad180 100644 --- a/test/core/concurrency_test.dart +++ b/test/core/concurrency_test.dart @@ -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} '''); diff --git a/test/core/core_test.dart b/test/core/core_test.dart index adcdd6d..81dc1d9 100644 --- a/test/core/core_test.dart +++ b/test/core/core_test.dart @@ -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} '''); diff --git a/test/core/multi_project_test.dart b/test/core/multi_project_test.dart index c86e633..b2ca8ea 100644 --- a/test/core/multi_project_test.dart +++ b/test/core/multi_project_test.dart @@ -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 diff --git a/test/core/retry_test.dart b/test/core/retry_test.dart index 64957de..76348c8 100644 --- a/test/core/retry_test.dart +++ b/test/core/retry_test.dart @@ -72,9 +72,11 @@ void registerIssueAssistantAppRunRetryTests() { defaults: issueAssistant: enabled: true - pollInterval: 1s projects: sample: + issueTracker: + eventSource: + pollInterval: 1s repo: owner/sample path: ${repoDir.path} '''); diff --git a/test/issue_event_source/github_gosmee_test.dart b/test/issue_event_source/github_gosmee_test.dart index 7a8ad11..ead73fc 100644 --- a/test/issue_event_source/github_gosmee_test.dart +++ b/test/issue_event_source/github_gosmee_test.dart @@ -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: - provider: github + 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), diff --git a/test/issue_event_source/gitlab_gosmee_test.dart b/test/issue_event_source/gitlab_gosmee_test.dart index 5807240..9aac4dc 100644 --- a/test/issue_event_source/gitlab_gosmee_test.dart +++ b/test/issue_event_source/gitlab_gosmee_test.dart @@ -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: - provider: gitlab + 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), diff --git a/test/issue_event_source/gosmee_test.dart b/test/issue_event_source/gosmee_test.dart index 8db40d0..a082997 100644 --- a/test/issue_event_source/gosmee_test.dart +++ b/test/issue_event_source/gosmee_test.dart @@ -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: - provider: gitea + 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: - provider: gitea + issueTracker: + provider: gitea + eventSource: + type: tea/gosmee + reconciliation: continuous + reconcileInterval: 1s repo: owner/sample path: ${repoDir.path} - issueAssistant: - eventSource: tea/gosmee - reconciliation: continuous - reconcileInterval: 1s '''); final app = await IssueAssistantApp.open( config: await AppConfig.load(configFile.path), diff --git a/test/issue_event_source/webhook_forward_test.dart b/test/issue_event_source/webhook_forward_test.dart index 5d86cc4..42097f3 100644 --- a/test/issue_event_source/webhook_forward_test.dart +++ b/test/issue_event_source/webhook_forward_test.dart @@ -89,11 +89,12 @@ defaults: timeout: 1m projects: sample: - provider: github + 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: - provider: github + 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: - provider: github + issueTracker: + provider: github + eventSource: + type: gh/webhook-forward + reconciliation: continuous + reconcileInterval: 1s repo: owner/sample path: ${repoDir.path} - issueAssistant: - eventSource: gh/webhook-forward - reconciliation: continuous - reconcileInterval: 1s '''); final app = await IssueAssistantApp.open( config: await AppConfig.load(configFile.path), diff --git a/test/notifier/notifications_test.dart b/test/notifier/notifications_test.dart index 1999c11..0996145 100644 --- a/test/notifier/notifications_test.dart +++ b/test/notifier/notifications_test.dart @@ -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} '''); diff --git a/test/support/cli_utils.dart b/test/support/cli_utils.dart index 45ba4a6..248bd00 100644 --- a/test/support/cli_utils.dart +++ b/test/support/cli_utils.dart @@ -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 runCli(List args) async { exitCode = 0; try { await IOOverrides.runZoned>( - () => _cliEntry.main(args), + () => cli_entry.main(args), stdout: () => out, stderr: () => err, ); diff --git a/test/workspace/worktree_test.dart b/test/workspace/worktree_test.dart index 6458ec8..b4ab2af 100644 --- a/test/workspace/worktree_test.dart +++ b/test/workspace/worktree_test.dart @@ -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} ''');