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

Components proposal #51

Merged
Show file tree
Hide file tree
Changes from 14 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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ The current SIG is made up of the following individuals, and feel free to submit
- Mark Haine ([Founder, Considrd Consulting](https://www.linkedin.com/in/mark-haine/))
- Phil Sturgeon ([Dev Rel, Stoplight](https://www.linkedin.com/in/philipsturgeon/))
- Kevin Duffey ([Tech Lead, Postman](https://www.linkedin.com/in/kmd/))
- Shai Sachs ([Staff Engineer, Chewy](https://linkedin.com/in/shaisachs/))

## The Workflows Specification

Expand Down
13 changes: 13 additions & 0 deletions examples/1.0.0/pet-coupons.openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ paths:
- available
- pending
- sold
- name: page
in: query
description: Which page of results to display. First page is 1.
required: true
schema:
type: int32
- name: pageSize
in: query
description: Number of results to display per page.
required: false
schema:
type: int32
default: 10
responses:
'200':
description: successful operation
Expand Down
112 changes: 96 additions & 16 deletions examples/1.0.0/pet-coupons.workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@ workflows:
This is how you can find a pet, find an applicable coupon, and apply that coupon in your order.
The workflow concludes by outputting the ID of the placed order.
inputs:
type: object
properties:
my_pet_tags:
type: array
items:
type: string
description: Desired tags to use when searching for a pet, in CSV format: e.g. "puppy, dalmation"
$ref: "#/components/inputs/apply_coupon_input"
steps:
- stepId: find-pet
operationId: findPetsByTags
Expand All @@ -50,21 +44,84 @@ workflows:
outputs:
my_coupon_code: $response.body.couponCode
- stepId: place-order
description: Use the coupon to get a discount on the desired pet.
workflowId: place-order
parameters:
- name: pet_id
in: body
value: $steps.find-pet.outputs.my_pet_id
- name: coupon_code
in: body
value: $steps.find-coupons.outputs.my_coupon_code
successCriteria:
- $statusCode == 200
outputs:
my_order_id: $response.body.id
- workflowId: buy-available-pet
summary: Buy an available pet if one is available.
description:
This workflow demonstrates a workflow very similar to `apply-coupon`, by intention.
It's meant to indicate how to reuse a step (`place-order`) as well as a parameter (`page`, `pageSize`).
inputs:
$ref: "#/components/inputs/buy_available_pet_input"
steps:
- stepId: find-pet
operationId: findPetsByStatus
parameters:
- name: status
in: query
value: "available"
- $ref: '#/components/parameters/page'
value: 1
- $ref: '#/components/parameters/pageSize'
value: 10
successCriteria:
- $statusCode == 200
outputs:
my_pet_id: $outputs[0].id
- stepId: place-order
workflowId: place-order
parameters:
- name: pet_id
in: body
value: $steps.find-pet.outputs.my_pet_id
successCriteria:
- $statusCode == 200
outputs:
my_order_id: $response.body.id
- workflowId: place-order
summary: Place an order for a pet.
description:
This workflow places an order for a pet. It may be reused by other workflows as the "final step" in a purchase.
inputs:
type: object
properties:
pet_id:
type: integer
format: int64
description: The ID of the pet to place in the order.
quantity:
type: integer
format: int32
description: The number of pets to place in the order.
value: 1
coupon_code:
type: string
description: The coupon code to apply to the order.
steps:
- stepId: place-order
operationId: placeOrder
parameters:
- name: pet_id
in: body
target: $request.body#/petId
value: $steps.find-pet.outputs.my_pet_id
value: $inputs.pet_id
- name: coupon_code
in: body
target: $request.body#/couponCode
value: $steps.find-pet.outputs.my_coupon_code
value: $inputs.coupon_code
- name: quantity
in: body
target: $request.body#/quantity
value: 1
value: $inputs.quantity
- name: status
in: body
target: $request.body#/status
Expand All @@ -77,7 +134,30 @@ workflows:
- $statusCode == 200
outputs:
my_order_id: $response.body.id


outputs:
order_id: $steps.place-order.my_order_id
components:
inputs:
apply_coupon_input:
type: object
properties:
my_pet_tags:
type: array
items:
type: string
description: Desired tags to use when searching for a pet, in CSV format: e.g. "puppy, dalmation"
store_id:
$ref: "#/components/inputs/store_id"
buy_available_pet_input:
type: object
properties:
store_id:
$ref: "#/components/inputs/store_id"
store_id:
type: string
description: Indicates the domain name of the store where the customer is browsing or buying pets, e.g. "pets.example.com" or "pets.example.co.uk".
parameters:
page:
type: integer
format: int32
pageSize:
type: integer
format: int32
99 changes: 96 additions & 3 deletions versions/1.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ The Workflows Specification can articulate these workflows in a human and machin
- [Failure Action Object](#failure-action-object)
- [Fixed Fields](#fixed-fields-7)
- [Failure Action Object Example](#failure-action-object-example)
- [Component Object](#component-object)
- [Fixed Fields](#fixed-fields-8)
- [Component Object Example](#component-object-example)
- [Reference Object](#reference-object)
- [Fixed Fields](#fixed-fields-9)
- [Reference Object Example](#reference-object-example)
- [Runtime Expressions](#runtime-expressions)
- [Specification Extensions](#specification-extensions)
- [Appendix A: Revision History](#appendix-a-revision-history)
Expand Down Expand Up @@ -121,6 +127,7 @@ Field Name | Type | Description
<a name="workflowsInfo"></a>info | [Info Object](#info-object) | **REQUIRED**. Provides metadata about the Workflows. The metadata MAY be used by tooling as required.
<a name="workflowsSources"></a>sources | [[Source Object](#source-object)] | **REQUIRED**. A list of source documents (such as an OpenAPI document) this workflow SHALL apply to. The list MUST have at least one entry.
<a name="workflows"></a>workflows | [[Workflow Object](#workflow-object)] | **REQUIRED**. A list of workflows. The list MUST have at least one entry.
<a name="components"></a>components | [Component Object](#component-object) | An element to hold various schemas for the document.

This object MAY be extended with [Specification Extensions](#specification-extensionsxtensions).

Expand Down Expand Up @@ -250,8 +257,8 @@ Field Name | Type | Description
<a name="workflowId"></a>workflowId | `string` | **REQUIRED**. Unique string to represent the workflow. The id MUST be unique amongst all workflows describe in the Workflows document. The `workflowId` value is **case-sensitive**. Tools and libraries MAY use the `workflowId` to uniquely identify a workflow, therefore, it is RECOMMENDED to follow common programming naming conventions.
<a name="workflowSummary"></a>summary | `string` | A summary of the purpose or objective of the workflow.
<a name="workflowDescription"></a>description | `string` | A description of the workflow. [CommonMark syntax](https://spec.commonmark.org/) MAY be used for rich text representation.
<a name="workflowInputs"></a>inputs | `JSON Schema` | A JSON Schema object representing the input parameters used by this workflow
<a name="workflowSteps"></a>steps | [[Step Object](#step-object)] | **REQUIRED**. An ordered list of steps where each step represents a call to an API operation or to another workflow
<a name="workflowInputs"></a>inputs | `JSON Schema` | A JSON Schema 2020-12 object representing the input parameters used by this workflow.
<a name="workflowSteps"></a>steps | [[Step Object](#step-object)] | **REQUIRED**. An ordered list of steps where each step represents a call to an API operation or to another workflow.
<a name="outputs"></a>outputs | Map[`string`, {expression}] | A map between a friendly name and a dynamic output value. The name MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`.

This object MAY be extended with [Specification Extensions](#specification-extensions).
Expand Down Expand Up @@ -305,7 +312,7 @@ Field Name | Type | Description
<a name="stepOperationId"></a>operationId | `string` | The name of an existing, resolvable operation, as defined with a unique `operationId` and existing within one of the `source` documents. The referenced operation will be invoked by this workflow step. If more than one `source` document is defined within a Workflows document, then the `operationId` specified MUST be prefixed with the source name to avoid ambiguity or potential clashes. This field is mutually exclusive of the `operationRef` and `workflowId` fields respectively.
<a name="stepOperationRef"></a>operationRef | `string` | A relative or absolute URI reference to an OAS operation. This field is mutually exclusive of the `operationId` and `workflowId` fields respectively. Relative `operationRef` values MAY be used to locate an existing. See [OpenAPI relative reference resolution rules](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#relativeReferencesURI) for guidance. A complete [URI Template](https://www.rfc-editor.org/rfc/rfc6570) can also be used.
<a name="stepWorkflowId"></a>workflowId | `string` | The [workflowId](#fixed-fields-2) referencing an existing workflow within the Workflows document. The field is mutually exclusive of the `operationId` and `operationRef` fields respectively.
<a name="stepParameters"></a>parameters | [[Parameter Object](#parameter-object)] | A list of parameters to pass to an operation or workflow as referenced by `operationId`, `operationRef`, or `workflowId`.
<a name="stepParameters"></a>parameters | [[Parameter Object](#parameter-object) | [Reference Object](#reference-object)] | A list of parameters to pass to an operation or workflow as referenced by `operationId`, `operationRef`, or `workflowId`. If a Reference Object is provided, it MUST refer to a Parameter.
<a name="dependsOn"></a>dependsOn | [`string`] | A list of steps that MUST be completed before this step can be processed. This helps to ensure workflow steps are executed in the correct order and that dependent steps are not processed in parallel. The values provided MUST be the be the `stepId` which uniquely references a step.
<a name="stepSuccessCriteria"></a>successCriteria | [{expression}] | A list of assertions to determine the success of the step
<a name="stepOnSuccess"></a>onSuccess | [[Success Action Object](#success-action-object)] | An array of success action objects that specify what to do upon step success. If omitted, the next sequential step shall be executed as the default behavior.
Expand Down Expand Up @@ -480,6 +487,92 @@ criteria:
- $statusCode == 503
```

#### Component Object

Holds a set of reusable objects for different aspects of the Workflows Specification. All objects defined within the components object will have no effect on the workflow unless they are explicitly referenced from properties outside the components object.

##### Fixed Fields

Field Name | Type | Description
---|:---|---
<a name="componentInputs"></a> inputs | Map[`string`, JSON Schema Object] | An object to hold reusable JSON Schema objects to be referenced from workflow inputs.
<a name="componentParameters">parameters</a> | Map[`string`, [Parameter Object](#parameter-object)] | An object to hold reusable Parameter Objects

This object _MAY_ be extended with [Specification Extensions](#specificationExtensions).


All the fixed fields declared above are objects that MUST use keys that match the regular expression: `^[a-zA-Z0-9\.\-_]+$`. The key is used to refer to the input or parameter in other parts of the Workflow document.

Field Name Examples:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what the field name examples are representing here. We don't have this in other sections

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's just a regex for the keys in the Maps - happy to remove this section but I figured it'd be a good idea.


```
User
User_1
User_Name
user-name
my.org.User
```

##### Component Object Example

```json
"components": {
"inputs": {
"storeId": {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These examples seem to be backwards no? Isn't input a JSON Schema and parameter has the the name, in value property?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm - components.inputs is a Map of string to JSON Schema object, so I'm reasonably sure that piece is right (in this case storeId is the key). Not sure I understand the problem with parameter.

"name": "storeId",
"in": "header",
"value": "$inputs.x-store-id"
}
},
"parameters": {
"pagination": {
"type": "object",
"properties": {
"page": {
"type": "integer",
"format": "int32"
},
"pageSize": {
"type": "integer",
"format": "int32"
}
}
}
}
}
```

#### Reference Object

**Note -** This section is derived from the [OpenAPI Specification, v3.1](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#referenceObject), and is intended to be implemented in similar fashion.

A simple object to allow referencing other components in the OpenAPI document, internally and externally.
frankkilcommins marked this conversation as resolved.
Show resolved Hide resolved

The `$ref` string value contains a URI [RFC3986](https://tools.ietf.org/html/rfc3986), which identifies the location of the value being referenced.

See the rules for resolving [Relative References](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#relativeReferencesURI).

##### Fixed Fields
Field Name | Type | Description
---|:---:|---
<a name="referenceRef"></a>$ref | `string` | **REQUIRED**. The reference identifier. This MUST be in the form of a URI, with a prefix of `#/components/inputs` or `#/components/parameters`.
<a name="referenceValue"></a>value | `string` | The value of the Input or Parameter which by default SHOULD override that of the referenced component.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a dramatic departure from how $ref is used in every other specification I've seen, and will cause problems with anyone trying to use standard tooling. In particular, if this is done with $ref inside of schemas, you will not be able to use standard draft 2020-12 JSON Schema implementations, which was the main reason that OAS 3.1 adopted 2020-12 in full.

I'm kind of dropping in here without context- is there somewhere I can read up on the reason for this usage? don't see any discussion of it in the referenced issue.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably makes sense to discuss at our meeting this coming Wednesday, can you make it? Also, might be worth taking a look at the pet store example which I've marked up in this PR, that should at least convey the intention of this use of $ref. But certainly open to hearing improvements.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to make the meeting. My main concern here is that this proposal seems to be a bit disconnected from the general history and usage of $ref. Support for $ref has been a challenge in the OAS tooling community, and has often been addressed by having standalone tools that understand $ref which are used in conjunction with OAS-specific tools. Adding substantially different behavior to $ref will break many, many things.


##### Reference Object Example

```json
{
"$ref": "#/components/parameters/page",
"value": 1
}
```

```yaml
"$ref": "#/components/parameters/page"
value: 1
```


### <a name="runtimeExpressions"></a>Runtime Expressions
A runtime expression allows values to be defined based on information that will be available within an HTTP message, an event message, and within objects serialized from the Workflows document such as [workflows](#workflow-object) or [steps](#step-object).

Expand Down