Repository: slack-go/slack
Pull request #1060 (2022-05-06 15:28:58)

add: workflows.stepCompleted and workflwows.stepFailed support
add support for the [workflows.stepCompleted](https://api.slack.com/methods/workflows.stepCompleted) and [workflows.stepFailed](https://api.slack.com/methods/workflows.stepFailed) 

using this API to indicate Slack that the workflow step is complete

kanata2: Please add description for your changes.

Patch:
diff --git a/messages.go b/messages.go
index 1a3110e..2cc31d5 100644
--- a/messages.go
+++ b/messages.go
@@ -131,8 +131,6 @@ type Msg struct {
 
 	// Block type Message
 	Blocks Blocks `json:"blocks,omitempty"`
-	// permalink
-	Permalink string `json:"permalink,omitempty"`
 }
 
 const (
diff --git a/users.go b/users.go
index d22b44f..8731156 100644
--- a/users.go
+++ b/users.go
@@ -292,13 +292,6 @@ func GetUsersOptionPresence(n bool) GetUsersOption {
 	}
 }
 
-// GetUsersOptionTeamID include team Id
-func GetUsersOptionTeamID(teamId string) GetUsersOption {
-	return func(p *UserPagination) {
-		p.teamId = teamId
-	}
-}
-
 func newUserPagination(c *Client, options ...GetUsersOption) (up UserPagination) {
 	up = UserPagination{
 		c:     c,
@@ -317,7 +310,6 @@ type UserPagination struct {
 	Users        []User
 	limit        int
 	presence     bool
-	teamId       string
 	previousResp *ResponseMetadata
 	c            *Client
 }
@@ -352,7 +344,6 @@ func (t UserPagination) Next(ctx context.Context) (_ UserPagination, err error)
 		"presence":       {strconv.FormatBool(t.presence)},
 		"token":          {t.c.token},
 		"cursor":         {t.previousResp.Cursor},
-		"team_id":        {t.teamId},
 		"include_locale": {strconv.FormatBool(true)},
 	}
 
@@ -373,13 +364,13 @@ func (api *Client) GetUsersPaginated(options ...GetUsersOption) UserPagination {
 }
 
 // GetUsers returns the list of users (with their detailed information)
-func (api *Client) GetUsers(options ...GetUsersOption) ([]User, error) {
-	return api.GetUsersContext(context.Background(), options...)
+func (api *Client) GetUsers() ([]User, error) {
+	return api.GetUsersContext(context.Background())
 }
 
 // GetUsersContext returns the list of users (with their detailed information) with a custom context
-func (api *Client) GetUsersContext(ctx context.Context, options ...GetUsersOption) (results []User, err error) {
-	p := api.GetUsersPaginated(options...)
+func (api *Client) GetUsersContext(ctx context.Context) (results []User, err error) {
+	p := api.GetUsersPaginated()
 	for err == nil {
 		p, err = p.Next(ctx)
 		if err == nil {
diff --git a/workflow_step_execute.go b/workflow_step_execute.go
new file mode 100644
index 0000000..18516f2
--- /dev/null
+++ b/workflow_step_execute.go
@@ -0,0 +1,85 @@
+package slack
+
+import (
+	"context"
+	"encoding/json"
+)
+
+type (
+	WorkflowStepCompletedRequest struct {
+		WorkflowStepExecuteID string            `json:"workflow_step_execute_id"`
+		Outputs               map[string]string `json:"outputs"`
+	}
+
+	WorkflowStepFailedRequest struct {
+		WorkflowStepExecuteID string `json:"workflow_step_execute_id"`
+		Error                 struct {
+			Message string `json:"message"`
+		} `json:"error"`
+	}
+)
+
+type WorkflowStepCompletedRequestOption func(opt WorkflowStepCompletedRequest) error
+
+func WorkflowStepCompletedRequestOptionOutput(outputs map[string]string) WorkflowStepCompletedRequestOption {
+	return func(opt WorkflowStepCompletedRequest) error {
+		if len(outputs) > 0 {
+			opt.Outputs = outputs
+		}
+		return nil
+	}
+}
+
+// WorkflowStepCompleted indicates step is completed
+func (api *Client) WorkflowStepCompleted(workflowStepExecuteID string, options ...WorkflowStepCompletedRequestOption) error {
+	// More information: https://api.slack.com/methods/workflows.stepCompleted
+	r := WorkflowStepCompletedRequest{
+		WorkflowStepExecuteID: workflowStepExecuteID,
+	}
+	for _, option := range options {
+		option(r)
+	}
+
+	endpoint := api.endpoint + "workflows.stepCompleted"
+	jsonData, err := json.Marshal(r)
+	if err != nil {
+		return err
+	}
+
+	response := &SlackResponse{}
+	if err := postJSON(context.Background(), api.httpclient, endpoint, api.token, jsonData, response, api); err != nil {
+		return err
+	}
+
+	if !response.Ok {
+		return response.Err()
+	}
+
+	return nil
+}
+
+// WorkflowStepFailed indicates step is failed
+func (api *Client) WorkflowStepFailed(workflowStepExecuteID string, errorMessage string) error {
+	// More information: https://api.slack.com/methods/workflows.stepFailed
+	r := WorkflowStepFailedRequest{
+		WorkflowStepExecuteID: workflowStepExecuteID,
+	}
+	r.Error.Message = errorMessage
+
+	endpoint := api.endpoint + "workflows.stepFailed"
+	jsonData, err := json.Marshal(r)
+	if err != nil {
+		return err
+	}
+
+	response := &SlackResponse{}
+	if err := postJSON(context.Background(), api.httpclient, endpoint, api.token, jsonData, response, api); err != nil {
+		return err
+	}
+
+	if !response.Ok {
+		return response.Err()
+	}
+
+	return nil
+}


Test patch:
diff --git a/workflow_step_execute_test.go b/workflow_step_execute_test.go
new file mode 100644
index 0000000..60c21c8
--- /dev/null
+++ b/workflow_step_execute_test.go
@@ -0,0 +1,35 @@
+package slack
+
+import (
+	"encoding/json"
+	"net/http"
+	"testing"
+)
+
+func workflowStepHandler(rw http.ResponseWriter, r *http.Request) {
+	rw.Header().Set("Content-Type", "application/json")
+	response, _ := json.Marshal(SlackResponse{
+		Ok: true,
+	})
+	rw.Write(response)
+}
+
+func TestWorkflowStepCompleted(t *testing.T) {
+	http.HandleFunc("/workflows.stepCompleted", workflowStepHandler)
+	once.Do(startServer)
+	api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
+
+	if err := api.WorkflowStepCompleted("executeID"); err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	}
+}
+
+func TestWorkflowStepFailed(t *testing.T) {
+	http.HandleFunc("/workflows.stepFailed", workflowStepHandler)
+	once.Do(startServer)
+	api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
+
+	if err := api.WorkflowStepFailed("executeID", "error message"); err != nil {
+		t.Errorf("Unexpected error: %s", err)
+	}
+}