Code Monkey home page Code Monkey logo

issue-forms-body-parser's Introduction

GitHub Issue Forms Body Parser

Test Release Conventional Commits zentered.co

Issue Forms is a great way to structure GitHub Issues to an expected format, and to make it easier to capture information from the user. Unfortunately, the schema only defined the input of the data, not the output. So the markdown body needs to be parsed to extract the information in a structured way and to make further processing easier.

We use this Action at the Cyprus Developer Community to create issues with event data for upcoming meetups etc. The parser extracts the information from the issues and provides structured data to create calendar entries (ie .ics files for calendar subscriptions with GitEvents), calling 3rd party APIs, etc.

Inspired by: Peter Murray's Issue Forms Body Parser with valuable feedback from Steffen

Features

  • ✅ npm version available npm i @zentered/issue-forms-body-parser
  • ✅ parse question/answer format into title/text as JSON
  • ✅ parse line items and "tasks" with separate checked attributes
  • ✅ slugify title to id to find data
  • ✅ parse dates and times into separate date and time fields
  • ❎ no tokens/input required
  • ❎ zero configuration

Transforms markdown from GitHub Issue Forms:

### Event Description

Let's meet for coffee and chat about tech, coding, Cyprus and the newly formed
CDC (Cyprus Developer Community).

### Location

Cafe Nero Finikoudes, Larnaka

### Date

11.03.2022

### Time

16:00

to structured, usable data:

{
  "event-description": {
    "order": 0,
    "title": "Event Description",
    "text": "Let's meet for coffee and chat about tech, coding, Cyprus and the newly formed\nCDC (Cyprus Developer Community)."
  },
  "location": {
    "order": 1,
    "title": "Location",
    "text": "Cafe Nero Finikoudes, Larnaka"
  },
  "date": {
    "order": 2,
    "title": "Date",
    "text": "11.03.2022",
    "date": "2022-03-11"
  },
  "time": {
    "order": 3,
    "title": "Time",
    "text": "16:00",
    "time": "16:00"
  }
}

See more examples in md test cases and test results.

Parsers

  • date: checks if the value matches a common date format and returns a formatted date field (in UTC).
  • time: checks if the value matches a common time format and returns a formatted time field.
  • lists: automatically returns lists as arrays
  • duration: currently only the format XXhYYm is supported as duration, ie. 1h30m returns a duration object with hours and minutes.

Installation & Usage

GitHub Actions

name: Issue Forms Body Parser

on: issues

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - name: Issue Forms Body Parser
        id: parse
        uses: zentered/[email protected]
      - run: echo ${{ toJSON(steps.parse.outputs.data) }}

You can also provide a custom body input:

name: Issue Forms Body Parser

on:
  workflow_dispatch:
    inputs:
      issue_number:
        type: string
        required: true
env:
  GH_TOKEN: ${{ github.token }}

jobs:
  process:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch the issue
        id: read_issue_body
        run:
          echo "body=$(gh issue view ${{ inputs.issue_number }} --repo ${{
          github.repo }} --json body --jq '.body')" >> $GITHUB_OUTPUT

      - name: Issue Forms Body Parser
        id: parse
        uses: zentered/[email protected]
        with:
          body: ${{ steps.read_issue_body.output.body }}

      - run: echo ${{ toJSON(steps.parse.outputs.data) }}

NPM

The parser is available as a standalone library:

    npm i @zentered/issue-forms-body-parser
    # OR yarn add @zentered/issue-forms-body-parser

Usage:

import bodyParser from '@zentered/issue-forms-body-parser'
const issueData = await bodyParser(issue.body)

Development & Testing

You can use act to test this Action locally.

npm run build && act issues -e test/issue.json

or run:

npm test

to test the parser.

Links

License

Licensed under MIT.

Here is a list of all the licenses of our production dependencies

issue-forms-body-parser's People

Contributors

andyfeller avatar benja-m-1 avatar dependabot[bot] avatar mariosimou avatar mivano avatar patrickheneise avatar robandpdx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

issue-forms-body-parser's Issues

Action escapes underscores and likely other characters unexpectedly.

Describe the bug

Action is escaping underscores from issue form parsing.

To reproduce

  1. Create issue form with input and/or textarea field types

  2. Create workflow triggered on new issue creation that parses issue form and passes output to step

        steps:
          - name: Cloning repository for reusable scripts
            uses: actions/checkout@v2
     
          - name: Parse issue form
            id: parse
            uses: zentered/[email protected]
     
          - name: Record issue form results
            uses: actions/github-script@v6
            env:
              ISSUE_FORM_JSON: ${{ steps.parse.outputs.data }}
            with:
              script: |
                const issueForm = JSON.parse(process.env.ISSUE_FORM_JSON)
                const jsonPretty = JSON.stringify(issueForm, null, 2)
                const body = `
                Nice!  Let's validate the issue form so we can get this thing done!
                <details>
                  <summary>Issue Form Payload</summary>
                  \`\`\`json
                  ${jsonPretty}
                  \`\`\`
                </details>
                `
                github.rest.issues.createComment({
                  ...context.repo,
                  issue_number: context.issue.number,
                  body
                })
  3. Create issue and verify processed JSON output with escaped underscores

    {"repository-name":{"title":"Repository name","content":["check\\_underscores\\_2"],"text":"check\\_underscores\\_2"},"repository-description":{"title":"Repository description","content":["*No response*"],"text":"*No response*"},"repository-visibility":{"title":"Repository visibility","content":["Internal"],"text":"Internal"},"repository-justification":{"title":"Repository justification","content":["*No response*"],"text":"*No response*"},"repository-access":{"title":"Repository access","content":["@tinyfists/under\\_scores , read"],"text":"@tinyfists/under\\_scores , read"}}

Expected behaviour

There might be a good reason for this, so either:

  1. Review whether this is intended and provide docs for users to de-escape text as needed
  2. Modify action to de-escape text resulting from parsing

Additional context

No response

Provide option to return a hash / dictionary rather than an array

Is your feature request related to a problem? Please describe.

When working with the results from parsing the issue form, it takes additional effort to find the right array index containing the section I need. Since each section is uniquely named, it would be easier to return a dictionary or hash with the results indexed by id instead.

So instead of:

[
{
  "id": "repository-name",
  "title": ">>Repository name<<",
  "text": "test-zentered-issue-form-parser-2\n"
},
{
  "id": "repository-description",
  "title": ">>Repository description<<",
  "text": "*No response*\n"
},
{
  "id": "repository-visibility",
  "title": ">>Repository visibility<<",
  "text": "Internal\n"
},
{
  "id": "repository-access",
  "title": ">>Repository access<<",
  "text": "@tinyfists/monks, read\n"
},
{
  "id": "compliance-programs",
  "title": ">>Compliance programs<<",
  "list": [
    {
      "checked": false,
      "text": "GDPR"
    },
    {
      "checked": true,
      "text": "HIPAA"
    },
    {
      "checked": true,
      "text": "PCI"
    },
    {
      "checked": false,
      "text": "..."
    }
  ],
  "text": "*   [ ] GDPR\n*   [x] HIPAA\n*   [x] PCI\n*   [ ] ...\n"
}
]

something like this could be returned:

{
	"repository-name": {
		"id": "repository-name",
		"title": ">>Repository name<<",
		"text": "test-zentered-issue-form-parser-2\n"
	},
	"repository-description": {
		"id": "repository-description",
		"title": ">>Repository description<<",
		"text": "*No response*\n"
	},
	"repository-visibility": {
		"id": "repository-visibility",
		"title": ">>Repository visibility<<",
		"text": "Internal\n"
	},
	"repository-access": {
		"id": "repository-access",
		"title": ">>Repository access<<",
		"text": "@tinyfists/monks, read\n"
	},
	"compliance-programs": {
		"id": "compliance-programs",
		"title": ">>Compliance programs<<",
		"list": [
			{
				"checked": false,
				"text": "GDPR"
			}, {
				"checked": true,
				"text": "HIPAA"
			}, {
				"checked": true,
				"text": "PCI"
			}, {
			"checked": false,
			"text": "..."
			}
		],
		"text": "*   [ ] GDPR\n*   [x] HIPAA\n*   [x] PCI\n*   [ ] ...\n"
	}
}

I could give or take redundantly including the "id" within the payload along with being the key.

Describe the solution you would like

Provide an option that allows the user to indicate whether an array of objects or a hash / dictionary should be returned.

Describe alternatives you have considered

No response

Additional context

Love the work!

Multiple problems trying to use this action: bad version, no JSON instruction and missing index.js

Describe the bug

Multiple errors after multiples tries.

To Reproduce

Unable to use the released version

Trying to use this version: https://github.com/zentered/issue-forms-body-parser/releases/tag/v1.1.0

      - name: Issue Forms Body Parser
        id: parse
        uses: zentered/[email protected]
      - run: echo "${{ JSON.stringify(steps.parse.outputs.data) }}"

Error:

Unable to resolve action `zentered/[email protected]`, unable to find version `1.1`

Unrecognized named-value: 'JSON'

Running the example given into README:

      - name: Issue Forms Body Parser
        id: parse
        uses: zentered/[email protected]
      - run: echo "${{ JSON.stringify(steps.parse.outputs.data) }}"

Error:

Invalid workflow file: .github/workflows/issue_comment.yml#L38
The workflow is not valid. .github/workflows/issue_comment.yml (Line: 38, Col: 14): Unrecognized named-value: 'JSON'. Located at position 1 within expression: JSON.stringify(steps.parse.outputs.data)

Missing dist/index.js

      - name: GitHub Issue Forms Body Parser
        id: parsezt
        uses: zentered/issue-forms-body-parser@main
        # same error with: @1.0.2

Error:

2022-03-20T15:48:57.9592858Z ##[group]Run zentered/issue-forms-body-parser@main
2022-03-20T15:48:57.9593184Z ##[endgroup]
2022-03-20T15:48:57.9685273Z ##[error]File not found: '/home/runner/work/_actions/zentered/issue-forms-body-parser/main/dist/index.js'

Expected behavior

Works as described. Release published on Action marketplace to test against (but it seems

Feature request: Allow to specify the content to parse

Is your feature request related to a problem? Please describe.

Hi there 👋

I have a workflow that runs when an issue is created, reopened, edited. Now, I'd like to run this workflow again when someone comments /run with https://github.com/peter-evans/slash-command-dispatch. This will trigger the workflow with either a repository_dispatch or a workflow_dispatch. In any case, I could get the issue id from the payload/inputs. This will allow me to fetch the issue to then parse the content.

Describe the solution you would like

That would be awesome if I could provide a body parameter to the step:

      - id: read_issue_body 
        run: echo "body=$(gh issue view ${{ inputs.issue_number }} --json body)" >> $GITHUB_OUTPUT

      - name: Parse issue body
        id: parse
        uses: zentered/[email protected]
        with:
            body: ${{ steps.read_issue_body.output.body }}

Describe alternatives you have considered

I could use a actions/github-script and use some js in it to do that.

      - id: read_issue_body 
        run: echo "body=$(gh issue view ${{ inputs.issue_number }} --json body)" >> $GITHUB_OUTPUT

      - uses: actions/setup-node@v3

      - run: npm install @zentered/issue-forms-body-parser

      - name: Get extensions
        id: extract_extensions
        uses: actions/github-script@v6
        with:
          script: |
            const { default: parser } = await import('${{ github.workspace }}/node_modules/@zentered/issue-forms-body-parser/pkg/parse.js');
            try {
              const content = await parser(${{ steps.read_issue_body.output.body }});
              core.setOutput(content);
            }
            // ...

Additional context

No response

Body containing hours triggers date-fns parsing and error

Describe the bug

When an issue contains hours at the beginning of a line we try to parse it as an hour and date-fns crashes.

This is what we're sending to date-fns parse:

1) 19:00 - 19:45 - "Workflow automation with GitHub Actions"
Yuri Trykov (inDrive)
Automation is a crucial aspect of fast code delivery, and GitHub Actions is a simple and convenient tool to automate the development workflow right in your GitHub repository. In this talk, I am going to cover basic scenarios: testing, building and deploying code, and integration with external services. Moreover, I will share some tips for creating effective automation and fixing common problems.
2) hh:mm A 
3) 2023-09-05T18:51:53.608Z 
4) undefined

This eventually fails because of the A with

Issue 'CDC Test failed': RangeError: Format string contains an unescaped latin alphabet character `A`

To reproduce

This is the original string which reproduces the error:

### Event Description\n\nWe are happy to announce the first meetup of CocoaHeads Cyprus! Let's gather and have some fun. Talks would be in English. [Reserve a spot here](https://www. eventbrite. com/e/cocoaheads-cyprus-0604-tickets-596834436867).\n\nAgenda\n\n18:30- 19:00 - Gathering & Intro\n\n19:00 - 19:45 - "Workflow automation with GitHub Actions"\nYuri Trykov (inDrive)\nAutomation is a crucial aspect of fast code delivery, and GitHub Actions is a simple and convenient tool to automate the development workflow right in your GitHub repository. In this talk, I am going to cover basic scenarios: testing, building and deploying code, and integration with external services. Moreover, I will share some tips for creating effective automation and fixing common problems.\n\n19:45 - 20:00 - Coffee Break & Networking\n\n20:00 - 20:45 - "Boosting your pet-project with ChatGPT"\nAlexey Levanov (Exness)\nVery often pet projects are not completed due to lack of time, loss of motivation, or workload. If your pet project is a completed mobile application, in addition to development, you need design and promotion. It is quite difficult to engage in development, UI/UX prototyping, and marketing at the same time. Let's see how currently available neural networks can help you to accelerate the development of your pet project and replace competencies that you don't possess.\n\n20:45 - 21:00 - Networking\n\n### Location\n\nPorto Bello, Limassol\n\n### Date\n\n06.04.2023\n\n### Time\n\n18.30\n\n### Duration\n\n2h30m\n\n### Code of Conduct\n\n- [X] I agree to follow this project's [Code of Conduct](https://berlincodeofconduct. org)

Expected behaviour

The body parses correctly without errors

Additional context

We could definitely improve the parsing logic (or handle exceptions) but I was wondering if you thought about dealing with parsing based on the header.

In that way whatever content is in the Event Description won't matter and we'll accept only dates in Date or times in Time.

Old setOutput function before @actions/core 1.10.0 is deprecated

Describe the bug

The old setOutput function is deprecated and its use leads to the following deprecation warning:

The `set-output` command is deprecated and will be disabled soon. Please upgrade to using Environment Files. For more information see: https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

To reproduce

Use the action and observe that calling it produces a deprecation warning.
See https://github.com/Kas-tle/java2bedrock.sh/actions/runs/3247277630 for example.

Expected behaviour

No deprecation warning occurs.

Additional context

This can be remedied by upgrading the @actions/core package to 1.10.0 as described here:
https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/

Return null or empty string when no response was given on a field

Is your feature request related to a problem? Please describe.

When an optional field is left blank, the final markdown contains No response . This gets picked up and parsed as ordinary text by the library:

"field":{"title":"field","heading":1,"content":["*No response*"],"text":"*No response*"}

Describe the solution you would like

Ideally, it would be preferable that an empty response is detected and replaced with a null or empty string.

Describe alternatives you have considered

No response

Additional context

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.