danger-dangermattic 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b15ae97cc1a24568ecab35470fabcf26fcb858e586abf81f1c9cba4e8f28a095
4
- data.tar.gz: 5a5441a1ffd66d05a136e3db188b3f20cb963ef8c376ea70af86b6194cf6a79c
3
+ metadata.gz: '094bf199c42dcc05762611116e76958dd679f4fd528aee911a0f2e56cef7ec1e'
4
+ data.tar.gz: 0ea8f18010582cf5d91d0f75a5e7aeadf677fce8bf46fe9d006f0b2cb5985c15
5
5
  SHA512:
6
- metadata.gz: b5fe63d7356f08bd84721b91436eb66e66e6a3b1cb4b53c17e5e503e10d95417af516224c904dd788c5971b5e69d79e09e1d11c0a87673051a2bd34deb6add6a
7
- data.tar.gz: 03c6f7e8fe657924e88aeaecd6d0bf56ae68f133f3b5ed0214267507ab1c4692f711b181a5ec41e2de47bb12e13da4e2af7d6cb0a1155d6ad628a2abf7f74a6d
6
+ metadata.gz: 477a907cde572da9e3c5a76eee541e38b82a240a12b8691dec4c2a1697ebb7a664b80836d5eca45513d26a95e270e67b9cbcde08562f9abb691684fa47a21b93
7
+ data.tar.gz: cc0e1a03b5ddb87b3a7961665f7318feceaff2efe437d261b484c5fad1455a78872c719baee93642d0698dc24314bbc4a22cdb9218c8bc80c7ae6997bfbf55f3
@@ -0,0 +1,71 @@
1
+ # Dangermattic GitHub Workflows Documentation
2
+
3
+ We provide reusable GitHub workflows to be used with Dangermattic.
4
+ Each workflow is designed to be called from other workflows using the `workflow_call` event and input parameters.
5
+ All jobs are run on `ubuntu-latest`.
6
+
7
+ ## Check Labels on Issues
8
+
9
+ **File:** `workflows/reusable-check-labels-on-issues.yml`
10
+
11
+ This workflow is an independent check (not using Danger) to verify if the labels on an issue match specified regex patterns.
12
+
13
+ ### Inputs:
14
+ - `label-format-list`: JSON list of regex formats expected for the labels (default: `[".*"]`)
15
+ - `label-error-message`: Error message when labels don't match
16
+ - `label-success-message`: Success message when labels match
17
+ - `cancel-running-jobs`: Cancel in-progress jobs when new ones are created (default: `true`)
18
+
19
+ ### Secrets:
20
+ - `github-token`: Required GitHub token
21
+
22
+ ### Job: `check-issue-labels`
23
+ - Permissions: `issues: write`
24
+ - Main step: "🏷️ Check Issue Labels"
25
+ - Checks if issue labels match the specified regex patterns
26
+ - Posts a comment on the issue with success or error message
27
+
28
+ ## Retry Buildkite Step on Pull Request Events
29
+
30
+ **File:** `workflows/reusable-retry-buildkite-step-on-events.yml`
31
+
32
+ This workflow retries a specific job in a Buildkite pipeline.
33
+
34
+ ### Inputs:
35
+ - `org-slug`: Buildkite organization slug
36
+ - `pipeline-slug`: Slug of the Buildkite pipeline to be run
37
+ - `retry-step-key`: Key of the Buildkite job to be retried
38
+ - `build-commit-sha`: Commit to check for running Buildkite Builds
39
+ - `cancel-running-github-jobs`: Cancel in-progress GitHub jobs when new ones are created (default: `true`)
40
+
41
+ ### Secrets:
42
+ - `buildkite-api-token`: Required Buildkite API token
43
+
44
+ ### Job: `retry-buildkite-job`
45
+ - Main step: "🔄 Retry job on the latest Buildkite Build"
46
+ - Retrieves the latest Buildkite build for the specified commit
47
+ - Identifies the job to retry based on the provided step key
48
+ - Retries the job if it's in an appropriate state (passed, failed, canceled, or finished)
49
+
50
+ ## Run Danger on GitHub
51
+
52
+ **File:** `workflows/reusable-run-danger.yml`
53
+
54
+ This workflow runs Danger directly on GitHub Actions.
55
+
56
+ ### Inputs:
57
+ - `remove-previous-comments`: Remove previous Danger comments and add a new one (default: `false`)
58
+ - `cancel-running-jobs`: Cancel in-progress jobs when new ones are created (default: `true`)
59
+
60
+ ### Secrets:
61
+ - `github-token`: Required GitHub token
62
+
63
+ ### Job: `dangermattic`
64
+ - Steps:
65
+ 1. Checkout repository
66
+ 2. Set up Ruby
67
+ 3. Run Danger PR Check
68
+ - Executes Danger in read-only mode for forks and Dependabot PRs
69
+ - Runs Danger with full functionality for PRs where the configured token has access to the repo
70
+
71
+ These reusable workflows can be incorporated into other workflows in your repository to perform specific tasks related to issue labeling, Buildkite job management, and pull request checks using Danger.
@@ -1,30 +1,38 @@
1
+ # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2
+
1
3
  on:
2
4
  workflow_call:
3
5
  inputs:
4
6
  label-format-list:
5
- description: 'The Regex formats expected for the labels; must be a JSON list'
6
- default: '[
7
- ".*"
8
- ]'
7
+ description: The Regex formats expected for the labels; must be a JSON list
8
+ default: |
9
+ [
10
+ ".*"
11
+ ]
9
12
  type: string
10
13
  required: false
11
14
  label-error-message:
12
- description: 'Error message to be posted when the labels set don''t match the required list of formats.'
13
- default: 'At least one label is required.'
15
+ description: Error message to be posted when the labels set don't match the required list of formats.
16
+ default: At least one label is required.
14
17
  type: string
15
18
  required: false
16
19
  label-success-message:
17
- description: 'Message to be posted when the labels set fulfill the entire list of expected formats.'
18
- default: '✅ Yay, issue looks great!'
20
+ description: Message to be posted when the labels set fulfill the entire list of expected formats.
21
+ default: ✅ Yay, issue looks great!
19
22
  type: string
20
23
  required: false
24
+ cancel-running-jobs:
25
+ description: Cancel currently in progress jobs when new ones are added.
26
+ default: true
27
+ type: boolean
28
+ required: false
21
29
  secrets:
22
30
  github-token:
23
31
  required: true
24
32
 
25
33
  concurrency:
26
- group: danger-${{ github.event.issue.number }}
27
- cancel-in-progress: true
34
+ group: ${{ github.workflow }}-${{ github.event.issue.number }}
35
+ cancel-in-progress: ${{ inputs.cancel-running-jobs }}
28
36
 
29
37
  jobs:
30
38
  check-issue-labels:
@@ -32,7 +40,7 @@ jobs:
32
40
  permissions:
33
41
  issues: write
34
42
  steps:
35
- - name: "🏷️ Check Issue Labels"
43
+ - name: 🏷️ Check Issue Labels
36
44
  env:
37
45
  GITHUB_TOKEN: ${{ secrets.github-token }}
38
46
  GH_REPO: ${{ github.repository }}
@@ -1,24 +1,26 @@
1
+ # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2
+
1
3
  on:
2
4
  workflow_call:
3
5
  inputs:
4
6
  org-slug:
5
- description: 'Buildkite organization slug'
7
+ description: Buildkite organization slug
6
8
  required: true
7
9
  type: string
8
10
  pipeline-slug:
9
- description: 'Slug of the Buildkite pipeline to be run'
11
+ description: Slug of the Buildkite pipeline to be run
10
12
  required: true
11
13
  type: string
12
14
  retry-step-key:
13
- description: 'Key of the Buildkite job to be retried'
15
+ description: Key of the Buildkite job to be retried
14
16
  required: true
15
17
  type: string
16
18
  build-commit-sha:
17
- description: 'Commit to check for running Buildkite Builds on. Usually github.event.pull_request.head.sha .'
19
+ description: Commit to check for running Buildkite Builds on. Usually github.event.pull_request.head.sha .
18
20
  required: true
19
21
  type: string
20
22
  cancel-running-github-jobs:
21
- description: 'Cancel currently in progress Github jobs when new ones are added.'
23
+ description: Cancel currently in progress Github jobs when new ones are added.
22
24
  default: true
23
25
  type: boolean
24
26
  required: false
@@ -27,15 +29,19 @@ on:
27
29
  required: true
28
30
 
29
31
  concurrency:
30
- group: danger-buildkite-retry-${{ github.ref }}
32
+ group: ${{ github.workflow }}-${{ github.ref }}
31
33
  cancel-in-progress: ${{ inputs.cancel-running-github-jobs }}
32
34
 
33
35
  jobs:
34
36
  retry-buildkite-job:
35
37
  runs-on: ubuntu-latest
36
38
  steps:
37
- - name: "🔄 Retry job on the latest Buildkite Build"
39
+ - name: 🔄 Retry job on the latest Buildkite Build
40
+ env:
41
+ READ_ONLY_MODE: ${{ github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' }}
38
42
  run: |
43
+ [ "$READ_ONLY_MODE" = true ] && { echo "ℹ️ Cannot retry a Buildkite job from GitHub when running in read-only mode (from a fork or a Dependabot Pull Request). Please find the Buildkite job and retry manually."; exit 0; }
44
+
39
45
  ORG_SLUG="${{ inputs.org-slug }}"
40
46
  PIPELINE_SLUG="${{ inputs.pipeline-slug }}"
41
47
  RETRY_STEP_KEY="${{ inputs.retry-step-key }}"
@@ -1,13 +1,15 @@
1
+ # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
2
+
1
3
  on:
2
4
  workflow_call:
3
5
  inputs:
4
6
  remove-previous-comments:
5
- description: 'Configures Danger to always remove previous comments and add a new one instead of editing the same comment.'
7
+ description: Configures Danger to always remove previous comments and add a new one instead of editing the same comment.
6
8
  default: false
7
9
  type: boolean
8
10
  required: false
9
11
  cancel-running-jobs:
10
- description: 'Cancel currently in progress jobs when new ones are added.'
12
+ description: Cancel currently in progress jobs when new ones are added.
11
13
  default: true
12
14
  type: boolean
13
15
  required: false
@@ -16,22 +18,22 @@ on:
16
18
  required: true
17
19
 
18
20
  concurrency:
19
- group: danger-${{ github.ref }}
21
+ group: ${{ github.workflow }}-${{ github.ref }}
20
22
  cancel-in-progress: ${{ inputs.cancel-running-jobs }}
21
23
 
22
24
  jobs:
23
25
  dangermattic:
24
26
  runs-on: ubuntu-latest
25
27
  steps:
26
- - name: "📥 Checkout Repo"
28
+ - name: 📥 Checkout Repo
27
29
  uses: actions/checkout@v4
28
30
  with:
29
31
  fetch-depth: 100
30
- - name: "💎 Ruby Setup"
32
+ - name: 💎 Ruby Setup
31
33
  uses: ruby/setup-ruby@v1
32
34
  with:
33
35
  bundler-cache: true
34
- - name: "☢️ Danger PR Check"
36
+ - name: ☢️ Danger PR Check
35
37
  env:
36
38
  PR_URL: ${{ github.event.pull_request.html_url }}
37
39
  READ_ONLY_MODE: ${{ github.event.pull_request.head.repo.fork || github.actor == 'dependabot[bot]' }}
data/CHANGELOG.md CHANGED
@@ -2,6 +2,40 @@
2
2
 
3
3
  ---
4
4
 
5
+ ## Trunk
6
+
7
+ ### Breaking Changes
8
+
9
+ _None_
10
+
11
+ ### New Features
12
+
13
+ _None_
14
+
15
+ ### Bug Fixes
16
+
17
+ _None_
18
+
19
+ ### Internal Changes
20
+
21
+ _None_
22
+
23
+ ## 1.2.0
24
+
25
+ ### New Features
26
+
27
+ - `manifest_pr_checker`: add check for `Package.resolved` using full paths [#86]
28
+
29
+ ### Bug Fixes
30
+
31
+ - `view_changes_checker`: update GitHub assets URL regex to be less strict [#89]
32
+
33
+ ## 1.1.2
34
+
35
+ ### Internal Changes
36
+
37
+ - Bump Ruby dependencies [#76]
38
+
5
39
  ## 1.1.1
6
40
 
7
41
  ### Internal Changes
@@ -12,19 +46,19 @@
12
46
 
13
47
  ### New Features
14
48
 
15
- - Reusable GitHub Workflow for retrying Buildkite jobs (#64)
49
+ - Reusable GitHub Workflow for retrying Buildkite jobs [#64]
16
50
 
17
51
  ## 1.0.2
18
52
 
19
53
  ### Bug Fixes
20
54
 
21
- - Clean up and update dependencies. (#62)
55
+ - Clean up and update dependencies. [#62]
22
56
 
23
57
  ## 1.0.1
24
58
 
25
59
  ### Bug Fixes
26
60
 
27
- - Fix `tracks_checker` plugin so that only additions / removals in a diff are considered in the check, therefore not including the context parts of the diff. (#58)
61
+ - Fix `tracks_checker` plugin so that only additions / removals in a diff are considered in the check, therefore not including the context parts of the diff. [#58]
28
62
 
29
63
  ## 1.0.0
30
64
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- danger-dangermattic (1.1.1)
4
+ danger-dangermattic (1.2.0)
5
5
  danger (~> 9.4)
6
6
  danger-plugin-api (~> 1.0)
7
7
  danger-rubocop (~> 0.13)
@@ -10,8 +10,8 @@ PATH
10
10
  GEM
11
11
  remote: https://rubygems.org/
12
12
  specs:
13
- addressable (2.8.6)
14
- public_suffix (>= 2.0.2, < 6.0)
13
+ addressable (2.8.7)
14
+ public_suffix (>= 2.0.2, < 7.0)
15
15
  ast (2.4.2)
16
16
  base64 (0.2.0)
17
17
  claide (1.1.0)
@@ -23,7 +23,8 @@ GEM
23
23
  colored2 (3.1.2)
24
24
  cork (0.3.0)
25
25
  colored2 (~> 3.1)
26
- danger (9.4.3)
26
+ danger (9.5.1)
27
+ base64 (~> 0.2)
27
28
  claide (~> 1.0)
28
29
  claide-plugins (>= 0.9.2)
29
30
  colored2 (~> 3.1)
@@ -33,8 +34,8 @@ GEM
33
34
  git (~> 1.13)
34
35
  kramdown (~> 2.3)
35
36
  kramdown-parser-gfm (~> 1.0)
36
- no_proxy_fix
37
37
  octokit (>= 4.0)
38
+ pstore (~> 0.1)
38
39
  terminal-table (>= 1, < 4)
39
40
  danger-plugin-api (1.0.0)
40
41
  danger (> 2.0)
@@ -42,18 +43,21 @@ GEM
42
43
  danger
43
44
  rubocop (~> 1.0)
44
45
  diff-lcs (1.5.1)
45
- faraday (2.9.0)
46
- faraday-net_http (>= 2.0, < 3.2)
46
+ faraday (2.12.0)
47
+ faraday-net_http (>= 2.0, < 3.4)
48
+ json
49
+ logger
47
50
  faraday-http-cache (2.5.1)
48
51
  faraday (>= 0.8)
49
- faraday-net_http (3.1.0)
52
+ faraday-net_http (3.3.0)
50
53
  net-http
51
- ffi (1.16.3)
54
+ ffi (1.17.0)
55
+ ffi (1.17.0-arm64-darwin)
52
56
  formatador (1.1.0)
53
57
  git (1.19.1)
54
58
  addressable (~> 2.8)
55
59
  rchardet (~> 1.8)
56
- guard (2.18.1)
60
+ guard (2.19.0)
57
61
  formatador (>= 0.2.4)
58
62
  listen (>= 2.7, < 4.0)
59
63
  lumberjack (>= 1.0.12, < 2.0)
@@ -67,7 +71,7 @@ GEM
67
71
  guard (~> 2.1)
68
72
  guard-compat (~> 1.1)
69
73
  rspec (>= 2.99.0, < 4.0)
70
- json (2.7.2)
74
+ json (2.7.5)
71
75
  kramdown (2.4.0)
72
76
  rexml
73
77
  kramdown-parser-gfm (1.1.0)
@@ -76,30 +80,30 @@ GEM
76
80
  listen (3.9.0)
77
81
  rb-fsevent (~> 0.10, >= 0.10.3)
78
82
  rb-inotify (~> 0.9, >= 0.9.10)
83
+ logger (1.6.1)
79
84
  lumberjack (1.2.10)
80
85
  method_source (1.1.0)
81
86
  nap (1.1.0)
82
87
  nenv (0.3.0)
83
88
  net-http (0.4.1)
84
89
  uri
85
- no_proxy_fix (0.1.2)
86
90
  notiffany (0.1.3)
87
91
  nenv (~> 0.1)
88
92
  shellany (~> 0.0)
89
- octokit (8.1.0)
90
- base64
93
+ octokit (9.2.0)
91
94
  faraday (>= 1, < 3)
92
95
  sawyer (~> 0.9)
93
96
  open4 (1.3.4)
94
- parallel (1.24.0)
95
- parser (3.3.1.0)
97
+ parallel (1.26.3)
98
+ parser (3.3.5.1)
96
99
  ast (~> 2.4.1)
97
100
  racc
98
101
  pry (0.14.2)
99
102
  coderay (~> 1.1)
100
103
  method_source (~> 1.0)
101
- public_suffix (5.0.5)
102
- racc (1.8.0)
104
+ pstore (0.1.3)
105
+ public_suffix (6.0.1)
106
+ racc (1.8.1)
103
107
  rainbow (3.1.1)
104
108
  rake (13.2.1)
105
109
  rb-fsevent (0.11.2)
@@ -107,59 +111,47 @@ GEM
107
111
  ffi (~> 1.0)
108
112
  rchardet (1.8.0)
109
113
  regexp_parser (2.9.2)
110
- rexml (3.2.8)
111
- strscan (>= 3.0.9)
114
+ rexml (3.3.9)
112
115
  rspec (3.13.0)
113
116
  rspec-core (~> 3.13.0)
114
117
  rspec-expectations (~> 3.13.0)
115
118
  rspec-mocks (~> 3.13.0)
116
- rspec-core (3.13.0)
119
+ rspec-core (3.13.2)
117
120
  rspec-support (~> 3.13.0)
118
- rspec-expectations (3.13.0)
121
+ rspec-expectations (3.13.3)
119
122
  diff-lcs (>= 1.2.0, < 2.0)
120
123
  rspec-support (~> 3.13.0)
121
- rspec-mocks (3.13.1)
124
+ rspec-mocks (3.13.2)
122
125
  diff-lcs (>= 1.2.0, < 2.0)
123
126
  rspec-support (~> 3.13.0)
124
127
  rspec-support (3.13.1)
125
- rubocop (1.63.5)
128
+ rubocop (1.68.0)
126
129
  json (~> 2.3)
127
130
  language_server-protocol (>= 3.17.0)
128
131
  parallel (~> 1.10)
129
132
  parser (>= 3.3.0.2)
130
133
  rainbow (>= 2.2.2, < 4.0)
131
- regexp_parser (>= 1.8, < 3.0)
132
- rexml (>= 3.2.5, < 4.0)
133
- rubocop-ast (>= 1.31.1, < 2.0)
134
+ regexp_parser (>= 2.4, < 3.0)
135
+ rubocop-ast (>= 1.32.2, < 2.0)
134
136
  ruby-progressbar (~> 1.7)
135
137
  unicode-display_width (>= 2.4.0, < 3.0)
136
- rubocop-ast (1.31.3)
138
+ rubocop-ast (1.33.0)
137
139
  parser (>= 3.3.1.0)
138
- rubocop-capybara (2.20.0)
139
- rubocop (~> 1.41)
140
- rubocop-factory_bot (2.25.1)
141
- rubocop (~> 1.41)
142
140
  rubocop-rake (0.6.0)
143
141
  rubocop (~> 1.0)
144
- rubocop-rspec (2.29.2)
145
- rubocop (~> 1.40)
146
- rubocop-capybara (~> 2.17)
147
- rubocop-factory_bot (~> 2.22)
148
- rubocop-rspec_rails (~> 2.28)
149
- rubocop-rspec_rails (2.28.3)
150
- rubocop (~> 1.40)
142
+ rubocop-rspec (3.2.0)
143
+ rubocop (~> 1.61)
151
144
  ruby-progressbar (1.13.0)
152
145
  sawyer (0.9.2)
153
146
  addressable (>= 2.3.5)
154
147
  faraday (>= 0.17.3, < 3)
155
148
  shellany (0.0.1)
156
- strscan (3.1.0)
157
149
  terminal-table (3.0.2)
158
150
  unicode-display_width (>= 1.1.1, < 3)
159
- thor (1.3.1)
160
- unicode-display_width (2.5.0)
161
- uri (0.13.0)
162
- yard (0.9.36)
151
+ thor (1.3.2)
152
+ unicode-display_width (2.6.0)
153
+ uri (0.13.1)
154
+ yard (0.9.37)
163
155
 
164
156
  PLATFORMS
165
157
  arm64-darwin-22
data/README.md CHANGED
@@ -35,6 +35,10 @@ Once the main Gem is installed, all Dangermattic plugins are available in your `
35
35
 
36
36
  All available plugins are defined here: https://github.com/Automattic/dangermattic/tree/trunk/lib/dangermattic/plugins
37
37
 
38
+ ## GitHub Workflows
39
+
40
+ Dangermattic also provides some useful reusable GitHub workflows. For more information on available workflows and how to use them, please refer to the [Workflows README](.github/workflows/README.md).
41
+
38
42
  ## Development
39
43
 
40
44
  - Clone the repo and run `bundle install` to setup dependencies
@@ -66,3 +70,26 @@ my_new_plugin_checker.check_method(param: my_param_value)
66
70
  ```
67
71
 
68
72
  Please follow the existing naming convention for validation and check plugins: classes end with a `*Checker` suffix and the main validation methods are named with a `check_*` prefix.
73
+
74
+ ## Releasing a new version
75
+
76
+ To create a new release of the Dangermattic gem, use the `new_release` Rake task:
77
+
78
+ ```
79
+ bundle exec rake new_release
80
+ ```
81
+
82
+ This task will:
83
+
84
+ 1. Parse the `CHANGELOG.md` file to get the latest version and pending changes.
85
+ 1. Prompt for the new version number.
86
+ 1. Update the `VERSION` constant in the `gem_version.rb` file.
87
+ 1. Update the `CHANGELOG.md` file with the new version.
88
+ 1. Create a new branch, commit the changes, and push to GitHub.
89
+ 1. Open a draft Pull Request for the release.
90
+
91
+ After running the task, follow the instructions provided to complete the release process:
92
+
93
+ 1. Review and merge the Pull Request.
94
+ 1. Create a GitHub release targeting the `trunk` branch, using the changelog content provided.
95
+ 1. Publishing the GitHub release with a tag will trigger a CI workflow to publish the new gem version to RubyGems.
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ task all: %i[specs lint]
11
11
 
12
12
  desc 'Ensure that the plugin passes `danger plugins lint`'
13
13
  task :danger_lint do
14
- sh 'bundle exec danger plugins lint'
14
+ sh('bundle', 'exec', 'danger', 'plugins', 'lint')
15
15
  end
16
16
 
17
17
  desc 'Runs linting tasks: :rubocop and :danger_lint'
@@ -22,3 +22,90 @@ RSpec::Core::RakeTask.new(:specs)
22
22
 
23
23
  desc 'Run RuboCop on the lib/specs directory'
24
24
  RuboCop::RakeTask.new(:rubocop)
25
+
26
+ desc 'Generate the docs using YARD'
27
+ task :doc do
28
+ sh('bundle', 'exec', 'yard', 'doc')
29
+ # Open generated doc in browser
30
+ sh('open', 'yard-doc/index.html')
31
+ end
32
+
33
+ desc "Print stats about undocumented methods. Provide an optional path relative to 'lib/dangermattic/plugins' to only show stats for that subdirectory"
34
+ task :docstats, [:path] do |_, args|
35
+ path = File.join('lib/dangermattic/plugins', args[:path] || '.')
36
+ sh('yard', 'stats', '--list-undoc', path)
37
+ end
38
+
39
+ VERSION_FILE = File.join('lib', 'dangermattic', 'gem_version.rb')
40
+
41
+ desc 'Create a new version of the dangermattic gem'
42
+ task :new_release do
43
+ require_relative(VERSION_FILE)
44
+
45
+ parser = ChangelogParser.new(file: 'CHANGELOG.md')
46
+ latest_version = parser.parse_pending_section
47
+
48
+ ## Print current info
49
+ Console.header "Current version is: #{Dangermattic::VERSION}"
50
+ Console.warning "Warning: Latest version number does not match latest version title in CHANGELOG (#{latest_version})!" unless latest_version == Dangermattic::VERSION
51
+
52
+ Console.header 'Pending CHANGELOG:'
53
+ changelog = parser.cleaned_pending_changelog_lines
54
+ Console.print_indented_lines(changelog)
55
+
56
+ ## Prompt for next version number
57
+ guess = parser.guessed_next_semantic_version(current: Dangermattic::VERSION)
58
+ new_version = Console.prompt('New version to release', guess)
59
+
60
+ ## Checkout branch, update files
61
+ GitHelper.check_or_create_branch(new_version)
62
+ Console.header 'Update `VERSION` constant in `version.rb`...'
63
+ update_version_constant(VERSION_FILE, new_version)
64
+ Console.header 'Updating CHANGELOG...'
65
+ parser.update_for_new_release(new_version: new_version)
66
+
67
+ # Commit and push
68
+ Console.header 'Commit and push changes...'
69
+ GitHelper.commit_files("Bumped to version #{new_version}", [VERSION_FILE, 'Gemfile.lock', 'CHANGELOG.md'])
70
+
71
+ Console.header 'Opening PR draft in your default browser...'
72
+ pr_body = <<~BODY
73
+ Releasing new version #{new_version}.
74
+
75
+ # What's Next
76
+
77
+ PR Author: Be sure to create and publish a GitHub Release pointing to `trunk` once this PR gets merged,
78
+ copy/pasting the following text as the GitHub Release's description:
79
+ ```
80
+ #{changelog.join}
81
+ ```
82
+ BODY
83
+ GitHelper.prepare_github_pr("release/#{new_version}", 'trunk', "Release #{new_version} into trunk", pr_body)
84
+
85
+ Console.info <<~INSTRUCTIONS
86
+
87
+ ---------------
88
+
89
+ >>> WHAT'S NEXT
90
+
91
+ Once the PR is merged, publish a GitHub release for `#{new_version}`, targeting `trunk`,
92
+ with the following text as description:
93
+
94
+ ```
95
+ #{changelog.join}
96
+ ```
97
+
98
+ The publication of the new GitHub release will create a git tag, which in turn will trigger
99
+ a CI workflow that will take care of doing the `gem push` of the new version to RubyGems.
100
+
101
+ INSTRUCTIONS
102
+ end
103
+
104
+ def update_version_constant(version_file, new_version)
105
+ content = File.read(version_file)
106
+ content.gsub!(/VERSION = .*/, "VERSION = '#{new_version}'")
107
+ File.write(version_file, content)
108
+
109
+ # Updates the Gemfile.lock with the new dangermattic version
110
+ sh('bundle', 'install', '--quiet')
111
+ end
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.required_ruby_version = '~> 3.2'
23
23
 
24
24
  spec.add_dependency 'danger', '~> 9.4'
25
- spec.add_runtime_dependency 'danger-plugin-api', '~> 1.0'
25
+ spec.add_dependency 'danger-plugin-api', '~> 1.0'
26
26
 
27
27
  # Danger plugins
28
28
  spec.add_dependency 'danger-rubocop', '~> 0.13'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dangermattic
4
- VERSION = '1.1.1'
4
+ VERSION = '1.2.0'
5
5
  end
@@ -29,6 +29,7 @@ module Danger
29
29
  #
30
30
  class ManifestPRChecker < Plugin
31
31
  MESSAGE = '`%s` was changed without updating its corresponding `%s`. %s.'
32
+ SWIFT_INSTRUCTION = 'Please resolve the Swift packages as appropriate to your project setup (e.g. in Xcode or by running `swift package resolve`)'
32
33
 
33
34
  # Performs all the checks, asserting that changes on `Gemfile`, `Podfile` and `Package.swift` must have corresponding
34
35
  # lock file changes.
@@ -46,7 +47,6 @@ module Danger
46
47
  #
47
48
  # @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
48
49
  #
49
- #
50
50
  # @return [void]
51
51
  def check_gemfile_lock_updated(report_type: :warning)
52
52
  check_manifest_lock_updated(
@@ -61,7 +61,6 @@ module Danger
61
61
  #
62
62
  # @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
63
63
  #
64
- #
65
64
  # @return [void]
66
65
  def check_podfile_lock_updated(report_type: :warning)
67
66
  check_manifest_lock_updated(
@@ -76,13 +75,27 @@ module Danger
76
75
  #
77
76
  # @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
78
77
  #
79
- #
80
78
  # @return [void]
81
79
  def check_swift_package_resolved_updated(report_type: :warning)
82
80
  check_manifest_lock_updated(
83
81
  file_name: 'Package.swift',
84
82
  lock_file_name: 'Package.resolved',
85
- instruction: 'Please resolve the Swift packages in Xcode',
83
+ instruction: SWIFT_INSTRUCTION,
84
+ report_type: report_type
85
+ )
86
+ end
87
+
88
+ # Check if the `Package.swift` file was modified without a corresponding `Package.resolved` update,
89
+ # checking for exact path matches
90
+ #
91
+ # @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
92
+ #
93
+ # @return [void]
94
+ def check_swift_package_resolved_updated_strict(manifest_path:, manifest_lock_path:, report_type: :warning)
95
+ check_manifest_lock_updated_strict(
96
+ manifest_path: manifest_path,
97
+ manifest_lock_path: manifest_lock_path,
98
+ instruction: SWIFT_INSTRUCTION,
86
99
  report_type: report_type
87
100
  )
88
101
  end
@@ -91,16 +104,27 @@ module Danger
91
104
 
92
105
  def check_manifest_lock_updated(file_name:, lock_file_name:, instruction:, report_type: :warning)
93
106
  # Find all the modified manifest files
94
- manifest_modified_files = git.modified_files.select { |f| File.basename(f) == file_name }
107
+ manifest_modified_files = git_utils.all_changed_files.select { |f| File.basename(f) == file_name }
95
108
 
96
109
  # For each manifest file, check if the corresponding lockfile (in the same dir) was also modified
97
110
  manifest_modified_files.each do |manifest_file|
98
- lockfile_modified = git.modified_files.any? { |f| File.dirname(f) == File.dirname(manifest_file) && File.basename(f) == lock_file_name }
111
+ lockfile_modified = git_utils.all_changed_files.any? { |f| File.dirname(f) == File.dirname(manifest_file) && File.basename(f) == lock_file_name }
99
112
  next if lockfile_modified
100
113
 
101
114
  message = format(MESSAGE, manifest_file, lock_file_name, instruction)
102
115
  reporter.report(message: message, type: report_type)
103
116
  end
104
117
  end
118
+
119
+ def check_manifest_lock_updated_strict(manifest_path:, manifest_lock_path:, instruction:, report_type: :warning)
120
+ manifest_modified = git_utils.all_changed_files.include?(manifest_path)
121
+ return unless manifest_modified
122
+
123
+ lockfile_modified = git_utils.all_changed_files.include?(manifest_lock_path)
124
+ return if lockfile_modified
125
+
126
+ message = format(MESSAGE, manifest_path, File.basename(manifest_lock_path), instruction)
127
+ reporter.report(message: message, type: report_type)
128
+ end
105
129
  end
106
130
  end
@@ -18,7 +18,7 @@ module Danger
18
18
  MEDIA_IN_PR_BODY_PATTERNS = [
19
19
  %r{https?://\S*\.(gif|jpg|jpeg|png|svg)},
20
20
  %r{https?://\S*\.(mp4|avi|mov|mkv)},
21
- %r{https?://\S*github\S+/\S+/assets/\d+/},
21
+ %r{https?://\S*github\S+/\S+/assets/},
22
22
  /!\[(.*?)\]\((.*?)\)/,
23
23
  /<img\s+[^>]*src\s*=\s*[^>]*>/,
24
24
  /<video\s+[^>]*src\s*=\s*[^>]*>/
@@ -31,7 +31,7 @@ module Danger
31
31
  # displaying a warning if view files have been modified but no screenshot or video is included.
32
32
  #
33
33
  # @return [void]
34
- def check
34
+ def check(report_type: :warning)
35
35
  view_files_modified = git.modified_files.any? do |file|
36
36
  VIEW_EXTENSIONS_IOS =~ file || VIEW_EXTENSIONS_ANDROID =~ file
37
37
  end
@@ -40,7 +40,7 @@ module Danger
40
40
  github.pr_body =~ pattern
41
41
  end
42
42
 
43
- warn(MESSAGE) if view_files_modified && !pr_has_media
43
+ reporter.report(message: MESSAGE, type: report_type) if view_files_modified && !pr_has_media
44
44
  end
45
45
  end
46
46
  end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parses and updates changelog files for software projects.
4
+ #
5
+ # This class provides functionality to parse a changelog file, identify pending
6
+ # sections for upcoming releases, and update the changelog for new releases based on
7
+ # semantic versioning conventions.
8
+ #
9
+ # @example
10
+ # parser = ChangelogParser.new(file: 'CHANGELOG.md')
11
+ # latest_version = parser.parse_pending_section
12
+ # new_version = parser.guessed_next_semantic_version(current: '1.0.0')
13
+ # parser.update_for_new_release(new_version: new_version)
14
+ class ChangelogParser
15
+ PENDING_SECTION_TITLE = 'Trunk'
16
+ EMPTY_PLACEHOLDER = '_None_'
17
+ SUBSECTIONS_SEMVER_MAP = { 'Breaking Changes': 3, 'New Features': 2, 'Bug Fixes': 1, 'Internal Changes': 1 }.freeze
18
+
19
+ def initialize(file: 'CHANGELOG.md')
20
+ @lines = File.readlines(file)
21
+ @current_index = nil
22
+ @pending_section = nil
23
+ end
24
+
25
+ # @return the title of the section after the pending one -- which should match the latest released version
26
+ def parse_pending_section
27
+ (lines_before_first_section, _, title) = advance_to_next_header(level: 2)
28
+ raise "Expected #{PENDING_SECTION_TITLE} as first section but found #{title} instead." unless title == PENDING_SECTION_TITLE
29
+
30
+ subsections = []
31
+ prev_subtitle = nil
32
+ loop do
33
+ (lines, next_level, next_subtitle) = advance_to_next_header(level: 2..3)
34
+ subsections.append({ title: prev_subtitle, lines: lines }) unless lines.reject { |l| l.chomp.empty? || l.chomp == EMPTY_PLACEHOLDER }.empty?
35
+ prev_subtitle = next_subtitle
36
+
37
+ break if next_level < 3
38
+ end
39
+ @pending_section = { lines_before: lines_before_first_section, subsections: subsections, next_title: prev_subtitle }
40
+ prev_subtitle
41
+ end
42
+
43
+ def cleaned_pending_changelog_lines
44
+ lines = []
45
+ @pending_section[:subsections].map do |s|
46
+ lines.append "### #{s[:title]}\n" unless s[:title].nil? # subsection title is nil for lines between h2 and first h3
47
+ lines += s[:lines]
48
+ end
49
+ lines
50
+ end
51
+
52
+ def guessed_next_semantic_version(current:)
53
+ comps = current.split('.')
54
+ idx_to_bump = 3 - semver_category
55
+ comps[idx_to_bump] = (comps[idx_to_bump].to_i + 1).to_s
56
+ ((idx_to_bump + 1)...(comps.length)).each { |i| comps[i] = '0' }
57
+ comps.join('.')
58
+ end
59
+
60
+ def update_for_new_release(new_version:, new_file: 'CHANGELOG.md')
61
+ raise 'You need to call #parse_pending_section first' if @pending_section.nil?
62
+
63
+ File.open(new_file, 'w') do |f|
64
+ f.puts @pending_section[:lines_before]
65
+ # Empty placeholder section for next version after this one
66
+ f.puts placeholder_section
67
+ # Section for new version, with the non-empty subsections found while parsing first section
68
+ f.puts "## #{new_version}\n\n"
69
+ f.puts cleaned_pending_changelog_lines
70
+ f.puts "## #{@pending_section[:next_title]}"
71
+ f.puts read_up_to_end
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ # Advance line pointer to next index of provided `level`
78
+ # @return [Array] A 3-item array of [scanned_lines, next_header_level, next_header_title]
79
+ def advance_to_next_header(level:)
80
+ range = level.is_a?(Range) ? level : level..level
81
+ regex = /^(\#{#{range.min},#{range.max}}) ?([^#].*)$/ # A line starting with {range.min,range.max} times '#' then optional space then a title
82
+ start_idx = @current_index.nil? ? 0 : @current_index + 1
83
+ offset = @lines[start_idx...].index { |l| l =~ regex }
84
+ @current_index = offset.nil? ? -1 : start_idx + offset
85
+
86
+ m = regex.match(@lines[@current_index])
87
+ [@lines[start_idx...@current_index], m[1].length, m[2]]
88
+ end
89
+
90
+ def read_up_to_end
91
+ idx = @current_index + 1
92
+ @current_index = -1
93
+ @lines[idx...]
94
+ end
95
+
96
+ def placeholder_section
97
+ lines = ["## #{PENDING_SECTION_TITLE}\n\n"]
98
+ lines += SUBSECTIONS_SEMVER_MAP.keys.map { |s| "### #{s}\n\n#{EMPTY_PLACEHOLDER}\n\n" }
99
+ lines.join
100
+ end
101
+
102
+ # @return the SemVer category (as described in Gem::Version doc). 3=major, 2=minor, 1=patch
103
+ def semver_category
104
+ raise 'You need to call #parse_pending_section first' if @pending_section.nil?
105
+
106
+ @pending_section[:subsections].map { |s| SUBSECTIONS_SEMVER_MAP[s[:title].to_sym] || 1 }.max || 1
107
+ end
108
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides methods for colored console output and user interaction.
4
+ #
5
+ # The Console module contains methods for printing colored text to the terminal using
6
+ # ANSI escape codes. It also includes utility methods for prompting user input.
7
+ module Console
8
+ # ANSI colors
9
+ RED = 1
10
+ GREEN = 2
11
+ YELLOW = 3
12
+ PURPLE = 4
13
+
14
+ def self.color_puts(lines, color_code:)
15
+ puts "\x1b[3#{color_code}m#{lines}\x1b[0m"
16
+ end
17
+
18
+ def self.header(title)
19
+ color_puts(">>> #{title}", color_code: GREEN) # green
20
+ end
21
+
22
+ def self.info(text)
23
+ color_puts(text, color_code: YELLOW) # yellow
24
+ end
25
+
26
+ def self.warning(text)
27
+ color_puts(text, color_code: RED) # red
28
+ end
29
+
30
+ def self.print_indented_lines(lines)
31
+ color_puts(lines.map { |l| "| #{l}" }.join, color_code: YELLOW)
32
+ end
33
+
34
+ def self.prompt(text, default_value)
35
+ color_puts("#{text}? [default: #{default_value}] ", color_code: GREEN)
36
+ answer = $stdin.gets.chomp
37
+ answer = default_value if answer.empty?
38
+ answer
39
+ end
40
+
41
+ def self.confirm(text)
42
+ color_puts("#{text} [y/n]?", color_code: GREEN)
43
+ answer = $stdin.gets.chomp
44
+ answer.downcase == 'y'
45
+ end
46
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+
5
+ # Helper methods for common Git operations: checking / creating branches, preparing a pull request and
6
+ # committing / pushing files.
7
+ module GitHelper
8
+ def self.current_branch
9
+ `git --no-pager branch --show-current`.chomp
10
+ end
11
+
12
+ def self.check_or_create_branch(new_version)
13
+ release_branch = "release/#{new_version}"
14
+ branch_exists = !`git --no-pager branch -a --list --no-color #{release_branch}`.chomp.empty?
15
+ if current_branch == release_branch
16
+ puts 'Already on release branch'
17
+ elsif branch_exists
18
+ Rake.sh('git', 'checkout', release_branch)
19
+ else # create it
20
+ abort('Aborted, as not run from trunk nor release branch') unless current_branch == 'trunk' || Console.confirm("You are not on 'trunk', nor already on '#{release_branch}'. Do you really want to cut the release branch from #{current_branch}?")
21
+
22
+ Rake.sh('git', 'checkout', '-b', release_branch)
23
+ end
24
+ end
25
+
26
+ def self.prepare_github_pr(head, base, title, body)
27
+ require 'open-uri'
28
+ qtitle = CGI.escape(title)
29
+ qbody = CGI.escape(body)
30
+ uri = "https://github.com/Automattic/dangermattic/compare/#{base}...#{head}?expand=1&title=#{qtitle}&body=#{qbody}"
31
+ Rake.sh('open', uri)
32
+ end
33
+
34
+ def self.commit_files(message, files, push: true)
35
+ Rake.sh('git', 'add', *files)
36
+ Rake.sh('git', 'commit', '-m', message)
37
+ Rake.sh('git', 'push', '-q', '-u', 'origin', current_branch) if push
38
+ end
39
+ end
@@ -17,7 +17,7 @@ module Danger
17
17
  describe 'Bundler' do
18
18
  it 'reports a warning when a PR changed the Gemfile but not the Gemfile.lock' do
19
19
  modified_files = ['Gemfile']
20
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
20
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
21
21
 
22
22
  @plugin.check_gemfile_lock_updated
23
23
 
@@ -27,7 +27,7 @@ module Danger
27
27
 
28
28
  it 'reports no warnings when both the Gemfile and the Gemfile.lock were updated' do
29
29
  modified_files = ['Gemfile', 'Gemfile.lock']
30
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
30
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
31
31
 
32
32
  @plugin.check_gemfile_lock_updated
33
33
 
@@ -36,7 +36,7 @@ module Danger
36
36
 
37
37
  it 'reports no warnings when only the Gemfile.lock was updated' do
38
38
  modified_files = ['Gemfile.lock']
39
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
39
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
40
40
 
41
41
  @plugin.check_gemfile_lock_updated
42
42
 
@@ -47,7 +47,7 @@ module Danger
47
47
  describe 'CocoaPods' do
48
48
  it 'reports a warning when a PR changed the Podfile but not the Podfile.lock' do
49
49
  modified_files = ['Podfile']
50
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
50
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
51
51
 
52
52
  @plugin.check_podfile_lock_updated
53
53
 
@@ -57,7 +57,7 @@ module Danger
57
57
 
58
58
  it 'reports no warnings when both the Podfile and the Podfile.lock were updated' do
59
59
  modified_files = ['Podfile', 'Podfile.lock']
60
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
60
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
61
61
 
62
62
  @plugin.check_podfile_lock_updated
63
63
 
@@ -66,7 +66,7 @@ module Danger
66
66
 
67
67
  it 'reports a warning when a PR changed a custom located Podfile but not the corresponding Podfile.lock' do
68
68
  modified_files = ['./path/to/Podfile', './my/Podfile.lock']
69
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
69
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
70
70
 
71
71
  @plugin.check_podfile_lock_updated
72
72
 
@@ -76,7 +76,7 @@ module Danger
76
76
 
77
77
  it 'reports multiple warnings when a PR changed multiple custom located Podfiles but not the corresponding Podfile.lock' do
78
78
  modified_files = ['./dir1/Podfile', './dir2/Podfile', './dir3/Podfile', './dir1/Podfile.lock']
79
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
79
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
80
80
 
81
81
  @plugin.check_podfile_lock_updated
82
82
 
@@ -89,7 +89,7 @@ module Danger
89
89
 
90
90
  it 'reports no warnings when both custom located Podfile`s and their corresponding Podfile.lock were updated' do
91
91
  modified_files = ['./my/path/to/Podfile', './another/path/to/Podfile', './my/path/to/Podfile.lock', './another/path/to/Podfile.lock']
92
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
92
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
93
93
 
94
94
  @plugin.check_podfile_lock_updated
95
95
 
@@ -98,7 +98,7 @@ module Danger
98
98
 
99
99
  it 'reports no warnings when only the Podfile.lock was updated' do
100
100
  modified_files = ['Podfile.lock']
101
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
101
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
102
102
 
103
103
  @plugin.check_podfile_lock_updated
104
104
 
@@ -107,32 +107,73 @@ module Danger
107
107
  end
108
108
 
109
109
  describe 'Swift Package Manager' do
110
- it 'reports a warning when a PR changed the Package.swift but not the Package.resolved' do
111
- modified_files = ['Package.swift']
112
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
110
+ describe '#check_swift_package_resolved_updated' do
111
+ it 'reports a warning when a PR changed the Package.swift but not the Package.resolved' do
112
+ modified_files = ['Package.swift']
113
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
113
114
 
114
- @plugin.check_swift_package_resolved_updated
115
+ @plugin.check_swift_package_resolved_updated
115
116
 
116
- expected_warning = format(ManifestPRChecker::MESSAGE, 'Package.swift', 'Package.resolved', 'Please resolve the Swift packages in Xcode')
117
- expect(@dangerfile).to report_warnings([expected_warning])
118
- end
117
+ expected_warning = format(ManifestPRChecker::MESSAGE, 'Package.swift', 'Package.resolved', ManifestPRChecker::SWIFT_INSTRUCTION)
118
+ expect(@dangerfile).to report_warnings([expected_warning])
119
+ end
119
120
 
120
- it 'reports no warnings when both the Package.swift and the Package.resolved were updated' do
121
- modified_files = ['Package.swift', 'Package.resolved']
122
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
121
+ it 'reports no warnings when both the Package.swift and the Package.resolved were updated' do
122
+ modified_files = ['Package.swift', 'Package.resolved']
123
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
123
124
 
124
- @plugin.check_swift_package_resolved_updated
125
+ @plugin.check_swift_package_resolved_updated
125
126
 
126
- expect(@dangerfile).to not_report
127
+ expect(@dangerfile).to not_report
128
+ end
129
+
130
+ it 'reports no warnings when only the Package.resolved was updated' do
131
+ modified_files = ['Package.resolved']
132
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
133
+
134
+ @plugin.check_swift_package_resolved_updated
135
+
136
+ expect(@dangerfile).to not_report
137
+ end
127
138
  end
128
139
 
129
- it 'reports no warnings when only the Package.resolved was updated' do
130
- modified_files = ['Package.resolved']
131
- allow(@plugin.git).to receive(:modified_files).and_return(modified_files)
140
+ describe '#check_swift_package_resolved_updated_strict' do
141
+ it 'reports a warning when a PR changed the specific Package.swift but not its Package.resolved' do
142
+ modified_files = ['Apps/App1/Package.swift', 'Apps/App2/Package.swift', 'Apps/App2/Package.resolved']
143
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
132
144
 
133
- @plugin.check_swift_package_resolved_updated
145
+ @plugin.check_swift_package_resolved_updated_strict(
146
+ manifest_path: 'Apps/App1/Package.swift',
147
+ manifest_lock_path: 'Apps/App1/Package.resolved'
148
+ )
134
149
 
135
- expect(@dangerfile).to not_report
150
+ expected_warning = format(ManifestPRChecker::MESSAGE, 'Apps/App1/Package.swift', 'Package.resolved', ManifestPRChecker::SWIFT_INSTRUCTION)
151
+ expect(@dangerfile).to report_warnings([expected_warning])
152
+ end
153
+
154
+ it 'reports no warning when both the specific Package.swift and Package.resolved were updated' do
155
+ modified_files = ['Apps/App1/Package.swift', 'Apps/App1/Package.resolved']
156
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
157
+
158
+ @plugin.check_swift_package_resolved_updated_strict(
159
+ manifest_path: 'Apps/App1/Package.swift',
160
+ manifest_lock_path: 'Apps/App1/Package.resolved'
161
+ )
162
+
163
+ expect(@dangerfile).to not_report
164
+ end
165
+
166
+ it 'reports no warning when the specific Package.swift was not modified' do
167
+ modified_files = ['Apps/App2/Package.swift', 'Apps/App2/Package.resolved']
168
+ allow(@plugin.git_utils).to receive(:all_changed_files).and_return(modified_files)
169
+
170
+ @plugin.check_swift_package_resolved_updated_strict(
171
+ manifest_path: 'Apps/App1/Package.swift',
172
+ manifest_lock_path: 'Apps/App1/Package.resolved'
173
+ )
174
+
175
+ expect(@dangerfile).to not_report
176
+ end
136
177
  end
137
178
  end
138
179
  end
data/spec/spec_helper.rb CHANGED
@@ -28,7 +28,6 @@ require 'danger_plugin'
28
28
  # it comes with an extra function `.string` which will
29
29
  # strip all ANSI colours from the string.
30
30
 
31
- # rubocop:disable Lint/NestedMethodDefinition
32
31
  def testing_ui
33
32
  @output = StringIO.new
34
33
  def @output.winsize
@@ -41,7 +40,6 @@ def testing_ui
41
40
  end
42
41
  cork
43
42
  end
44
- # rubocop:enable Lint/NestedMethodDefinition
45
43
 
46
44
  # Example environment (ENV)
47
45
  def testing_env
@@ -75,7 +75,7 @@ module Danger
75
75
  expect(@dangerfile).to not_report
76
76
  end
77
77
 
78
- it 'does nothing when a PR with view code changes has a video defined with a simple URL' do
78
+ it 'does nothing when a PR with view code changes has a video defined with a simple repo assets URL' do
79
79
  allow(@plugin.github).to receive(:pr_body)
80
80
  .and_return("see video:\nhttps://github.com/woocommerce/woocommerce-ios/assets/1864060/0e983305-5047-40a3-8829-734e0b582b96 body body")
81
81
 
@@ -83,6 +83,15 @@ module Danger
83
83
 
84
84
  expect(@dangerfile).to not_report
85
85
  end
86
+
87
+ it 'does nothing when a PR with view code changes has a video defined with a simple GitHub assets URL' do
88
+ allow(@plugin.github).to receive(:pr_body)
89
+ .and_return("see video:\nhttps://github.com/user-attachments/assets/f3461fec-f96c-4376-9e00-f8faf65f3457 body body")
90
+
91
+ @plugin.check
92
+
93
+ expect(@dangerfile).to not_report
94
+ end
86
95
  end
87
96
 
88
97
  shared_examples 'PR without view code changes' do |modified_files|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danger-dangermattic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Automattic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-21 00:00:00.000000000 Z
11
+ date: 2024-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: danger
@@ -201,6 +201,7 @@ files:
201
201
  - ".buildkite/gem-push.sh"
202
202
  - ".buildkite/pipeline.yml"
203
203
  - ".bundle/config"
204
+ - ".github/workflows/README.md"
204
205
  - ".github/workflows/reusable-check-labels-on-issues.yml"
205
206
  - ".github/workflows/reusable-retry-buildkite-step-on-events.yml"
206
207
  - ".github/workflows/reusable-run-danger.yml"
@@ -234,6 +235,9 @@ files:
234
235
  - lib/dangermattic/plugins/pr_size_checker.rb
235
236
  - lib/dangermattic/plugins/tracks_checker.rb
236
237
  - lib/dangermattic/plugins/view_changes_checker.rb
238
+ - rakelib/changelog_parser.rake
239
+ - rakelib/console.rake
240
+ - rakelib/git_helpers.rake
237
241
  - spec/android_release_checker_spec.rb
238
242
  - spec/android_strings_checker_spec.rb
239
243
  - spec/android_unit_test_checker_spec.rb