diff --git a/.github/workflows/migrate-work-items.yml b/.github/workflows/migrate-work-items.yml
index 043ee35..dca78ec 100644
--- a/.github/workflows/migrate-work-items.yml
+++ b/.github/workflows/migrate-work-items.yml
@@ -2,51 +2,51 @@ name: Migrate Work Items
on:
workflow_dispatch:
- inputs:
+ inputs:
ado-org:
- description: 'ado-org'
+ description: "ado-org"
required: true
- default: 'jjohanning0798'
+ default: "jjohanning0798"
ado-project:
- description: 'ado-project'
+ description: "ado-project"
required: true
- default: 'PartsUnlimited'
+ default: "PartsUnlimited"
ado_area_path:
- description: 'ADO area path to migrate - uses the UNDER operator'
+ description: "ADO area path to migrate - uses the UNDER operator"
required: true
- default: 'migrate'
+ default: "migrate"
ado_migrate_closed_workitems:
- description: 'Migrate closed work items'
+ description: "Migrate closed work items"
required: true
type: boolean
- default: 'true'
+ default: true
ado_production_run:
description: tag migrated work items with migrated-to-github and add discussion comment
required: true
type: boolean
- default: 'true'
+ default: true
gh-org:
- description: 'gh-org'
+ description: "gh-org"
required: true
- default: 'joshjohanning-org'
+ default: "joshjohanning-org"
gh-repo:
- description: 'gh-org'
+ description: "gh-org"
required: true
- default: 'migrate-ado-workitems'
+ default: "migrate-ado-workitems"
gh_update_assigned_to:
- description: 'Update Assigned To'
+ description: "Update Assigned To"
required: true
type: boolean
- default: 'true'
+ default: true
gh_assigned_to_user_suffix:
- description: 'EMU suffix'
+ description: "EMU suffix"
required: true
- default: '_corp'
+ default: "_corp"
gh_add_ado_comments:
- description: 'Add ADO Comments'
+ description: "Add ADO Comments"
required: true
type: boolean
- default: 'true'
+ default: true
jobs:
migrate:
@@ -54,25 +54,25 @@ jobs:
steps:
- uses: actions/checkout@main
-
+
- uses: tibdex/github-app-token@v1
id: get_installation_token
- with:
+ with:
app_id: 179484
installation_id: 23995058
private_key: ${{ secrets.PRIVATE_KEY }}
-
+
- name: run migration
shell: pwsh
run: |
# run migration script
-
+
# cleaning up bools
$ado_migrate_closed_workitems=$false
$ado_production_run=$false
$gh_update_assigned_to=$false
$gh_add_ado_comments=$false
-
+
if("${{ github.event.inputs.ado_migrate_closed_workitems }}" -eq "true") {
$ado_migrate_closed_workitems=$true
}
@@ -84,10 +84,9 @@ jobs:
if("${{ github.event.inputs.gh_update_assigned_to }}" -eq "true") {
$gh_update_assigned_to=$true
}
-
+
if("${{ github.event.inputs.gh_add_ado_comments }}" -eq "true") {
$gh_add_ado_comments=$true
}
-
+
./ado_workitems_to_github_issues.ps1 -ado_pat "${{ SECRETS.ADO_PAT }}" -ado_org "${{ github.event.inputs.ado-org }}" -ado_project "${{ github.event.inputs.ado-project }}" -ado_area_path "${{ github.event.inputs.ado_area_path }}" -ado_migrate_closed_workitems $ado_migrate_closed_workitems -ado_production_run $ado_production_run -gh_pat "${{ steps.get_installation_token.outputs.token }}" -gh_org "${{ github.event.inputs.gh-org }}" -gh_repo "${{ github.event.inputs.gh-repo }}" -gh_update_assigned_to $gh_update_assigned_to -gh_assigned_to_user_suffix "${{ github.event.inputs.gh_assigned_to_user_suffix }}" -gh_add_ado_comments $gh_add_ado_comments
-
\ No newline at end of file
diff --git a/.github/workflows/pull_request_workflow.yaml b/.github/workflows/pull_request_workflow.yaml
new file mode 100644
index 0000000..955e5b0
--- /dev/null
+++ b/.github/workflows/pull_request_workflow.yaml
@@ -0,0 +1,14 @@
+on:
+ pull_request:
+
+permissions: read-all
+
+jobs:
+ pull_request_workflow:
+ uses: exit83/shared-workflows/.github/workflows/code_quality.yaml@main
+ with:
+ jest: 'no'
+ playwright: 'no'
+ pre_commit: 'yes'
+ trivy_vulnerability_scan: 'yes'
+ secrets: inherit
diff --git a/.markdownlint.yaml b/.markdownlint.yaml
new file mode 100644
index 0000000..5094d75
--- /dev/null
+++ b/.markdownlint.yaml
@@ -0,0 +1,18 @@
+# MARKDOWN LINT CONFIGURATION
+# https://github.com/DavidAnson/markdownlint/blob/main/schema/.markdownlint.yaml
+
+# Default state for all rules
+default: true
+
+# MD013/line-length - Line length
+MD013:
+ # Include tables
+ tables: false
+
+# MD024/no-duplicate-heading/no-duplicate-header - Multiple headings with the same content
+MD024:
+ # Only check sibling headings
+ siblings_only: true
+
+# MD036/no-emphasis-as-heading/no-emphasis-as-header - Emphasis used instead of a heading
+MD036: false
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..4ca2e99
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,61 @@
+# See https://pre-commit.com for more information
+# See https://pre-commit.com/hooks.html for more hooks
+repos:
+ - repo: https://github.com/gitguardian/ggshield
+ rev: v1.29.0
+ hooks:
+ - id: ggshield
+ language_version: python3
+ stages: [commit]
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.5.0
+ hooks:
+ - id: trailing-whitespace
+ args: [--markdown-linebreak-ext=md]
+ - id: end-of-file-fixer
+ - id: check-yaml
+ - id: check-added-large-files
+ - id: no-commit-to-branch
+ args: [--branch=main]
+ - repo: https://github.com/igorshubovych/markdownlint-cli
+ rev: v0.40.0
+ hooks:
+ - id: markdownlint
+ args: [--config=.markdownlint.yaml]
+ - repo: https://github.com/python-jsonschema/check-jsonschema
+ rev: 0.28.3
+ hooks:
+ - id: check-dependabot
+ - id: check-github-workflows
+ args: ["--verbose"]
+ - id: check-github-actions
+ - repo: https://github.com/antonbabenko/pre-commit-terraform
+ rev: v1.79.1
+ hooks:
+ - id: terraform_fmt
+ args:
+ - --args=-recursive
+ - id: terraform_tflint
+ args:
+ # Permanently Disabled Checks
+ - --args=--disable-rule=terraform_required_version # We manage TF Version in GH Workflow
+ # Disabled for this Project
+ # Temporarily Disabled Checks
+ - id: terraform_checkov
+ args:
+ - --args=--quiet
+ # - --args=--compact
+ # Permanently Disabled Checks
+ - --args=--skip-check CKV_AZURE_189 # We use Azure KeyVault on GH Actions
+ - --args=--skip-check CKV_AZURE_109 # Maintaining a list of allowed GH Action Worker IPs is not feasible
+ - --args=--skip-check CKV_AZURE_190 # No longer valid https://github.com/bridgecrewio/checkov/issues/4307
+ - --args=--skip-check CKV2_AZURE_1 # Customer managed keys
+ - --args=--skip-check CKV2_AZURE_18 # Customer managed keys
+ - --args=--skip-check CKV2_AZURE_32 # KeyVault Private endpoints are overly complicated for 99% of our clients
+ - --args=--skip-check CKV2_AZURE_33 # Storage Account Private endpoints are overly complicated for 99% of our clients
+ - --args=--skip-check CKV2_AZURE_47 # That only apply for no Azure Cloud (Azure Gov, China, etc)
+ - --args=--skip-check CKV2_AZURE_41 # The SAS accounts, not need limited for the duration. In general we not use sas accounts
+ - --args=--skip-check CKV_AZURE_33 # The rule only apply for Queue, and we not use Queue in general
+
+ # Disabled for this Project
+ # Temporarily Disabled Checks
diff --git a/README.md b/README.md
index 6bda3c2..39a1951 100644
--- a/README.md
+++ b/README.md
@@ -2,61 +2,74 @@
PowerShell script to migrate Azure DevOps work items to GitHub Issues
-### Prerequisites
+## Prerequisites
-1. Install az devops and github cli where this is running (ie: action or locally; GitHub-hosted runners already have)
-2. In GitHub, [create a label](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels) for EACH work item type that is being migrated (as lower case)
+1. Install az devops and github cli where this is running (ie: action or locally;
+ GitHub-hosted runners already have)
+2. In GitHub, [create a label](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels)
+ for EACH work item type that is being migrated (as lower case)
- ie: "user story", "bug", "task", "feature"
3. Define under what area path you want to migrate
- - You can modify the WIQL if you want to use a different way to migrate work items, such as `[TAG] = "migrate"`
+ - You can modify the WIQL if you want to use a different way to migrate workitems,
+ such as `[TAG] = "migrate"`
-### Things it migrates
+## Things it migrates
1. Title
2. Description (or for a bug, repro steps and/or system info)
3. State (if the work item is done / closed, it will be closed in GitHub)
-4. It will try to assign the work item to the correct user in GitHub - based on ADO email before the `@`
+4. It will try to assign the work item to the correct user in GitHub - based on
+ ADO email before the `@`
- This uses the `-gh_update_assigned_to` and `-gh_assigned_to_user_suffix` options
- Users have to be added to GitHub org
5. Migrate acceptance criteria as part of issue body (if present)
6. Adds in the following as a comment to the issue:
- - Original work item url
+ - Original work item url
- Basic details in a collapsed markdown table
- Entire work item as JSON in a collapsed section
-7. Creates tag "copied-to-github" and a comment on the ADO work item with `-$ado_production_run $true"`. The tag prevents duplicate copying.
+7. Creates tag "copied-to-github" and a comment on the ADO work item with
+ `-$ado_production_run $true"`. The tag prevents duplicate copying.
+
+## To Do
-### To Do
1. Provide user mapping option
-### Things it won't ever migrate
+## Things it won't ever migrate
+
1. Created date/update dates
-### Example
+## Example
- [Screenshot](https://user-images.githubusercontent.com/19912012/157745772-69f5cf75-5407-491e-a754-d94b188378ff.png)
- [Migrated GitHub Issue](https://github.com/joshjohanning-org/migrate-ado-workitems/issues/296)
## Instructions for Running in Actions
-The recommendation is to use a GitHub App to run the migration - a GitHub app has higher rate limits than using a user PAT.
+The recommendation is to use a GitHub App to run the migration - a GitHub app
+has higher rate limits than using a user PAT.
-1. Create GitHub App with (can use this [reference](https://josh-ops.com/posts/github-apps/#creating-a-github-app)). Use the following permissions:
- + Repo: `Contents:Read`
- + Repo: `Issues:Read and write`
- + Org: `Members:Read`
+1. Create GitHub App with (can use this [reference](https://josh-ops.com/posts/github-apps/#creating-a-github-app)).
+Use the following permissions:
+ - Repo: `Contents:Read`
+ - Repo: `Issues:Read and write`
+ - Org: `Members:Read`
1. Create Private Key for GitHub App
1. Obtain App ID and Installation ID - see [the instructions for using smee.io](https://josh-ops.com/posts/github-apps/#creating-a-github-app)
1. Create the following action secrets:
- + `ADO_PAT`: Azure DevOps PAT with appropriate permissions to read work items
- + `PRIVATE_KEY`: The contents of the private key created and downloaded in step #2
-1. Use the [action](.github/workflows/migrate-work-items.yml) and update the App ID and Installation ID obtained in step #3
-1. Update any defaults in the [action](.github/workflows/migrate-work-items.yml) (ie: Azure DevOps organization and project, GitHub organization and repo)
+ - `ADO_PAT`: Azure DevOps PAT with appropriate permissions to read work items
+ - `PRIVATE_KEY`: The contents of the private key created and downloaded in
+ step #2
+1. Use the [action](.github/workflows/migrate-work-items.yml) and update the App
+ ID and Installation ID obtained in step #3
+1. Update any defaults in the [action](.github/workflows/migrate-work-items.yml)
+ (ie: Azure DevOps organization and project, GitHub organization and repo)
1. Ensure the action exists in the repo's default branch
1. Run the workflow
## Instructions for Running Locally
-Using the GitHub app might be better so you don't reach a limit on your GitHub account on creating new issues 😀
+Using the GitHub app might be better so you don't reach a limit on your GitHub
+account on creating new issues 😀
```pwsh
./ado_workitems_to_github_issues.ps1 `
@@ -91,4 +104,5 @@ Using the GitHub app might be better so you don't reach a limit on your GitHub a
| `-gh_assigned_to_user_suffix` | No | `""` | Used in conjunction with `-gh_update_assigned_to`, used to suffix the username, e.g. if using GitHub Enterprise Managed User (EMU) instance |
| `-gh_add_ado_comments` | No | `$false` | Switch to add ADO comments as a section with the migrated work item |
-+ **Note**: With `-gh_update_assigned_to $true`, you/your users will receive a lot of emails from GitHub when the user is assigned to the issue
\ No newline at end of file
+- **Note**: With `-gh_update_assigned_to $true`, you/your users will receive a
+lot of emails from GitHub when the user is assigned to the issue
diff --git a/ado_workitems_to_github_issues.ps1 b/ado_workitems_to_github_issues.ps1
index f9d85bc..d572913 100644
--- a/ado_workitems_to_github_issues.ps1
+++ b/ado_workitems_to_github_issues.ps1
@@ -4,7 +4,7 @@
# Prerequisites:
# 1. Install az devops and github cli
-# 2. create a label for EACH work item type that is being migrated (as lower case)
+# 2. create a label for EACH work item type that is being migrated (as lower case)
# - ie: "user story", "bug", "task", "feature"
# 3. define under what area path you want to migrate
# - You can modify the WIQL if you want to use a different way to migrate work items, such as [TAG] = "migrate"
@@ -20,7 +20,7 @@
# 4. It will try to assign the work item to the correct user in GitHub - based on ADO email (-gh_update_assigned_to and -gh_assigned_to_user_suffix options) - they of course have to be in GitHub already
# 5. Migrate acceptance criteria as part of issue body (if present)
# 6. Adds in the following as a comment to the issue:
-# a. Original work item url
+# a. Original work item url
# b. Basic details in a collapsed markdown table
# c. Entire work item as JSON in a collapsed section
# 7. Creates tag "copied-to-github" and a comment on the ADO work item with `-$ado_production_run $true` . The tag prevents duplicate copying.
@@ -117,14 +117,14 @@ ForEach($workitem in $query) {
$ado_assigned_to_display_name = ""
$ado_assigned_to_unique_name = ""
}
-
+
# create the details table
$ado_details_beginning="`n`n " + "`n`n"
$ado_details_beginning | Add-Content -Path ./temp_comment_body.txt -Encoding ASCII;
$ado_details= "| Created date | Created by | Changed date | Changed By | Assigned To | State | Type | Area Path | Iteration Path|`n|---|---|---|---|---|---|---|---|---|`n"
$ado_details+="| $($details.fields.{System.CreatedDate}) | $($details.fields.{System.CreatedBy}.displayName) | $($details.fields.{System.ChangedDate}) | $($details.fields.{System.ChangedBy}.displayName) | $ado_assigned_to_display_name | $($details.fields.{System.State}) | $($details.fields.{System.WorkItemType}) | $($details.fields.{System.AreaPath}) | $($details.fields.{System.IterationPath}) |`n`n"
$ado_details | Add-Content -Path ./temp_comment_body.txt -Encoding ASCII;
- $ado_details_end="`n" + "`nOriginal Work Item Details
" + "`n`n" @@ -153,13 +153,13 @@ ForEach($workitem in $query) { $ado_original_workitem_json_end | Add-Content -Path ./temp_comment_body.txt -Encoding ASCII; } } - + # setting the label on the issue to be the work item type $work_item_type = $details.fields.{System.WorkItemType}.ToLower() # create the issue $issue_url=gh issue create --body-file ./temp_issue_body.txt --repo "$gh_org/$gh_repo" --title "$title" --label $work_item_type - + if (![string]::IsNullOrEmpty($issue_url.Trim())) { Write-Host " Issue created: $issue_url"; $count++; @@ -167,7 +167,7 @@ ForEach($workitem in $query) { else { throw "Issue creation failed."; } - + # update assigned to in GitHub if the option is set - tries to use ado email to map to github username if ($gh_update_assigned_to -eq $true -and $ado_assigned_to_unique_name -ne "") { $gh_assignee=$ado_assigned_to_unique_name.Split("@")[0] @@ -187,7 +187,7 @@ ForEach($workitem in $query) { if ($ado_production_run) { $workitemTags = $workitem.fields.'System.Tags'; $discussion = "This work item was copied to github as issue $issue_url"; - az boards work-item update --id "$workitemId" --fields "System.Tags=copied-to-github; $workitemTags" --discussion "$discussion" | Out-Null; + az boards work-item update --id "$workitemId" --fields "System.Tags=copied-to-github; $workitemTags" --discussion "$discussion" | Out-Null; } # close out the issue if it's closed on the Azure Devops side @@ -195,6 +195,6 @@ ForEach($workitem in $query) { if ($ado_closure_states.Contains($details.fields.{System.State})) { gh issue close $issue_url } - + } Write-Host "Total items copied: $count"