danger-dangermattic 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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