Skip to content

Commit

Permalink
Merge pull request #27 from nverges/26-allow-manual-user-mapping-over…
Browse files Browse the repository at this point in the history
…rides

Allow manual user mapping overrides
  • Loading branch information
nverges authored Dec 5, 2024
2 parents 3b1faf0 + 15bfb53 commit 91039af
Show file tree
Hide file tree
Showing 42 changed files with 314 additions and 297 deletions.
262 changes: 166 additions & 96 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## Adding a new Import Source
# Adding a new Import Source

- Set `ENABLE_DETAILED_LOGGING=true` in `.env`

- `importSource` logic begins here. This is the value we'll use to swap between importers

```js
// src/import.mjs
// src/import.js
const extractedPivotalData = await pivotalFormatter({
team,
directory,
Expand All @@ -16,114 +16,184 @@ const extractedPivotalData = await pivotalFormatter({

- Using the `importSource` value in `import.mjs`, add logic to return a value other than `extractedPivotalData` (e.g., `extractedTrelloData`). A clever mechanism to manage future additions would be nice here.

- It should adhere to this format:
As long as your code generates a JSON output in this format, all data should migrate into Linear as expected. Key/value pairs may be ommitted if desired.

```json
{
"issues": [
- It should adhere to this format:

```json
{
"issues": [
{
"isRelease": true,
"iteration": 1,
"title": "Issue 1",
"id": "1",
"type": "release",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Dropdown menu doesn't close when clicking outside.",
"state": "unscheduled",
"priority": "p2 - Medium",
"labels": "foo, bar",
"requestedBy": "Samwise Gamgee",
"ownedBy": ["Frodo Baggins"],
"estimate": "3",
"comments": []
},
{
"isRelease": false,
"iteration": 1,
"title": "Becomes sub-issue of `Issue 1`",
"id": "2",
"type": "feature",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Enhance the login process for better user experience.",
"state": "in progress",
"priority": "p1 - High",
"labels": "ux",
"requestedBy": "Alice Johnson",
"ownedBy": ["Mike Johnson", "Tom Wilson"],
"estimate": "5",
"comments": ["Initial thoughts", "Need more details", "Final review"]
},
{
"isRelease": false,
"iteration": 2,
"title": "Is not a sub-issue",
"id": "3",
"type": "feature",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Enhance the login process for better user experience.",
"state": "in progress",
"priority": "p1 - High",
"labels": "login, logout",
"requestedBy": "Tony Hawk",
"ownedBy": ["Bob Evans"],
"estimate": "5",
"comments": ["Single comment"]
}
],
"aggregatedData": {
"userNames": [
"Samwise Gamgee",
"Frodo Baggins",
"Alice Johnson"
"Mike Johnson",
"Tom Wilson",
"Tony Hawk",
"Bob Evans",
],
"labels": [
{
"name": "foo",
"color": "#6C757D"
},
{
"isRelease": true,
"iteration": 1,
"title": "Issue 1",
"id": "1",
"type": "release",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Dropdown menu doesn't close when clicking outside.",
"state": "unscheduled",
"priority": "p2 - Medium",
"labels": "foo, bar",
"requestedBy": "Samwise Gamgee",
"ownedBy": ["Frodo Baggins"],
"estimate": "3",
"comments": []
"name": "bar",
"color": "#6C757D"
},
{
"isRelease": false,
"iteration": 1,
"title": "Becomes sub-issue of `Issue 1`",
"id": "2",
"type": "feature",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Enhance the login process for better user experience.",
"state": "in progress",
"priority": "p1 - High",
"labels": "ux",
"requestedBy": "Alice Johnson",
"ownedBy": ["Mike Johnson", "Tom Wilson"],
"estimate": "5",
"comments": ["Initial thoughts", "Need more details", "Final review"]
"name": "ux",
"color": "#6C757D"
},
{
"isRelease": false,
"iteration": 2,
"title": "Is not a sub-issue",
"id": "3",
"type": "feature",
"dueDate": "",
"createdAt": "",
"startsAt": "",
"endsAt": "",
"description": "Enhance the login process for better user experience.",
"state": "in progress",
"priority": "p1 - High",
"labels": "login, logout",
"requestedBy": "Tony Hawk",
"ownedBy": ["Bob Evans"],
"estimate": "5",
"comments": ["Single comment"]
"name": "login",
"color": "#007BFF"
}
],
"aggregatedData": {
"userNames": [
"Samwise Gamgee",
"Frodo Baggins",
"Alice Johnson"
"Mike Johnson",
"Tom Wilson",
"Tony Hawk",
"Bob Evans",
],
"labels": [
{
"name": "foo",
"color": "#6C757D"
},
{
"name": "bar",
"color": "#6C757D"
},
{
"name": "ux",
"color": "#6C757D"
},
{
"name": "login",
"color": "#007BFF"
}
{
"name": "logout",
"color": "#007BFF"
}
]
}
{
"name": "logout",
"color": "#007BFF"
}
]
}
```
}
```

- `isRelease` controls issues that are created as Release Issues (parent issues). In a Pivotal Tracker export, this is true if the value of the `Type` column is `release`.
- There's also a row called `Iteration` in a Pivotal Tracker export. It's an integer, and any issues with the same iteration number will be created as sub-issues under the corresponding release issue.
- `isRelease` controls issues that are created as Release Issues (parent issues). In a Pivotal Tracker export, this is true if the value of the `Type` column is `release`.
- There's also a row called `Iteration` in a Pivotal Tracker export. It's an integer, and any issues with the same iteration number will be created as sub-issues under the corresponding release issue.

#### Generic CSV

- You'll probably have to make some adjustments to logic related to directories depending on your folder structure
The current acceptable CSV format, as determined by Pivotal Tracker, is as follows:

```
Id,
Title,
Labels,
Iteration,
Iteration Start,
Iteration End,
Type,
Estimate,
Priority,
Current State,
Created at,
Accepted at,
Deadline,
Requested By,
Description,
URL,
Owned By,
Blocker,
Blocker Status,
Comment,
Comment,
Task,
Task Status,
Review Type,
Reviewer,
Review Status,
Pull Request,
Git Branch
```

- Order is irrelevant, but all casings must match exactly
- Comments must be formatted across multiple columns:

```
| Comment | Comment |
| ------------- | ----------- |
| Comment 1 | Comment 2 |
```

- `Owned By` may be formatted in a single column or across multiple columns:

- Single column

```
| Owned By |
|----------------|
| Samwise Gamgee, Frodo Baggins |
```
- Or in multiple columns:
```
| Owned By | Owned By |
| -------------- | ------------- |
| Samwise Gamgee | Frodo Baggins |
```
- You may add any other columns that you would like. This data will not be imported onto the Linear issue itself, but all columns WILL be added to the **Raw Pivotal Tracker Data** comment that's created on each comment.
- You'll have to make some adjustments to logic related to directories depending on your folder structure
- `src/csv/parse.js`
- `logger/logger.mjs`
- `src/files/find_attachments_in_folder.js`
- `src/csv/parse.js`
- File attachments must exist in a folder that matches the `Id` column in the csv
![alt text](image-3.png)
![alt text](image-4.png)
#### Generic JSON
Expand Down
50 changes: 24 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ CLI tool for migrating Pivotal Tracker projects to Linear via CSV export. Conver

### For Developers

- The codebase is structured to support additional importers reasonably easily (as of `v2.0.0`) See [Contributing Guide](./CONTRIBUTING.md) or contact me if you intend to add support for other platforms (e.g., Trello)
- This importer is currently only set up for a Pivotal Tracker. However you could alter your own CSV to adhere to the accepted format. See [Generic CSV](./CONTRIBUTING.md#generic-csv) for more information
- The codebase is structured to support building additional importers reasonably easily (as of `v2.0.0`). See [Contributing Guide](./CONTRIBUTING.md), open a PR, or contact me if you intend to add support for other platforms (e.g., Trello)

Built with [Linear SDK](https://github.com/linear/linear/tree/master/packages/sdk)

Expand Down Expand Up @@ -63,11 +64,11 @@ Built with [Linear SDK](https://github.com/linear/linear/tree/master/packages/sd

#### Comments

- Comments are imported with original metadata (author, timestamp) and content preserved. Each issue also includes a `Raw Pivotal Tracker Data` comment containing the complete CSV data for audit purposes.
- Comments are imported with original metadata (author, timestamp) and content preserved. Each issue also includes a `Raw Pivotal Tracker Data` comment containing the complete CSV data

#### Statuses

- The following Workflow Statuses will be created in the selected Team. This allows each Team to modify statuses at their own pace without affecting other Teams, and will avoid any naming conflicts with existing statuses.
- The following Workflow Statuses will be created in the selected Team. This allows each Team to modify statuses at their own pace without affecting other Teams, and will avoid any naming conflicts with existing statuses
- `pivotal - accepted`
- `pivotal - unscheduled`
- `pivotal - finished`
Expand All @@ -76,7 +77,7 @@ Built with [Linear SDK](https://github.com/linear/linear/tree/master/packages/sd

#### Labels

- The following Labels will be created in the selected Team. This allows each Team to modify labels at their own pace without affecting other Teams, and will avoid any naming conflicts with existing labels.
- The following Labels will be created in the selected Team. This allows each Team to modify labels at their own pace without affecting other Teams, and will avoid any naming conflicts with existing labels

- `pivotal-epic`
- `pivotal-release`
Expand Down Expand Up @@ -120,28 +121,8 @@ Linear Issues will be assigned a label with the corresponding Story Type (See [L
![alt text](image-2.png)

- For stories without owners:

- Story creator becomes the assignee

- User Map data is stored in `log/<team>/user_mapping.json`:
```json
{
"generated": "2024-01-01T00:00:00.000Z",
"mapping": {
"johndoe42": {
"linearId": "a1b2c3d4-e5f6-4321-9876-543210fedcba",
"linearName": "John Doe",
"linearEmail": "john.doe@acme.com"
},
"robotcoder99": {
"linearId": null,
"linearName": null,
"linearEmail": null,
"note": "No matching Linear user found (manual skip)"
}
}
}
```
- User Map data is stored in `log/<team>/user_mapping.json` (See [Logs](#logs)):

#### Subscribers

Expand Down Expand Up @@ -179,7 +160,24 @@ Linear Issues will be assigned a label with the corresponding Story Type (See [L

- Maps Pivotal Tracker usernames to Linear user accounts
- Used for automatic user matching in future imports
- See [Assignee](#assignee) section for example JSON structure
```json
{
"generated": "2024-01-01T00:00:00.000Z",
"mapping": {
"johndoe42": {
"linearId": "a1b2c3d4-e5f6-4321-9876-543210fedcba",
"linearName": "John Doe",
"linearEmail": "john.doe@acme.com"
},
"robotcoder99": {
"linearId": null,
"linearName": null,
"linearEmail": null,
"note": "No matching Linear user found (manual skip)"
}
}
}
```

- `successful_imports.csv`
- Tracks successfully imported Pivotal story IDs
Expand Down
Binary file added image-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 91039af

Please sign in to comment.