This is a short tutorial on how to automate the migration process between the legacy project boards and the new projects.
An exported GITHUB_TOKEN with the following permissions will be required:
- ...
An object describing the existing legacy project board will be required.
You can retrieve the legacy user project board as follows:
user=''
legacy_project_board_name=''
legacy_project_board="$(
gh api --paginate "users/${user}/projects" --jq "map(select(.name == \"${legacy_project_board_name}\"))" |
jq -n '[inputs] | add | .[0]'
)"
You can retrieve the legacy organisation project board as follows:
org=''
legacy_project_board_name=''
legacy_project_board="$(
gh api --paginate "orgs/${org}/projects" --jq "map(select(.name == \"${legacy_project_board_name}\"))" |
jq -n '[inputs] | add | .[0]'
)"
Unfortunately, new project creation cannot be automated. There are no API endpoints that can create new projects.
Follow either the creating an organization project instructions or the creating a user project instructions to create a new project.
Subsequent steps will require a node ID of the new project.
You can retrieve the new user project as follows:
user=''
new_project_name=''
new_project="$(
gh api graphql -f query='query($user: String!, $new_project_name: String) {
user(login: $user) {
projectsNext(first: 1, query: $new_project_name) {
nodes {
id
fields(first: 100) {
nodes {
id
name
}
}
}
}
}
}' -f user="${user}" -f new_project_name="${new_project_name}" --jq '.data.user.projectsNext.nodes[0]'
)"
You can retrieve the new organisation project as follows:
org=''
new_project_name=''
new_project="$(
gh api graphql -f query='query($org: String!, $new_project_name: String) {
organization(login: $org) {
projectsNext(first: 1, query: $new_project_name) {
nodes {
id
fields(first: 100) {
nodes {
id
name
}
}
}
}
}
}' -f org="${org}" -f new_project_name="${new_project_name}" --jq '.data.organization.projectsNext.nodes[0]'
)"
Since the API allows manipulating new project settings, legacy project name and body can be copied over.
You can synchronise the metadata as follows:
legacy_project_board=''
new_project=''
legacy_project_board_name"$(jq '.name' <<< "${legacy_project_board}")"
legacy_project_board_body"$(jq '.body' <<< "${legacy_project_board}")"
new_project_id="$(jq '.id' <<< "${new_project}")"
gh api graphql -f query='mutation(new_project_id: ID!, legacy_project_board_name: String, legacy_project_board_body: String) {
updateProjectNext(input: {
projectId: $new_project_id,
title: $legacy_project_board_name,
description: $legacy_project_board_body
}) {}
}' -f new_project_id="${new_project_id}" -f legacy_project_board_name="${legacy_project_board_name}" -f legacy_project_board_body="${legacy_project_board_body}"
owner=''
repo=''
legacy_project_board=''
new_project=''
legacy_project_board_id="$(jq '.id' <<< "${legacy_project_board}")"
legacy_project_board_columns="$(gh api --paginate "projects/${legacy_project_board_id}/columns" | jq -n '[inputs] | add')"
new_project_id="$(jq '.id' <<< "${new_project}")"
new_project_status_field_id="$(jq '.fields.nodes | map(select(.name == "Status")) | .[0].id' <<< "${new_project}")"
while read legacy_project_board_column_id; do
legacy_project_board_column_name="$(jq -r 'map(select(.id == $legacy_project_board_column_id)) | .[0].name' --argjson legacy_project_board_column_id "${legacy_project_board_column_id}" <<< "$legacy_project_board_columns")"
legacy_project_board_cards="$(gh api --paginate "projects/columns/${legacy_project_board_column_id}/cards" --jq 'map(select(.node_id != null))' | jq -n '[inputs] | add')"
while read legacy_project_board_card_id; do
legacy_project_board_card="$(jq -r 'map(select(.id == $legacy_project_board_card_id)) | .[0]' --argjson legacy_project_board_card_id "${legacy_project_board_card_id}" <<< "$legacy_project_board_cards")"
legacy_project_board_card_note="$(jq -r '.note // ""' <<< "${legacy_project_board_card}")"
if [[ -z "${legacy_project_board_card_note}" ]]; then
legacy_project_board_card_node_id="$(gh api "repos/${owner}/${repo}/issues -f title="${legacy_project_board_card_note:60}" -f body="${legacy_project_board_card_note}" --jq '.node_id')"
else
legacy_project_board_card_node_id="$(jq '.node_id' <<< "${legacy_project_board_card}")"
fi
new_project_item_id="$(
gh api graphql -f query='mutation(new_project_id: ID!, legacy_project_board_card_node_id: ID!) {
addProjectNextItem(input: {
projectId: $new_project_id,
contentId: $legacy_project_board_card_node_id
}) {
projectNextItem {
id
}
}
}' -f new_project_id="${new_project_id}" -f legacy_project_board_card_node_id="${legacy_project_board_card_node_id}" --jq 'data.addProjectNextItem.projectNextItem.id'
)"
gh api graphql -f query='mutation(new_project_id: ID!, new_project_item_id: ID!, new_project_status_field_id: ID!, legacy_project_board_column_name: String!) {
updateProjectNextItemField(input: {
projectId: $new_project_id,
itemId: $new_project_item_id,
fieldId: $new_project_status_field_id,
value: $legacy_project_board_column_name,
}) {}
}' -f new_project_id="${new_project_id}" -f new_project_item_id="${new_project_item_id}" -f new_project_status_field_id="${new_project_status_field_id}" -f legacy_project_board_column_name="${legacy_project_board_column_name}"
done <<< "$(jq '.[].id' <<< "$legacy_project_board_cards")"
done <<< "$(jq '.[].id' <<< "$legacy_project_board_columns")"