Extending using Custom Forms and Issue Ops Actions
Last updated
Last updated
This comprehensive guide will walk you through the process of creating custom forms that render in your Dev Central dashboard and setting up custom actions triggered by those forms.
By following this guide, you can create custom forms that render in your Dev Central dashboard and set up custom actions triggered by those forms. This approach allows you to extend the functionality of your sfops workflow to meet your specific project needs while leveraging the power of the sfops issueAnalyzer to process and utilize form data efficiently.
Remember that custom forms and actions should be designed with your team's specific workflows and requirements in mind. Regularly gather feedback from users and iterate on your custom forms and actions to ensure they continue to meet your team's evolving needs.
Create a new YAML file in the _forms
directory of your dev central repository. The file name will be used as the form identifier, so choose a descriptive name (e.g., request-custom-action.yml
).
Define the form structure in the YAML file using the following syntax:
name: Request Custom Action
description: This form allows you to request a custom action.
title: "Custom Action Request"
labels: ["custom", "request"]
body:
- type: input
id: name
attributes:
label: Name
description: Enter your name
validations:
required: true
- type: textarea
id: description
attributes:
label: Description
description: Provide a description of the custom action
validations:
required: true
- type: dropdown
id: priority
attributes:
label: Priority
description: Select the priority level
options:
- High
- Medium
- Low
- type: checkboxes
id: options
attributes:
label: Options
description: Select the applicable options
options:
- label: Option 1
- label: Option 2
- label: Option 3
Customize the form fields based on your requirements. Here are some commonly used field types and their behaviors:
input
: A single-line text input field. You can specify validations like required
to make the field mandatory.
textarea
: A multi-line text input field for longer descriptions or comments.
dropdown
: A dropdown menu with predefined options. You can specify the options
array to define the available choices.
checkboxes
: A set of checkboxes allowing multiple selections. Each checkbox is defined within the options
array.
select
: A dropdown menu with support for multiple selections. The options
array defines the available choices, and you can group related options using the optgroup
element.
hiddenInput
: A hidden input field that is not visible to the user but can store predefined values.
In addition to the standard form fields, you can leverage special field IDs to populate form options dynamically based on external data sources. This allows for more flexible and data-driven form configurations. Here are some special field IDs you can use:
tag
field:
Use the tag
field ID to populate options based on available tags from the scratchOrgStatus.json
file.
The field type will be automatically set to dropdown
.
Example:
- type: dropdown
id: tag
attributes:
label: Select a tag
description: Choose a tag from the available options
sourceSB
field:
Use the sourceSB
field ID to populate options based on snapshot environments from the envInfos.json
file.
The field type will be automatically set to dropdown
.
Example:
- type: dropdown
id: sourceSB
attributes:
label: Select a source sandbox
description: Choose a source sandbox from the available options
sourceBranch
field:
Use the sourceBranch
field ID to populate options based on available branches from the branches.json
file.
The field type will be automatically set to dropdown
.
Example:
- type: dropdown
id: sourceBranch
attributes:
label: Select a source branch
description: Choose a source branch from the available options
envs
field:
Use the envs
field ID to populate options based on environments from envInfos.json
, available developer sandboxes from developerSandboxes.json
, and available CI sandboxes from ciSandboxes.json
.
The field type will be automatically set to select
for multi-select functionality.
Options will be grouped based on their type (e.g., "Developer", "Review") using the optgroup
element.
Example:
- type: select
id: envs
attributes:
label: Select environments
description: Choose one or more environments from the available options
multiple: true
domain
field:
Use the domain
field ID to populate options based on available domains from the domains.json
file.
The field type will be automatically set to dropdown
.
Example:
- type: dropdown
id: domain
attributes:
label: Select a domain
description: Choose a domain from the available options
By utilizing these special field IDs, you can create dynamic form fields that adapt to your project's specific data and configurations.
Create a new workflow file (e.g., custom-action-workflow.yml
) in the .github/workflows
directory of your project repository.
Use the following template as a starting point for your custom action workflow:
name: Custom Action Workflow
on:
issues:
types: [opened, reopened]
jobs:
analyze_issue:
runs-on: ubuntu-latest
outputs:
sfops_issue: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue }}
name: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_name }}
description: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_description }}
priority: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_priority }}
options: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_options }}
issue_number: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_issueNumber }}
repo_owner: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_repoOwner }}
repo_name: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_repoName }}
issue_creator: ${{ steps.sfops_issue_analyzer.outputs.sfops_issue_issueCreator }}
steps:
- uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ inputs.sfopsbot-app-id }}
private-key: ${{ secrets.SFOPSBOT_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Analyze Issue
uses: ${{ sfops.repo_owner }}/${{ sfops.action_repository }}/issueAnalyzer@main
id: sfops_issue_analyzer
with:
repo_owner: ${{ github.repository_owner }}
repo_name: ${{ github.event.repository.name }}
issue: ${{ github.event.issue.number }}
token: ${{ steps.app-token.outputs.token }}
include_issues: 'your-custom-form-id'
execute_custom_action:
needs: analyze_issue
if: needs.analyze_issue.outputs.sfops_issue == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Execute Custom Action
run: |
echo "Executing custom action..."
echo "Name: ${{ needs.analyze_issue.outputs.name }}"
echo "Description: ${{ needs.analyze_issue.outputs.description }}"
echo "Priority: ${{ needs.analyze_issue.outputs.priority }}"
echo "Options: ${{ needs.analyze_issue.outputs.options }}"
echo "Issue Number: ${{ needs.analyze_issue.outputs.issue_number }}"
echo "Repository: ${{ needs.analyze_issue.outputs.repo_owner }}/${{ needs.analyze_issue.outputs.repo_name }}"
echo "Issue Creator: ${{ needs.analyze_issue.outputs.issue_creator }}"
- name: Add Comment to Issue
uses: ${{ sfops.repo_owner }}/${{ sfops.action_repository }}/add-pr-comment@main
with:
issue: ${{ needs.analyze_issue.outputs.issue_number }}
repo-token: ${{ steps.app-token.outputs.token }}
message: |
Custom action executed successfully!
Customize the workflow:
a. In the on
section, the workflow is triggered when issues are opened or reopened. You can adjust this as needed.
b. In the analyze_issue
job:
Replace your-custom-form-id
in the include_issues
parameter with the ID of your custom form (the filename without the .yml extension).
This job uses the issueAnalyzer
action to determine if the issue is related to your custom form and extracts the form data.
In the outputs
section, define all the form fields and metadata you want to make available to subsequent jobs. Each output should correspond to a field in your form or metadata provided by the issueAnalyzer.
c. In the execute_custom_action
job:
This job only runs if the issue is identified as a custom form submission (sfops_issue == 'true'
).
You can directly access all form fields and metadata defined in the outputs
of the analyze_issue
job using needs.analyze_issue.outputs.<field_name>
.
d. Understanding the issueAnalyzer output: The issueAnalyzer processes the form data and makes it available as outputs. Here's how the data is structured:
sfops_issue
: A boolean value indicating whether the issue is a valid SFOps issue (based on include/exclude rules).
Individual form fields: Each form field is available as a separate output with the prefix sfops_issue_
.
Metadata: Additional information like issueNumber
, repoOwner
, repoName
, and issueCreator
are also available as outputs.
e. Accessing and using form data in your custom action:
You can access the form data in your custom action steps using the needs
context. Here's an example of how to use the parsed data:
- name: Execute Custom Action
run: |
echo "Executing custom action..."
echo "Name: ${{ needs.analyze_issue.outputs.name }}"
echo "Description: ${{ needs.analyze_issue.outputs.description }}"
echo "Priority: ${{ needs.analyze_issue.outputs.priority }}"
echo "Options: ${{ needs.analyze_issue.outputs.options }}"
echo "Issue Number: ${{ needs.analyze_issue.outputs.issue_number }}"
echo "Repository: ${{ needs.analyze_issue.outputs.repo_owner }}/${{ needs.analyze_issue.outputs.repo_name }}"
echo "Issue Creator: ${{ needs.analyze_issue.outputs.issue_creator }}"
# Use the data in your custom logic
if [ "${{ needs.analyze_issue.outputs.priority }}" = "High" ]; then
echo "High priority action required!"
# Add your high-priority action logic here
fi
This example demonstrates how to access various form fields and metadata directly from the job outputs.
Adjust the permissions and authentication as needed for your specific use case.
Commit and push the changes to your project repository.
The issueAnalyzer is a crucial component in processing custom forms. Here's an overview of its functionality:
It fetches the issue details using the provided issue number, repository owner, and repository name.
It looks for a JSON payload in the issue body, which is typically enclosed in HTML comments (<!-- -->
).
If a valid JSON payload is found, it processes the data and sets various outputs:
sfops_issue
: Set to "true" if the issue is a valid SFOps issue, "false" otherwise.
Individual form fields: Each field from the form is set as a separate output with the prefix sfops_issue_
.
It adds some additional metadata as outputs:
sfops_issue_issueNumber
: The number of the current issue.
sfops_issue_repoOwner
: The owner of the repository.
sfops_issue_repoName
: The name of the repository.
sfops_issue_issueCreator
: The GitHub username of the person who created the issue.
If the envs
field is not present in the form data, it defaults to ["devhub"]
.
The analyzer respects the include_issues
and exclude_issues
inputs to determine whether an issue should be processed or not.
By leveraging the issueAnalyzer, your custom action can easily access and use the form data submitted by users, allowing you to create powerful and flexible workflows tailored to your specific needs.
Keep your custom forms focused and concise, collecting only the necessary information.
Use meaningful labels and descriptions for form fields to guide users.
Leverage dynamic options when possible to reduce manual maintenance of form options.
In your custom action workflow, add appropriate error handling and logging.
Consider adding status checks or notifications to keep users informed about the progress of their request.
Regularly review and update your custom forms and actions to ensure they remain relevant and efficient.
Use the include_issues
parameter in the issueAnalyzer step to ensure only relevant issues trigger your custom action.
When processing form data, always validate inputs to ensure data integrity and security.
Utilize the metadata provided by the issueAnalyzer (such as issue_creator
and repo_name
) to add context to your custom actions.
If your custom action involves sensitive operations, consider adding approval steps or additional security checks.
Define all necessary form fields and metadata as outputs in the analyze_issue
job to make them easily accessible in subsequent jobs.
Use meaningful names for your outputs to make the workflow more readable and maintainable.