diff --git a/action-scripts/label-dispatcher/README-ja.md b/action-scripts/label-dispatcher/README-ja.md index c7b45a5..7315585 100644 --- a/action-scripts/label-dispatcher/README-ja.md +++ b/action-scripts/label-dispatcher/README-ja.md @@ -86,7 +86,7 @@ bundle exec ruby label-dispatcher/bin/dispatcher help_usage ## 変更パスの照合 -変更ファイルを定義された stack のパスに照合し、サービス・環境・任意 placeholder を抽出します。`environments` を持つ stack は定義環境だけを受け付け、パスに環境名がない場合は定義環境ごとに評価します。両方の属性マップがない stack は変更パスから抽出した環境名を使います。`attributes` を持つ stack は `environment: null` の照合として扱います。 +変更ファイルを定義された stack のパスに照合し、サービス・環境・任意 placeholder を抽出します。stack のパスはディレクトリを指すため、そのディレクトリ配下にある変更ファイルだけが一致し、ファイル自身のパスが解決後のパスと等しい場合は対象外です。`environments` を持つ stack は定義環境だけを受け付け、パスに環境名がない場合は定義環境ごとに評価します。両方の属性マップがない stack は変更パスから抽出した環境名を使います。`attributes` を持つ stack は `environment: null` の照合として扱います。 各照合に除外条件を適用し、除外されない照合が一つでもあるサービスを一度だけラベル対象にします。サービス全体のディレクトリを検出対象にする場合は、そのパスも stack に定義します。削除されたファイルも照合するため、ディレクトリの存在は要求しません。 diff --git a/action-scripts/label-dispatcher/README.md b/action-scripts/label-dispatcher/README.md index 2164cf9..25dfae0 100644 --- a/action-scripts/label-dispatcher/README.md +++ b/action-scripts/label-dispatcher/README.md @@ -86,7 +86,7 @@ The dispatcher sets the following environment variables for GitHub Actions: ## Change Matching -Matches changed files against configured stack paths and extracts services, environments, and arbitrary placeholders. A stack with `environments` accepts only its declared names; a path without an environment name is evaluated for each declared environment. A stack with neither attribute map uses the environment captured from the changed path. A stack with `attributes` is evaluated with `environment: null`. +Matches changed files against configured stack paths and extracts services, environments, and arbitrary placeholders. A stack path resolves to a directory, so a changed file matches only when it is located under that directory; a file whose own path equals the resolved path is ignored. A stack with `environments` accepts only its declared names; a path without an environment name is evaluated for each declared environment. A stack with neither attribute map uses the environment captured from the changed path. A stack with `attributes` is evaluated with `environment: null`. Applies exclusion conditions to each match. A service receives one label if at least one match is not excluded. To detect changes throughout a service directory, include that path in a stack definition. Directories need not exist because deleted files are also matched. diff --git a/action-scripts/shared/entities/pattern_matcher.rb b/action-scripts/shared/entities/pattern_matcher.rb index 24f30e9..367e7f2 100644 --- a/action-scripts/shared/entities/pattern_matcher.rb +++ b/action-scripts/shared/entities/pattern_matcher.rb @@ -41,11 +41,10 @@ def self.extract(pattern, path) match_to_hash(regex.match(path), pattern) end - # Like extract, but only requires the pattern to match the prefix of path. - # Path may carry additional "/"-separated segments after the pattern. + # Like extract, but path must carry at least one "/"-separated segment after the pattern. def self.extract_prefix(pattern, path) return nil if pattern.nil? || path.nil? - regex = Regexp.new("\\A#{compile_regex_body(pattern)}(?:/.*)?\\z") + regex = Regexp.new("\\A#{compile_regex_body(pattern)}/.+\\z") match_to_hash(regex.match(path), pattern) end diff --git a/action-scripts/spec/label-dispatcher/use_cases/detect_changed_services_spec.rb b/action-scripts/spec/label-dispatcher/use_cases/detect_changed_services_spec.rb index caba8dd..67302c4 100644 --- a/action-scripts/spec/label-dispatcher/use_cases/detect_changed_services_spec.rb +++ b/action-scripts/spec/label-dispatcher/use_cases/detect_changed_services_spec.rb @@ -63,6 +63,18 @@ def services expect(services).to eq(['api']) end + it 'ignores files placed at the service position' do + config_hash['stacks'] = [{ 'name' => 'container', 'paths' => ['dystopia/{service}'], 'attributes' => {} }] + changed_files.replace(['dystopia/README.md', 'dystopia/api/main.rb']) + expect(services).to eq(['api']) + end + + it 'ignores files placed at the environment position' do + config_hash['stacks'] = [{ 'name' => 'kubernetes', 'paths' => ['dystopia/{service}/kubernetes/overlays/{environment}'] }] + changed_files.replace(['dystopia/web/kubernetes/overlays/README.md', 'dystopia/api/kubernetes/overlays/develop/kustomization.yaml']) + expect(services).to eq(['api']) + end + it 'uses AND within conditions and OR across conditions' do stack['exclude'] = [{ 'team' => 'platform', 'service' => 'demo' }, { 'team' => 'sandbox' }] changed_files.replace(['teams/platform/api/aws/develop/main.tf', 'teams/sandbox/api/aws/develop/main.tf', 'teams/platform/demo/aws/develop/main.tf']) diff --git a/action-scripts/spec/shared/entities/pattern_matcher_spec.rb b/action-scripts/spec/shared/entities/pattern_matcher_spec.rb index 1b38df3..a47d684 100644 --- a/action-scripts/spec/shared/entities/pattern_matcher_spec.rb +++ b/action-scripts/spec/shared/entities/pattern_matcher_spec.rb @@ -129,10 +129,16 @@ expect(result).to eq('service' => 'foo') end - it 'matches when path equals the pattern exactly' do + it 'returns nil when the path equals the pattern exactly' do expect( described_class.extract_prefix('{service}/terragrunt', 'foo/terragrunt') - ).to eq('service' => 'foo') + ).to be_nil + end + + it 'returns nil when the path ends with a separator after the pattern' do + expect( + described_class.extract_prefix('{service}/terragrunt', 'foo/terragrunt/') + ).to be_nil end it 'returns nil when the path is shorter than the pattern' do