Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a read option #6

Merged
merged 1 commit into from
Aug 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Update Project Action

A composite GitHub action that updates an item's fields on a GitHub Projects (beta) board based on a workflow dispatch (or other) event's input.
A composite GitHub action that updates or gets an item's fields on a GitHub Projects (beta) board based on a workflow dispatch (or other) event's input.

[![CI](https://github.com/benbalter/update-project-action/actions/workflows/ci.yml/badge.svg)](https://github.com/benbalter/update-project-action/actions/workflows/ci.yml)

## Goals

* To make it easier to update the fields of a GitHub Project board based on action taken elsewhere within the development process (e.g., status update comments)
* To make it easier to update/read the fields of a GitHub Project board based on action taken elsewhere within the development process (e.g., status update comments)
* Keep it simple - Prefer boring technology that others can understand, modify, and contribute to
* Never force a human to do what a robot can

Expand All @@ -27,7 +27,20 @@ jobs:
update_project:
runs-on: ubuntu-latest
steps:
- name: Read status
id: read_status
uses: github/update-project-action@v2
with:
github_token: ${{ secrets.STATUS_UPDATE_TOKEN }}
organizatin: github
project_number: 1234
operation: read
content_id: ${{ github.event.client_payload.command.resource.id }}
- name: Output status
run: |
echo "Current status value: ${{ steps.read_status.outputs.field_read_value }}"
- name: Update status
id: update_status
uses: github/update-project-action@v2
with:
github_token: ${{ secrets.STATUS_UPDATE_TOKEN }}
Expand All @@ -51,8 +64,12 @@ The Action is largely feature complete with regards to its initial goals. Find a
* `organization` - The organization that contains the project, defaults to the current repository owner
* `project_number` - The project number from the project's URL
* `value` - The value to set the project field to
* `operation` - Type of the operation (`update` or `read`; default is `update`)

### Outputs

* `field_read_value` - The value of the field before the update
* `field_updated_value` - The value of the field after the update (in case of `read` operation equals to `field_read_value`)
* `field_id` - The global ID of the field
* `field_type` - The updated field's ProjectV2FieldType (text, single_select, number, date, or iteration)
* `item_id` - The global ID of the issue or pull request
Expand Down
68 changes: 62 additions & 6 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ inputs:
project_number:
description: The project number from the project's URL
required: true
operation:
description: Operation type (update or read)
default: update
required: false
content_id:
description: The global ID of the issue or pull request within the project
required: true
Expand All @@ -33,6 +37,12 @@ outputs:
field_id:
description: "The global ID of the field"
value: ${{ steps.parse_project_metadata.outputs.field_id }}
field_read_value:
description: "The value of the field before the update"
value: ${{ steps.parse_content_metadata.outputs.item_value }}
field_updated_value:
description: "The value of the field after the update"
value: ${{ steps.output_values.outputs.field_updated_value }}
field_type:
description: "The updated field's ProjectV2FieldType (text, single_select, number, date, or iteration)"
value: ${{ steps.parse_project_metadata.outputs.field_type }}
Expand All @@ -42,14 +52,25 @@ outputs:
runs:
using: "composite"
steps:
- name: Fetch content ID and title
- name: Check that the operation type is valid
env:
OPERATION: ${{ inputs.operation }}
shell: bash
run: |
if [ "$OPERATION" != "read" ] && [ "$OPERATION" != "update" ]; then
echo "Invalid value passed for the 'operation' parameter (passed: $OPERATION, allowed: read, update)";
exit 1;
fi
- name: Fetch content ID, value and title
id: fetch_content_metadata
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
CONTENT_ID: ${{ inputs.content_id }}
FIELD_NAME: ${{ inputs.field }}
FILE_NAME: organization-${{ inputs.organization }}-issue-${{ inputs.content_id }}.json
OPERATION: ${{ inputs.operation }}
QUERY: |
query($issue_id: ID!) {
query($issue_id: ID!, $field_name: String!) {
node(id: $issue_id) {
... on Issue {
id
Expand All @@ -59,6 +80,7 @@ runs:
id
project {
number

owner {
... on Organization {
login
Expand All @@ -68,6 +90,24 @@ runs:
}
}
}

field: fieldValueByName(name: $field_name) {
... on ProjectV2ItemFieldSingleSelectValue {
value: name
}

... on ProjectV2ItemFieldNumberValue {
value: number
}

... on ProjectV2ItemFieldTextValue {
value: text
}

... on ProjectV2ItemFieldDateValue {
value: date
}
}
}
}
}
Expand All @@ -76,15 +116,15 @@ runs:
shell: bash
run: |
# Fetch project fields metadata
if [ ! -f "$FILE_NAME" ]; then
gh api graphql -f query="$QUERY" -F issue_id="$CONTENT_ID" > "$FILE_NAME"
if [ ! -f "$FILE_NAME" ] || [ "$OPERATION" == "read" ]; then
gh api graphql -f query="$QUERY" -F issue_id="$CONTENT_ID" -F field_name="$FIELD_NAME" > "$FILE_NAME"
else
echo "Using cached project fields metadata from '$FILE_NAME'"
fi

echo "::set-output name=file_name::$FILE_NAME"

- name: Parse content ID and title
- name: Parse content ID, value and title
id: parse_content_metadata
shell: bash
env:
Expand All @@ -95,6 +135,7 @@ runs:
# Parse content metadata
echo '::set-output name=item_id::'$(jq -r '.data.node.projectItems.nodes | .[] | select(.project.number==($PROJECT_NUMBER|fromjson) and .project.owner.login==$OWNER).id' "$FILE_NAME" --arg OWNER "$OWNER" --arg PROJECT_NUMBER "$PROJECT_NUMBER")
echo '::set-output name=item_title::'$(jq -r '.data.node.title' "$FILE_NAME")
echo '::set-output name=item_value::'$(jq -r '.data.node.projectItems.nodes | .[] | select(.project.number==($PROJECT_NUMBER|fromjson) and .project.owner.login==$OWNER).field.value' "$FILE_NAME" --arg OWNER "$OWNER" --arg PROJECT_NUMBER "$PROJECT_NUMBER")

- name: Ensure content item was found
env:
Expand Down Expand Up @@ -175,7 +216,9 @@ runs:
# Ensure project, item, field, and option were found
if [ -z "$PROJECT_ID" ] || [ "$PROJECT_ID" = "null" ]; then echo "Project '$PROJECT_NUMBER' not found for organization '$ORGANIZATION'"; exit 1; fi
if [ -z "$FIELD_ID" ]; then echo "Field '$FIELD' not found"; exit 1; fi
if [[ "$FIELD_TYPE" = "single_select" && -z "$OPTION_ID" ]]; then echo "Option not found with value '$VALUE'"; exit 1; fi
if [ "$OPERATION" == "update" ]; then
if [[ "$FIELD_TYPE" = "single_select" && -z "$OPTION_ID" ]]; then echo "Option not found with value '$VALUE'"; exit 1; fi
fi

- name: Parse value
shell: bash
Expand Down Expand Up @@ -203,7 +246,20 @@ runs:
echo '::set-output name=value_graphql_type::String'
fi

- name: Output values
id: output_values
shell: bash
env:
OPERATION: ${{ inputs.operation }}
run: |
if [ "$OPERATION" == "read" ]; then
echo ''::set-output name=field_updated_value::${{ steps.parse_content_metadata.outputs.item_value }}
else
echo ''::set-output name=field_updated_value::${{ inputs.value }}
fi

- name: Update field
if: ${{ inputs.operation == 'update' }}
env:
GITHUB_TOKEN: ${{ inputs.github_token }}
FIELD: ${{ inputs.field }}
Expand Down