plan_my_stuff 0.1.0 → 1.0.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 +4 -4
- data/CHANGELOG.md +595 -0
- data/CONFIGURATION.md +487 -0
- data/README.md +612 -88
- data/app/controllers/plan_my_stuff/application_controller.rb +27 -5
- data/app/controllers/plan_my_stuff/comments_controller.rb +50 -19
- data/app/controllers/plan_my_stuff/issues/approvals_controller.rb +127 -0
- data/app/controllers/plan_my_stuff/issues/closures_controller.rb +53 -0
- data/app/controllers/plan_my_stuff/issues/links_controller.rb +129 -0
- data/app/controllers/plan_my_stuff/issues/takes_controller.rb +161 -0
- data/app/controllers/plan_my_stuff/issues/testings_controller.rb +82 -0
- data/app/controllers/plan_my_stuff/issues/viewers_controller.rb +62 -0
- data/app/controllers/plan_my_stuff/issues/waitings_controller.rb +55 -0
- data/app/controllers/plan_my_stuff/issues_controller.rb +53 -70
- data/app/controllers/plan_my_stuff/labels_controller.rb +32 -10
- data/app/controllers/plan_my_stuff/project_items/assignments_controller.rb +88 -0
- data/app/controllers/plan_my_stuff/project_items/statuses_controller.rb +44 -0
- data/app/controllers/plan_my_stuff/project_items_controller.rb +32 -69
- data/app/controllers/plan_my_stuff/projects_controller.rb +81 -3
- data/app/controllers/plan_my_stuff/testing_project_items/results_controller.rb +67 -0
- data/app/controllers/plan_my_stuff/testing_project_items_controller.rb +49 -0
- data/app/controllers/plan_my_stuff/testing_projects_controller.rb +121 -0
- data/app/controllers/plan_my_stuff/webhooks/aws_controller.rb +202 -0
- data/app/controllers/plan_my_stuff/webhooks/github_controller.rb +371 -0
- data/app/jobs/plan_my_stuff/application_job.rb +8 -0
- data/app/jobs/plan_my_stuff/reminders_sweep_job.rb +75 -0
- data/app/views/plan_my_stuff/comments/edit.html.erb +1 -3
- data/app/views/plan_my_stuff/comments/partials/_form.html.erb +8 -0
- data/app/views/plan_my_stuff/issues/edit.html.erb +2 -4
- data/app/views/plan_my_stuff/issues/index.html.erb +5 -5
- data/app/views/plan_my_stuff/issues/new.html.erb +2 -4
- data/app/views/plan_my_stuff/issues/partials/_approvals.html.erb +108 -0
- data/app/views/plan_my_stuff/issues/partials/_form.html.erb +11 -6
- data/app/views/plan_my_stuff/issues/partials/_labels.html.erb +4 -3
- data/app/views/plan_my_stuff/issues/partials/_links.html.erb +113 -0
- data/app/views/plan_my_stuff/issues/partials/_viewers.html.erb +4 -3
- data/app/views/plan_my_stuff/issues/show.html.erb +67 -6
- data/app/views/plan_my_stuff/partials/_flash.html.erb +3 -0
- data/app/views/plan_my_stuff/projects/edit.html.erb +5 -0
- data/app/views/plan_my_stuff/projects/index.html.erb +18 -2
- data/app/views/plan_my_stuff/projects/new.html.erb +5 -0
- data/app/views/plan_my_stuff/projects/partials/_form.html.erb +30 -0
- data/app/views/plan_my_stuff/projects/show.html.erb +30 -11
- data/app/views/plan_my_stuff/testing_project_items/new.html.erb +10 -0
- data/app/views/plan_my_stuff/testing_project_items/results/new.html.erb +20 -0
- data/app/views/plan_my_stuff/testing_projects/edit.html.erb +5 -0
- data/app/views/plan_my_stuff/testing_projects/new.html.erb +5 -0
- data/app/views/plan_my_stuff/testing_projects/partials/_form.html.erb +40 -0
- data/app/views/plan_my_stuff/testing_projects/partials/_item.html.erb +52 -0
- data/app/views/plan_my_stuff/testing_projects/partials/items/_form.html.erb +36 -0
- data/app/views/plan_my_stuff/testing_projects/show.html.erb +65 -0
- data/config/routes.rb +43 -15
- data/lib/generators/plan_my_stuff/install/templates/initializer.rb +302 -20
- data/lib/plan_my_stuff/application_record.rb +158 -1
- data/lib/plan_my_stuff/approval.rb +88 -0
- data/lib/plan_my_stuff/archive/sweep.rb +85 -0
- data/lib/plan_my_stuff/archive.rb +12 -0
- data/lib/plan_my_stuff/attachment.rb +83 -0
- data/lib/plan_my_stuff/attachment_uploader.rb +245 -0
- data/lib/plan_my_stuff/aws_sns_simulator.rb +116 -0
- data/lib/plan_my_stuff/base_metadata.rb +25 -28
- data/lib/plan_my_stuff/base_project.rb +502 -0
- data/lib/plan_my_stuff/base_project_extractions/graphql_hydration.rb +186 -0
- data/lib/plan_my_stuff/base_project_item.rb +588 -0
- data/lib/plan_my_stuff/base_project_metadata.rb +16 -0
- data/lib/plan_my_stuff/cache.rb +197 -0
- data/lib/plan_my_stuff/client.rb +139 -64
- data/lib/plan_my_stuff/comment.rb +225 -100
- data/lib/plan_my_stuff/comment_metadata.rb +68 -5
- data/lib/plan_my_stuff/configuration.rb +459 -28
- data/lib/plan_my_stuff/custom_fields.rb +96 -12
- data/lib/plan_my_stuff/engine.rb +14 -2
- data/lib/plan_my_stuff/errors.rb +65 -5
- data/lib/plan_my_stuff/graphql/queries.rb +454 -0
- data/lib/plan_my_stuff/issue.rb +1097 -166
- data/lib/plan_my_stuff/issue_extractions/approvals.rb +370 -0
- data/lib/plan_my_stuff/issue_extractions/links.rb +525 -0
- data/lib/plan_my_stuff/issue_extractions/viewers.rb +75 -0
- data/lib/plan_my_stuff/issue_extractions/waiting.rb +171 -0
- data/lib/plan_my_stuff/issue_field.rb +126 -0
- data/lib/plan_my_stuff/issue_field_translation.rb +67 -0
- data/lib/plan_my_stuff/issue_field_value_set.rb +68 -0
- data/lib/plan_my_stuff/issue_metadata.rb +132 -21
- data/lib/plan_my_stuff/label.rb +100 -13
- data/lib/plan_my_stuff/link.rb +144 -0
- data/lib/plan_my_stuff/markdown.rb +13 -7
- data/lib/plan_my_stuff/metadata_parser.rb +51 -12
- data/lib/plan_my_stuff/notifications.rb +148 -0
- data/lib/plan_my_stuff/pipeline/completed_sweep.rb +46 -0
- data/lib/plan_my_stuff/pipeline/issue_linker.rb +62 -0
- data/lib/plan_my_stuff/pipeline/status.rb +40 -0
- data/lib/plan_my_stuff/pipeline/testing.rb +23 -0
- data/lib/plan_my_stuff/pipeline.rb +310 -0
- data/lib/plan_my_stuff/project.rb +63 -465
- data/lib/plan_my_stuff/project_item.rb +3 -409
- data/lib/plan_my_stuff/project_item_metadata.rb +55 -0
- data/lib/plan_my_stuff/project_metadata.rb +47 -0
- data/lib/plan_my_stuff/reminders/closer.rb +70 -0
- data/lib/plan_my_stuff/reminders/fire.rb +129 -0
- data/lib/plan_my_stuff/reminders/sweep.rb +54 -0
- data/lib/plan_my_stuff/reminders.rb +12 -0
- data/lib/plan_my_stuff/repo.rb +145 -0
- data/lib/plan_my_stuff/test_helpers.rb +265 -25
- data/lib/plan_my_stuff/testing_project.rb +292 -0
- data/lib/plan_my_stuff/testing_project_item.rb +218 -0
- data/lib/plan_my_stuff/testing_project_metadata.rb +94 -0
- data/lib/plan_my_stuff/user_resolver.rb +24 -3
- data/lib/plan_my_stuff/verifier.rb +10 -0
- data/lib/plan_my_stuff/version.rb +2 -2
- data/lib/plan_my_stuff/webhook_replayer.rb +292 -0
- data/lib/plan_my_stuff.rb +55 -20
- data/lib/tasks/plan_my_stuff.rake +331 -0
- metadata +99 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3993e1306f27793791833787c546d81a42ed7bdf23d1420a658ec3877acf284b
|
|
4
|
+
data.tar.gz: 4593de2a00ea81ad22d0d951e1a97eb858a3d26071510c42e2e1aab9b99ae0f8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a9e140d9c6371186961903c5251143a63f4bedb3c238fc2d2b69e25ef3263824bdeacf767494c46473a5c7e9560c50b057e9b82136505b3615bcacdc742b3b6c
|
|
7
|
+
data.tar.gz: f73cb36b19ced07d713ae6e1aee02ab314292b3410d8b14d160e2156ceedd4a202f2fcecff7f67b61d25c93887bbc7e694f4415b89bab1203faa1e8bf7d7566c
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
Official release.
|
|
6
|
+
|
|
7
|
+
### Breaking
|
|
8
|
+
|
|
9
|
+
- `MetadataParser.parse` no longer recognizes the legacy `<!-- pms-metadata:... -->` HTML-comment format.
|
|
10
|
+
Bodies written before 0.17.0 that have not been re-saved will now be returned as plain body text with
|
|
11
|
+
empty metadata. The deprecation warning emitted by 0.17.0+ has been removed along with the legacy
|
|
12
|
+
pattern.
|
|
13
|
+
- Removed the deprecated `IssueMetadata#priority_list`, `#priority_list=`, `#priority_list?`,
|
|
14
|
+
`#priority_list_priority`, and `#priority_list_priority=` accessors, along with the legacy-write forwarding
|
|
15
|
+
that turned `metadata.priority_list = true` into `Priority List` / `Priority List Priority` issue-field writes
|
|
16
|
+
on `save!` / `update!` / `create!`. Use `Issue#priority_list?` / `#priority_list_priority` for reads and
|
|
17
|
+
`Issue#add_to_priority_list!(priority: N)` / `#remove_from_priority_list!` for writes (closes #57).
|
|
18
|
+
- `CommentMetadata` no longer parses the legacy `{filename, url}` attachment shape into structured fields.
|
|
19
|
+
Entries must now carry the `{filename, owner, repo, sha, path}` shape; legacy entries that were never
|
|
20
|
+
re-saved are dropped as malformed. The `LEGACY_URL_REGEXES` / `LEGACY_ATTACHMENT_DEPRECATION_MESSAGE`
|
|
21
|
+
constants and the migrate-on-write deprecation warning have been removed.
|
|
22
|
+
|
|
23
|
+
## 0.30.0
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
|
|
27
|
+
- The AWS deployment-completed webhook now fires a single `pipeline_deployment_completed.plan_my_stuff` batch event
|
|
28
|
+
after the per-item sweep, carrying every item that actually transitioned (payload: `:project_items`, `:issue_numbers`,
|
|
29
|
+
`:commit_sha`). Per-item `pipeline_completed.plan_my_stuff` events still fire. The batch event is skipped when nothing
|
|
30
|
+
transitioned, giving subscribers (release-notes mailer, Slack summary, changelog generator) one clean
|
|
31
|
+
"deployment finished" signal without debouncing N per-item events (closes #97).
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
|
|
35
|
+
- `PlanMyStuff::Notifications.instrument` now accepts an `Array` resource. The payload key is the pluralized element
|
|
36
|
+
key (a batch of project items keys as `:project_items`, a batch of issues as `:issues`), so batch events carry a full
|
|
37
|
+
set under one key.
|
|
38
|
+
- `PlanMyStuff::Pipeline.instrument` now accepts an `Array` of items for a batch event; the payload carries
|
|
39
|
+
`:issue_numbers` (the linked number of every item) in place of the single-item `:issue_number`.
|
|
40
|
+
|
|
41
|
+
## 0.29.0
|
|
42
|
+
|
|
43
|
+
### Changed
|
|
44
|
+
|
|
45
|
+
- `Pipeline.complete_deployment!` now sets the linked issue's `Issue Status` field to `Fixed` on the auto-complete
|
|
46
|
+
success path (alongside moving the item to `Completed`). Gated on `config.issue_fields_enabled`, so completion still
|
|
47
|
+
succeeds when issue fields are disabled. The auto-complete-off early return is unchanged (closes #96).
|
|
48
|
+
|
|
49
|
+
## 0.28.0
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
|
|
53
|
+
- `Issue.list_page_info(...)` returns a `PlanMyStuff::Issue::PageInfo` value object exposing `.issues`, `.page`,
|
|
54
|
+
`.per_page`, `.has_next?`, and `.has_prev?`. `Issue.list` now delegates to it; return type unchanged
|
|
55
|
+
(`Array<Issue>`). Closes #63.
|
|
56
|
+
|
|
57
|
+
## 0.27.0
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- `PlanMyStuff::Issue#mark_responded!(user)` - stamps `metadata.responded_at` on the first support-user engagement of
|
|
62
|
+
any kind. No-ops when the user is blank, not a support user, the issue isn't a PMS issue, or `responded_at` is
|
|
63
|
+
already set.
|
|
64
|
+
|
|
65
|
+
### Changed
|
|
66
|
+
|
|
67
|
+
- `Pipeline.take!` and the `issues.assigned` webhook now stamp `metadata.responded_at` on first support engagement
|
|
68
|
+
(was previously only set by the first support comment) (closes #60).
|
|
69
|
+
|
|
70
|
+
## 0.26.0
|
|
71
|
+
|
|
72
|
+
### Added
|
|
73
|
+
|
|
74
|
+
- `PlanMyStuff::Issue#awaiting_reply?` - returns `true` when the issue's `Issue Status` field is `Waiting on Reply`.
|
|
75
|
+
- `config.issue_field_names` (canonical field name => consumer field name) and `config.issue_field_values` (canonical
|
|
76
|
+
field name => `{ canonical value => consumer value }`) let a consuming org rename the native Issue Fields / option
|
|
77
|
+
labels the gem refers to internally. Translation runs via the new `PlanMyStuff::IssueFieldTranslation` module:
|
|
78
|
+
canonical => consumer on writes and filters (`set_issue_fields!`, `Issue.list` / `.count` `issue_fields:` +
|
|
79
|
+
`priority_list:`), consumer => canonical on reads (`Issue#issue_fields`), so internal comparisons like
|
|
80
|
+
`awaiting_reply?` / `priority_list?` keep working regardless of the org's naming. Unmapped names / values pass
|
|
81
|
+
through unchanged (identity fallback, mirroring `config.pipeline_statuses`).
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- The waiting/inactivity lifecycle methods now write the native `Issue Status` issue field alongside their existing
|
|
86
|
+
label/metadata changes (gated on `config.issue_fields_enabled`): `enter_waiting_on_user!` sets `Waiting on Reply`,
|
|
87
|
+
`clear_waiting_on_user!` sets `Open`, and `reopen_by_reply!` sets `Reopened`. No-op when `issue_fields_enabled` is
|
|
88
|
+
`false`.
|
|
89
|
+
|
|
90
|
+
## 0.25.0
|
|
91
|
+
|
|
92
|
+
### Added
|
|
93
|
+
|
|
94
|
+
- `PlanMyStuff::Pipeline.clear_testing!(project_item, user: nil)` - reverses `request_testing!` by writing the
|
|
95
|
+
`:inactive` Testing field value. Fires `pipeline_testing_cleared.plan_my_stuff` with `field_name`, `value`,
|
|
96
|
+
`user` payload.
|
|
97
|
+
- `PlanMyStuff::Issues::TestingsController` + `POST/DELETE /issues/:issue_id/testing` route (gated on
|
|
98
|
+
`config.pipeline_enabled`). Backs new "Request testing" / "Clear testing" buttons on the issue show view
|
|
99
|
+
(closes #52).
|
|
100
|
+
|
|
101
|
+
## 0.24.0
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
|
|
105
|
+
- `PlanMyStuff::Issue.list` and `PlanMyStuff::Issue.count` now accept `issue_type:` (String / Symbol) and
|
|
106
|
+
`issue_fields:` (Hash keyed by display name) filter kwargs. `issue_type:` resolves symbol nicknames through
|
|
107
|
+
`ISSUE_TYPE_NICKNAMES` and `config.issue_types`; Arrays raise `ArgumentError` since GitHub's REST `type` param
|
|
108
|
+
and Search `type:` qualifier each accept only one value. `issue_fields:` accepts scalar (equality) or `Range`
|
|
109
|
+
(date / numeric bounds -- inclusive
|
|
110
|
+
`..` -> `>=`/`<=`, exclusive `...` -> `>=`/`<`, beginless / endless ranges drop the unbounded side) values and ANDs
|
|
111
|
+
multiple constraints together. Composes with the existing `priority_list:` filter into the same
|
|
112
|
+
`issue_field_values` (REST) / `field.<slug>:` (Search) qualifier list. Search-API calls flip
|
|
113
|
+
`advanced_search=true` when any field qualifier is present. `issue_fields:` raises
|
|
114
|
+
`IssueFieldsNotEnabledError` when `config.issue_fields_enabled` is `false` (closes #54).
|
|
115
|
+
|
|
116
|
+
## 0.23.1
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- `PlanMyStuff::UserResolver.from_github_login(login)` - inverse of `config.github_login_for`. Returns the
|
|
121
|
+
resolved user object whose configured GitHub login matches `login`, or `nil` when `login` is blank or
|
|
122
|
+
unmapped.
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
|
|
126
|
+
- `Webhooks::GithubController` now forwards the actor through to `Pipeline.take!`'s `user:` kwarg from
|
|
127
|
+
`handle_issue_assigned` (using `assignee.login`) and `handle_draft_opened` (using the PR author). The
|
|
128
|
+
resolved user lands on the `pipeline_started.plan_my_stuff` notification payload.
|
|
129
|
+
- `Issues::TakesController#create` now forwards `pms_current_user` to `Pipeline.take!`'s `user:` kwarg.
|
|
130
|
+
|
|
131
|
+
## 0.23.0
|
|
132
|
+
|
|
133
|
+
### Added
|
|
134
|
+
|
|
135
|
+
- `PlanMyStuff::Pipeline.take!` and `PlanMyStuff::Pipeline.request_testing!` now accept a `user:` kwarg
|
|
136
|
+
that is forwarded onto the `pipeline_started.plan_my_stuff` / `pipeline_testing.plan_my_stuff`
|
|
137
|
+
`ActiveSupport::Notifications` payload. Defaults to `nil`, falling back to
|
|
138
|
+
`config.current_user` via `PlanMyStuff::Notifications.resolve_current_user`.
|
|
139
|
+
|
|
140
|
+
## 0.22.0
|
|
141
|
+
|
|
142
|
+
### Added
|
|
143
|
+
|
|
144
|
+
- `Issue#add_to_priority_list!(priority:)` and `Issue#remove_from_priority_list!` - first-class setters that
|
|
145
|
+
mirror the `#priority_list?` / `#priority_list_priority` readers. Each writes both `Priority List` and
|
|
146
|
+
`Priority List Priority` in a single mutation so the two fields cannot drift apart (closes #80).
|
|
147
|
+
|
|
148
|
+
### Changed
|
|
149
|
+
|
|
150
|
+
- `IssueMetadata#priority_list` / `#priority_list_priority` deprecation message now points callers at the new
|
|
151
|
+
`Issue#add_to_priority_list!` / `#remove_from_priority_list!` pair instead of raw `set_issue_fields!`.
|
|
152
|
+
|
|
153
|
+
## 0.21.1
|
|
154
|
+
|
|
155
|
+
### Added
|
|
156
|
+
|
|
157
|
+
- `config.eager_load_controllers_on_boot` (default `false`). When `true`, the engine eager-loads
|
|
158
|
+
`app/controllers/` in `after_initialize` so consuming apps with `eager_load = false` (dev mode) see
|
|
159
|
+
`PlanMyStuff::*Controller` constants without having to reference them first. Opt in if the host app
|
|
160
|
+
probes engine controllers via `defined?`, e.g. `defined?(PlanMyStuff::Issues::TakesController)` would
|
|
161
|
+
otherwise return `nil` until something triggered Zeitwerk autoload. Falls back to `Kernel#require` on
|
|
162
|
+
Zeitwerk < 2.6.2 (which lacks `eager_load_dir`).
|
|
163
|
+
|
|
164
|
+
## 0.21.0
|
|
165
|
+
|
|
166
|
+
### Breaking
|
|
167
|
+
|
|
168
|
+
- `PMS::Attachment` no longer accepts/stores a single `url:` attribute. Construct with explicit
|
|
169
|
+
`filename:`, `owner:`, `repo:`, `sha:`, `path:` instead; `#url` is now a derived method that returns the
|
|
170
|
+
GitHub blob viewer URL (`https://github.com/{owner}/{repo}/blob/{sha}/{path}`) rather than the
|
|
171
|
+
`raw.githubusercontent.com` URL. `#to_h` emits the structured fields and no longer includes a `url` key.
|
|
172
|
+
Persisted comment metadata in the legacy `{filename, url}` shape is migrated on read and rewritten in the
|
|
173
|
+
new shape on next save (closes #70).
|
|
174
|
+
|
|
175
|
+
### Added
|
|
176
|
+
|
|
177
|
+
- Comment bodies now render a visible `<details><summary>attachments (N)</summary>` block listing each
|
|
178
|
+
attachment as a markdown link to its blob URL, between the `pms-metadata` block and the user body. The
|
|
179
|
+
parser strips this block on read so round-trips stay clean.
|
|
180
|
+
|
|
181
|
+
## 0.20.0
|
|
182
|
+
|
|
183
|
+
### Breaking
|
|
184
|
+
|
|
185
|
+
- `priority_list` and `priority_list_priority` keys removed from `IssueMetadata` serialization. Existing issues
|
|
186
|
+
migrate to the GitHub Issue Field equivalents (`Priority List`, `Priority List Priority`) on their next save.
|
|
187
|
+
|
|
188
|
+
### Added
|
|
189
|
+
|
|
190
|
+
- `Issue#priority_list?` and `Issue#priority_list_priority` read the corresponding issue field values directly.
|
|
191
|
+
- `Issue.priority_list(repo:, state:, labels:, page:, per_page:)` convenience method delegates to
|
|
192
|
+
`Issue.list(priority_list: true, ...)`.
|
|
193
|
+
- `Issue.list` and `Issue.count` accept `priority_list:` for server-side filtering via the GitHub issue fields
|
|
194
|
+
API (passes `priority_list: false` raises `ArgumentError` -- the API has no negation qualifier).
|
|
195
|
+
|
|
196
|
+
### Deprecated
|
|
197
|
+
|
|
198
|
+
- `IssueMetadata#priority_list`, `#priority_list=`, `#priority_list?`, `#priority_list_priority`, and
|
|
199
|
+
`#priority_list_priority=` emit deprecation warnings on each read/write. Legacy writes forward to the issue
|
|
200
|
+
field on `Issue#save!` / `#update!` / `Issue.create!`. The accessors will be removed in 1.0.0.
|
|
201
|
+
|
|
202
|
+
## 0.19.0
|
|
203
|
+
|
|
204
|
+
### Added
|
|
205
|
+
|
|
206
|
+
- Every controller action now yields its primary object to a block when subclassed, so consumers can do
|
|
207
|
+
`super do |obj| ... end` to wedge in audit-log / instrumentation without rewriting the action. Webhook
|
|
208
|
+
controllers yield `(payload, result)`. See [CONFIGURATION.md](CONFIGURATION.md).
|
|
209
|
+
|
|
210
|
+
## 0.18.0
|
|
211
|
+
|
|
212
|
+
### Breaking
|
|
213
|
+
|
|
214
|
+
- `PMS::Issue#to_param` now returns `"Nickname-number"` (e.g. `"Rawr-1234"`) instead of the default ActiveModel id.
|
|
215
|
+
Single-issue URLs change from `/issues/1234?repo=rawr` to `/issues/Rawr-1234`. Consuming apps using
|
|
216
|
+
`youtrack_issue_path(@issue)` work natively; any hand-rolled URLs that passed `@issue.number` plus a `repo:`
|
|
217
|
+
query param must switch to `@issue` (or `@issue.to_param`). The mounted engine's controllers and views have
|
|
218
|
+
been updated to the new shape, as has the markdown link embedded in the GitHub issue body via
|
|
219
|
+
`Issue#user_link`.
|
|
220
|
+
|
|
221
|
+
### Added
|
|
222
|
+
|
|
223
|
+
- `config.repo_nicknames` (default `{}`) -- Symbol-keyed map from repo key to the human-readable label used as
|
|
224
|
+
the `Issue#to_param` prefix. Missing keys fall back to `key.to_s.titleize`, so `:rawr` -> `"Rawr"` is free;
|
|
225
|
+
only divergent ones (e.g. `safety: 'Compliance'`) need an entry.
|
|
226
|
+
- `Configuration#repo_nickname_for(key)` accessor, `Repo#nickname`, and `Repo.from_nickname!` for the inverse
|
|
227
|
+
lookup used by `Issue.from_param`.
|
|
228
|
+
- `Issue#to_param` and `Issue.from_param` -- the latter parses `"Nickname-1234"` back into `[Repo, Integer]`.
|
|
229
|
+
- `Issue.find` first arg now accepts a nickname-id String (e.g. `"Rawr-1234"`) in addition to Integer / digit-
|
|
230
|
+
String + `repo:` kwarg. The nickname form ignores `repo:`.
|
|
231
|
+
|
|
232
|
+
## 0.17.0
|
|
233
|
+
|
|
234
|
+
### Added
|
|
235
|
+
|
|
236
|
+
- `PlanMyStuff.deprecator` returns a gem-scoped `ActiveSupport::Deprecation` instance.
|
|
237
|
+
Consuming apps can silence, filter, or re-route PMS deprecation warnings independently
|
|
238
|
+
of Rails' own deprecator.
|
|
239
|
+
|
|
240
|
+
### Changed
|
|
241
|
+
|
|
242
|
+
- Issue, comment, and project-readme metadata is now stored in a visible `<details>` block
|
|
243
|
+
with a JSON code fence instead of a hidden HTML comment. GitHub renders the block in-page
|
|
244
|
+
so the metadata is inspectable without opening the body editor (closes #58).
|
|
245
|
+
`MetadataParser.parse` still accepts the legacy `<!-- pms-metadata:... -->` format and
|
|
246
|
+
emits a deprecation warning when it sees one; pre-0.17.0 bodies keep parsing and
|
|
247
|
+
re-serialize to the new format on their next write. Legacy detection will be removed
|
|
248
|
+
in 1.0.0.
|
|
249
|
+
|
|
250
|
+
## 0.16.0
|
|
251
|
+
|
|
252
|
+
### Added
|
|
253
|
+
|
|
254
|
+
- `PlanMyStuff::Issue.count(repo:, state:, labels:)` returns the total count of matching issues via the
|
|
255
|
+
GitHub Search API in a single request, without paginating full issue payloads. Mirrors `Issue.list`
|
|
256
|
+
kwargs (minus `page`/`per_page`); returns an `Integer`. Excludes PRs server-side via the `is:issue`
|
|
257
|
+
qualifier.
|
|
258
|
+
|
|
259
|
+
## 0.15.0
|
|
260
|
+
|
|
261
|
+
### Breaking
|
|
262
|
+
|
|
263
|
+
- `ActiveSupport::Notifications` events renamed to follow Rails' convention (event first, library
|
|
264
|
+
last). Subscribers matching the old `plan_my_stuff.*` prefix must switch to `*.plan_my_stuff`.
|
|
265
|
+
|
|
266
|
+
| Old | New |
|
|
267
|
+
|----------------------------------------------|----------------------------------------------|
|
|
268
|
+
| `plan_my_stuff.issue.created` | `issue_created.plan_my_stuff` |
|
|
269
|
+
| `plan_my_stuff.issue.updated` | `issue_updated.plan_my_stuff` |
|
|
270
|
+
| `plan_my_stuff.issue.closed` | `issue_closed.plan_my_stuff` |
|
|
271
|
+
| `plan_my_stuff.issue.reopened` | `issue_reopened.plan_my_stuff` |
|
|
272
|
+
| `plan_my_stuff.issue.archived` | `issue_archived.plan_my_stuff` |
|
|
273
|
+
| `plan_my_stuff.issue.closed_inactive` | `issue_closed_inactive.plan_my_stuff` |
|
|
274
|
+
| `plan_my_stuff.issue.reopened_by_reply` | `issue_reopened_by_reply.plan_my_stuff` |
|
|
275
|
+
| `plan_my_stuff.issue.marked_duplicate` | `issue_marked_duplicate.plan_my_stuff` |
|
|
276
|
+
| `plan_my_stuff.issue.viewers_added` | `issue_viewers_added.plan_my_stuff` |
|
|
277
|
+
| `plan_my_stuff.issue.viewers_removed` | `issue_viewers_removed.plan_my_stuff` |
|
|
278
|
+
| `plan_my_stuff.issue.approval_requested` | `issue_approval_requested.plan_my_stuff` |
|
|
279
|
+
| `plan_my_stuff.issue.approval_granted` | `issue_approval_granted.plan_my_stuff` |
|
|
280
|
+
| `plan_my_stuff.issue.approval_revoked` | `issue_approval_revoked.plan_my_stuff` |
|
|
281
|
+
| `plan_my_stuff.issue.approval_rejected` | `issue_approval_rejected.plan_my_stuff` |
|
|
282
|
+
| `plan_my_stuff.issue.rejection_revoked` | `issue_rejection_revoked.plan_my_stuff` |
|
|
283
|
+
| `plan_my_stuff.issue.all_approved` | `issue_all_approved.plan_my_stuff` |
|
|
284
|
+
| `plan_my_stuff.issue.approvals_invalidated` | `issue_approvals_invalidated.plan_my_stuff` |
|
|
285
|
+
| `plan_my_stuff.issue.reminder_due` | `issue_reminder_due.plan_my_stuff` |
|
|
286
|
+
| `plan_my_stuff.issue.link_reciprocal_failed` | `issue_link_reciprocal_failed.plan_my_stuff` |
|
|
287
|
+
| `plan_my_stuff.comment.created` | `comment_created.plan_my_stuff` |
|
|
288
|
+
| `plan_my_stuff.comment.updated` | `comment_updated.plan_my_stuff` |
|
|
289
|
+
| `plan_my_stuff.label.added` | `label_added.plan_my_stuff` |
|
|
290
|
+
| `plan_my_stuff.label.removed` | `label_removed.plan_my_stuff` |
|
|
291
|
+
| `plan_my_stuff.project_item.added` | `project_item_added.plan_my_stuff` |
|
|
292
|
+
| `plan_my_stuff.project_item.removed` | `project_item_removed.plan_my_stuff` |
|
|
293
|
+
| `plan_my_stuff.project_item.assigned` | `project_item_assigned.plan_my_stuff` |
|
|
294
|
+
| `plan_my_stuff.project_item.status_changed` | `project_item_status_changed.plan_my_stuff` |
|
|
295
|
+
| `plan_my_stuff.pipeline.<status>` | `pipeline_<status>.plan_my_stuff` |
|
|
296
|
+
|
|
297
|
+
Rationale: aligns with `sql.active_record`, `process_action.action_controller`, etc. and lets
|
|
298
|
+
subscribers match "everything from PMS" via the standard suffix-regex (`/\.plan_my_stuff$/`).
|
|
299
|
+
|
|
300
|
+
## 0.14.0
|
|
301
|
+
|
|
302
|
+
### Added
|
|
303
|
+
|
|
304
|
+
- `Repo.resolve!` now treats a String matching a configured repo key (e.g. `"dummy"` when
|
|
305
|
+
`config.repos[:dummy]` is set) as that key, returning a Repo with `key:` populated.
|
|
306
|
+
Previously only Symbols hit the key lookup; strings always went through `"Org/Repo"`
|
|
307
|
+
parsing and raised on names without a slash. This prevents the need to call `to_sym` from the consuming app
|
|
308
|
+
|
|
309
|
+
## 0.13.0
|
|
310
|
+
|
|
311
|
+
### Changed
|
|
312
|
+
|
|
313
|
+
- Internal: gem now autoloads `lib/plan_my_stuff/**` via Zeitwerk
|
|
314
|
+
(already shipped by railties - no new dep). All `require_relative`
|
|
315
|
+
boilerplate in the gem's lib tree is gone. The gem entry retains two
|
|
316
|
+
explicit `require_relative`s for files that fall outside the autoload
|
|
317
|
+
model: `errors.rb` (defines several sibling error classes) and
|
|
318
|
+
`engine.rb` (must register with Rails at load time).
|
|
319
|
+
|
|
320
|
+
## 0.12.0
|
|
321
|
+
|
|
322
|
+
### Added
|
|
323
|
+
|
|
324
|
+
- `PlanMyStuff::IssueField` for org-level GitHub Issue Field definitions (public preview).
|
|
325
|
+
Exposes `.list`, `.find` (case-insensitive), and `#option_id_for!` for resolving
|
|
326
|
+
single-select option names.
|
|
327
|
+
- `PlanMyStuff::Issue#issue_fields` returns a hash-like `IssueFieldValueSet` view of the
|
|
328
|
+
field values on an issue. Values are coerced to native types (`Date` for date fields,
|
|
329
|
+
`Float` for numbers, the option name `String` for single-selects).
|
|
330
|
+
- `PlanMyStuff::Issue#set_issue_fields!(updates)` writes one or more field values in a
|
|
331
|
+
single GraphQL mutation; passing `nil` as a value clears the field.
|
|
332
|
+
- `issue_fields:` kwarg on `Issue.create!`, `Issue.update!`, `Issue#save!`, and
|
|
333
|
+
`Issue#update!` so callers can set field values inline with create/update instead of
|
|
334
|
+
following up with an explicit `set_issue_fields!` call.
|
|
335
|
+
- `Configuration#issue_fields_enabled` (default `true`, opt-out). Set to `false` if your
|
|
336
|
+
org has not been admitted to the Issue Fields preview - with the flag off,
|
|
337
|
+
`Issue#issue_fields` returns an empty set and the write paths raise
|
|
338
|
+
`IssueFieldsNotEnabledError` instead of letting a raw GraphQL error surface.
|
|
339
|
+
|
|
340
|
+
## 0.11.0
|
|
341
|
+
|
|
342
|
+
### Added
|
|
343
|
+
|
|
344
|
+
- `PlanMyStuff::Attachment` value object (`filename`, `url`) and
|
|
345
|
+
`CommentMetadata#attachments`. PMS now owns attachment storage:
|
|
346
|
+
`Comment.create!` accepts an `attachments:` kwarg of uploaded-file
|
|
347
|
+
objects responding to `#path` and `#original_filename` (e.g.
|
|
348
|
+
Rails `ActionDispatch::Http::UploadedFile`), `String`/`Pathname`
|
|
349
|
+
paths to local files, or pre-built `PlanMyStuff::Attachment`
|
|
350
|
+
instances. Each file is committed to the shared attachment repo
|
|
351
|
+
(`config.attachment_repo`, default `'pms-attachments'`, under
|
|
352
|
+
`config.organization`) on `config.main_branch` at
|
|
353
|
+
`<repo_key>/issue-<N>/<uuid>.<ext>`; the resulting SHA-pinned
|
|
354
|
+
`raw.githubusercontent.com` permalink is stored in metadata as a
|
|
355
|
+
`PlanMyStuff::Attachment(filename:, url:)`. The attachment repo
|
|
356
|
+
must exist; the uploader does not create it. Malformed metadata
|
|
357
|
+
entries are silently dropped on parse, matching existing `links`
|
|
358
|
+
/ `approvals` behavior on `IssueMetadata`.
|
|
359
|
+
- `config.attachment_repo` (default `'pms-attachments'`) names the
|
|
360
|
+
bare repo under `config.organization` that stores uploaded
|
|
361
|
+
attachment binaries.
|
|
362
|
+
- `PlanMyStuff::AttachmentUploader.upload_all!(repo:,
|
|
363
|
+
issue_number:, files:)` is the underlying uploader; called
|
|
364
|
+
internally by `Comment.create!` but also usable directly by apps
|
|
365
|
+
that want to upload before constructing a comment. Pre-built
|
|
366
|
+
`Attachment` instances pass through without re-uploading.
|
|
367
|
+
- `Issue.create!` accepts an `attachments:` kwarg, forwarded to the
|
|
368
|
+
body-comment `Comment.create!` call so attachments posted with a
|
|
369
|
+
new issue are recorded on (and uploaded for) the body comment.
|
|
370
|
+
- `PlanMyStuff::Attachment#download_to(path = nil)` fetches the file
|
|
371
|
+
via the GitHub Contents API (so it works on private repos) and
|
|
372
|
+
writes the bytes to disk. Defaults `path` to
|
|
373
|
+
`File.join(Dir.tmpdir, filename)` and returns the path written to.
|
|
374
|
+
|
|
375
|
+
### Documented
|
|
376
|
+
|
|
377
|
+
- `designs/g9/` documents the design pivot from inline-base64 (body
|
|
378
|
+
size capped) through sibling-repo (rejected) to the chosen
|
|
379
|
+
side-branch approach.
|
|
380
|
+
|
|
381
|
+
## 0.10.5
|
|
382
|
+
|
|
383
|
+
### Added
|
|
384
|
+
|
|
385
|
+
- `config.parent_controller` (default `'::ApplicationController'`) lets consuming apps that don't use the
|
|
386
|
+
`ApplicationController` name (e.g. `ActionController::Base`, `RawrApplicationController`) tell the engine
|
|
387
|
+
what to inherit from. The `plan_my_stuff:verify` rake task now reports whether the configured class
|
|
388
|
+
resolves.
|
|
389
|
+
|
|
390
|
+
### Fixed
|
|
391
|
+
|
|
392
|
+
- Example config option showed `url_options = Rails.application.config.action_mailer.default_url_options`. Now it shows
|
|
393
|
+
`url_options = Rails.application.routes.default_url_options`
|
|
394
|
+
|
|
395
|
+
## 0.10.4
|
|
396
|
+
|
|
397
|
+
### Changed
|
|
398
|
+
|
|
399
|
+
- Internal: unit specs now use VCR cassettes against `BrandsInsurance/ubiquitous-adventure` instead of
|
|
400
|
+
`instance_double(Octokit::Client)`. No effect on consuming apps.
|
|
401
|
+
|
|
402
|
+
### Removed
|
|
403
|
+
|
|
404
|
+
- ETag caching on `Issue.list`. The cache key included `state`, `labels`, `page`, and `per_page`,
|
|
405
|
+
so an etag stored under one combo never matched a request with different params - the cache wrote
|
|
406
|
+
on every call and effectively never hit. `Issue.list` now always issues a fresh GitHub request.
|
|
407
|
+
`Comment.list` keeps ETag caching (param surface is just `issue` + `pms_only`).
|
|
408
|
+
`PlanMyStuff::Cache.read_list` / `write_list` remain available for `Comment.list`.
|
|
409
|
+
|
|
410
|
+
## 0.10.3
|
|
411
|
+
|
|
412
|
+
### Added
|
|
413
|
+
|
|
414
|
+
- `BaseProjectItem#assignees` returns the GitHub logins of users assigned to the underlying Issue,
|
|
415
|
+
PullRequest, or DraftIssue. Populated from the `FIND_PROJECT` GraphQL response (the query was extended
|
|
416
|
+
with `assignees(first: 10)` on each content fragment).
|
|
417
|
+
|
|
418
|
+
## 0.10.2
|
|
419
|
+
|
|
420
|
+
### Changed
|
|
421
|
+
|
|
422
|
+
- Nothing, just a version bump
|
|
423
|
+
|
|
424
|
+
## 0.10.1
|
|
425
|
+
|
|
426
|
+
### Changed
|
|
427
|
+
|
|
428
|
+
- Nothing, just a version bump
|
|
429
|
+
|
|
430
|
+
## 0.10.0
|
|
431
|
+
|
|
432
|
+
### Changed
|
|
433
|
+
|
|
434
|
+
- `Issue` slimmed from 1791 to 911 lines by extracting feature clusters into per-feature modules under a sibling
|
|
435
|
+
`PlanMyStuff::IssueExtractions::*` namespace, included into `Issue`. Public API unchanged (`issue.approve!`,
|
|
436
|
+
`issue.add_related!`, `issue.enter_waiting_on_user!`, `issue.add_viewers!`, etc. still resolve to the same methods).
|
|
437
|
+
- `PlanMyStuff::IssueExtractions::Approvals` - `lib/plan_my_stuff/issue_extractions/approvals.rb`
|
|
438
|
+
- `PlanMyStuff::IssueExtractions::Links` - `lib/plan_my_stuff/issue_extractions/links.rb`
|
|
439
|
+
- `PlanMyStuff::IssueExtractions::Waiting` - `lib/plan_my_stuff/issue_extractions/waiting.rb`
|
|
440
|
+
- `PlanMyStuff::IssueExtractions::Viewers` - `lib/plan_my_stuff/issue_extractions/viewers.rb`
|
|
441
|
+
- `BaseProject` slimmed from 661 to 504 lines by extracting GraphQL hydration helpers into
|
|
442
|
+
`PlanMyStuff::BaseProjectExtractions::GraphqlHydration` (`lib/plan_my_stuff/base_project_extractions/graphql_hydration.rb`),
|
|
443
|
+
included into `BaseProject`'s singleton class. `BaseProject.find` / `BaseProject.list` remain public entry points.
|
|
444
|
+
- Specs for `Issue` features now live alongside the modules at `spec/plan_my_stuff/issue_extractions/<feature>_spec.rb`.
|
|
445
|
+
|
|
446
|
+
## 0.9.0
|
|
447
|
+
|
|
448
|
+
### Breaking
|
|
449
|
+
|
|
450
|
+
- `config.should_send_request` and `config.job_classes` accessors — declared but never wired up. The request gateway that would honor them is deferred (see `requirements/09_request_gateway.md` and `designs/init/gem_mvp_deferred_notes.md`); they will return when the gateway lands
|
|
451
|
+
|
|
452
|
+
### Added
|
|
453
|
+
|
|
454
|
+
- `CONFIGURATION.md` is now available bundled with the gem
|
|
455
|
+
|
|
456
|
+
### Changed
|
|
457
|
+
|
|
458
|
+
- `config.repos` is now assignable as a whole hash (`config.repos = { atlas: 'Org/Atlas', autofill: 'Org/atlas-autofill-moz' }`) in addition to the existing `config.repos[:key] = '...'` form
|
|
459
|
+
- `Issue.create!` / `Issue.update!` `issue_type:` kwarg now accepts the Symbol nicknames (`'bug'`, `'feature'`, `'it_issue'`, `'other'`, `'performance'`, `'question'`, `'task'`) as Strings too, resolving them to the same canonical name
|
|
460
|
+
|
|
461
|
+
## 0.8.0
|
|
462
|
+
|
|
463
|
+
### Breaking
|
|
464
|
+
|
|
465
|
+
- Issue show "Take" button is now hidden when the issue already has assignees, and `Issues::TakesController#create` rejects the request with a flash error naming the existing assignee. Best-effort race guard for two users clicking Take simultaneously — without it, GitHub silently piles the second user on as a co-assignee.
|
|
466
|
+
- Guard lives in the controller, not `Pipeline.take!` itself, because webhook paths (`handle_issue_assigned`, `handle_projects_v2_item`, `handle_draft_opened`, `handle_converted_to_draft`) legitimately call `take!` on already-assigned issues
|
|
467
|
+
- `Issue#add_viewers` / `Issue#remove_viewers` renamed to `Issue#add_viewers!` / `Issue#remove_viewers!` for consistency with other mutating instance methods (`approve!`, `close!`, etc.)
|
|
468
|
+
- `Approval#status` extended to a 3-state model (`pending`, `approved`, `rejected`); `Approval` gains a `rejected_at` attribute serialized in `to_h` and the metadata blob. Existing approvals deserialize unchanged (`rejected_at` defaults to `nil`)
|
|
469
|
+
- `Issue#fully_approved?` now requires every approver to be `approved` — a single rejection blocks the gate until revoked. Previously equivalent to `pending_approvals.empty?`, which silently treated rejections as "done"
|
|
470
|
+
- `Issue#revoke_approval!` accepts either an `approved` or `rejected` source state (previously only `approved`); raises `ValidationError` when the target is still `pending`. Authorization error message updated to "another user's response"
|
|
471
|
+
|
|
472
|
+
### Added
|
|
473
|
+
|
|
474
|
+
- `CONFIGURATION.md` documents every `PlanMyStuff::Configuration` option grouped by concern; `README.md` Configuration section trimmed to the two required options plus a link
|
|
475
|
+
- Install generator's initializer template now includes the four pipeline options previously missing from it: `pipeline_testing_field_name`, `pipeline_testing_values`, `pipeline_completion_purge_enabled`, `pipeline_completion_ttl_hours`
|
|
476
|
+
- Project show "Remove from project" button (and `DELETE /projects/:project_id/items/:id` route on `ProjectItemsController`) lets the user remove an item from a project board without bouncing out to GitHub. Calls `ProjectItem#destroy!` which fires `plan_my_stuff.project_item.removed`
|
|
477
|
+
- Issue show "Release" button (and `DELETE /issues/:issue_id/take` route on `Issues::TakesController`) lets a dev who took an issue undo their assignment from the same view, without bouncing out to GitHub or the project board. When the current user is the sole assignee the issue's GitHub assignees are cleared and the project item is removed from the pipeline (`project_item.destroy!`); when other assignees remain the current user is unassigned via `project_item.assign!(remaining)` and the item stays on the project
|
|
478
|
+
- `config.import_access_token` classic PAT (requires `repo` scope) used exclusively for the Issues Import API (`golden-comet-preview`); fine-grained tokens are not supported by that endpoint. Optional — defaults to `nil`
|
|
479
|
+
- `Issue.import!(payloads)` POSTs an `Array<Hash>` (one POST per payload) to GitHub's "Import Issues" preview endpoint and returns one status hash per input. Each payload must include `:repo` plus the GitHub-shaped `:issue` / `:comments` keys; payloads are passed through unchanged otherwise
|
|
480
|
+
- `Issue.check_import!(import_id, repo:)` polls a previously-submitted import for its status
|
|
481
|
+
- `Issue#created_at` / `Comment#created_at` attributes hydrated from GitHub's `created_at` field
|
|
482
|
+
- `Issue#issue_type` reader hydrated from GitHub's native `type.name`. `Issue.create!` and `Issue.update!` accept an `issue_type:` kwarg as a String (passed through), Symbol shortcut (`:bug`, `:feature`, `:it_issue`, `:other`, `:performance`, `:question`, `:task`), or `nil`. On `update!`, omitting the kwarg leaves the type untouched; passing `nil` clears it
|
|
483
|
+
- `config.issue_types` Hash{String => String} maps canonical type names to org-specific display names so consuming apps can rename without touching call sites (e.g. `{ 'Feature' => 'Enhancement' }`); missing keys pass through unchanged
|
|
484
|
+
- `config.controller_rescue` Proc invoked from every user-facing controller `rescue` block (after the gem logs the error and stack trace) so consuming apps can forward swallowed errors to their monitoring service
|
|
485
|
+
- `Issue#reject!(user:)` symmetric with `approve!`; accepts either `pending` or `approved` source state and raises `ValidationError` when already rejected. Fires `plan_my_stuff.issue.approval_rejected` and, when the flip drops the issue out of `fully_approved?`, `approvals_invalidated(trigger: :rejected)`
|
|
486
|
+
- `Issue#approve!` now accepts either `pending` or `rejected` source state; raises `ValidationError` only on `approved -> approved`. Clears `rejected_at` on the rejected -> approved transition
|
|
487
|
+
- `Issue#rejected_approvals` reader returns the subset of approvers with `status == 'rejected'`
|
|
488
|
+
- New events: `plan_my_stuff.issue.approval_rejected` and `plan_my_stuff.issue.rejection_revoked` (the latter fires when revoking a rejection back to pending)
|
|
489
|
+
- Approvals partial renders a `Reject` button alongside `Approve` for pending approvers, a `rejected at <ts>` row, a parenthetical rejected count in the header, and a `Revoke` button for either non-pending state
|
|
490
|
+
|
|
491
|
+
## 0.7.0
|
|
492
|
+
|
|
493
|
+
### Added
|
|
494
|
+
|
|
495
|
+
- `Issue#user_link` returns the per-issue URL in the consuming app, computed from `config.issues_url_prefix` + issue number
|
|
496
|
+
|
|
497
|
+
### Changed
|
|
498
|
+
|
|
499
|
+
- GitHub issues created/updated by PMS now render a markdown link `[Org/Repo#number](user_link)` as the visible body (previously empty); skipped when `issues_url_prefix` is unset
|
|
500
|
+
|
|
501
|
+
## 0.6.0
|
|
502
|
+
|
|
503
|
+
### Breaking
|
|
504
|
+
|
|
505
|
+
- `Pipeline.submit!` removed; consuming apps that called it directly should switch to `ProjectItem.create!` + `Pipeline.take!`
|
|
506
|
+
- `Pipeline::Status::SUBMITTED` and `Pipeline::Status::TESTING` constants removed; `Status::ALL` no longer includes them
|
|
507
|
+
- `Pipeline.request_testing!` no longer moves the `Status` field — it now writes to a separate `Testing` single-select custom field on the pipeline project. The pipeline project must have a `Testing` field with `Testing` / `Not testing` options
|
|
508
|
+
- Active pipeline status set is now `Started -> In Review -> Ready for Release -> Release in Progress -> Completed`
|
|
509
|
+
|
|
510
|
+
### Added
|
|
511
|
+
|
|
512
|
+
- `Pipeline::Testing` module (`FIELD_NAME`, `VALUES`)
|
|
513
|
+
- `Pipeline::CompletedSweep` removes items from `Completed` after the configured TTL; driven by `RemindersSweepJob`
|
|
514
|
+
- `BaseProjectItem#update_single_select_field!` instance method
|
|
515
|
+
- `BaseProjectItem#updated_at` populated from GitHub's `updatedAt`
|
|
516
|
+
- `Issue#assignees` public reader
|
|
517
|
+
- `Pipeline.release_cycle_locked?` helper
|
|
518
|
+
- New config: `pipeline_testing_field_name`, `pipeline_testing_values`, `pipeline_completion_purge_enabled` (default `true`), `pipeline_completion_ttl_hours` (default `24`)
|
|
519
|
+
|
|
520
|
+
### Changed
|
|
521
|
+
|
|
522
|
+
- Assigning a dev to an issue now creates the project item and lands it at `Started` (was `Submitted`)
|
|
523
|
+
- Opening a PR as a draft adds the linked issue to the pipeline at `Started` and assigns the PR author when the issue has no assignees; already-pipelined items are not moved
|
|
524
|
+
- The assignment webhook no longer calls `assign!` on the project item — GitHub already records the assignment, and `assign!` could clobber co-assignees
|
|
525
|
+
|
|
526
|
+
### Removed
|
|
527
|
+
|
|
528
|
+
- `Pipeline.submit!` (see Breaking)
|
|
529
|
+
- `Pipeline::Status::SUBMITTED`, `Pipeline::Status::TESTING` (see Breaking)
|
|
530
|
+
|
|
531
|
+
### Fixed
|
|
532
|
+
|
|
533
|
+
- Closed issues no longer alter the pipeline on assign/unassign webhook events
|
|
534
|
+
- Items at `Ready for Release`, `Release in Progress`, or `Completed` are no longer removed when an unassign webhook fires
|
|
535
|
+
- Pending-approvals guard runs before `ProjectItem.create!` in the assignment flow so the webhook no longer leaves orphan items when `Pipeline.take!`'s approval guard would otherwise raise
|
|
536
|
+
|
|
537
|
+
### Documented
|
|
538
|
+
|
|
539
|
+
- `designs/pipeline_cleanup/plan.md` — full design + bug-to-fix mapping
|
|
540
|
+
- `requirements/08_release_pipeline.md` updated to reflect the new flow
|
|
541
|
+
- `requirements/tasks.md` — T-PC-001 added under Phase 14
|
|
542
|
+
|
|
543
|
+
## 0.5.1
|
|
544
|
+
|
|
545
|
+
### Fixed
|
|
546
|
+
|
|
547
|
+
- AWS webhook rejected SNS `SubscriptionConfirmation` and `UnsubscribeConfirmation` messages with 401; now signature-verified, logged, and acked with 200
|
|
548
|
+
|
|
549
|
+
## 0.5.0
|
|
550
|
+
|
|
551
|
+
### Added
|
|
552
|
+
|
|
553
|
+
- `post_install_message` in gemspec listing available rake tasks and generators
|
|
554
|
+
- `rake plan_my_stuff:install` and `rake plan_my_stuff:views` aliases for the Rails generators
|
|
555
|
+
|
|
556
|
+
### Fixed
|
|
557
|
+
|
|
558
|
+
- `TestingProjectItem.create!` left new items with a blank Test Status; now defaults to `Todo`
|
|
559
|
+
- `TestingProjectItem.create!` left new items with no Pass Mode; now defaults to `all`
|
|
560
|
+
|
|
561
|
+
## 0.4.0
|
|
562
|
+
|
|
563
|
+
- Full feature set release before PR
|
|
564
|
+
|
|
565
|
+
## 0.3.0
|
|
566
|
+
|
|
567
|
+
### Added
|
|
568
|
+
|
|
569
|
+
- Add `new`/`create`/`edit`/`update` routes for Projects
|
|
570
|
+
|
|
571
|
+
## 0.2.0
|
|
572
|
+
|
|
573
|
+
### Added
|
|
574
|
+
|
|
575
|
+
- Validate `config.custom_fields` on `create!`/`update!` actions
|
|
576
|
+
|
|
577
|
+
### Changes
|
|
578
|
+
|
|
579
|
+
- CodeRabbit improvements
|
|
580
|
+
|
|
581
|
+
## 0.1.2
|
|
582
|
+
|
|
583
|
+
### Fixed
|
|
584
|
+
|
|
585
|
+
- Issues' links were looking for the issue in the default repo with the same number
|
|
586
|
+
|
|
587
|
+
## 0.1.1
|
|
588
|
+
|
|
589
|
+
### Fixed
|
|
590
|
+
|
|
591
|
+
- Wrong changelog included in publish
|
|
592
|
+
|
|
593
|
+
## 0.1.0
|
|
594
|
+
|
|
595
|
+
- Initial Setup
|