From 831f0aa578b692c68664629df7d1eae64981fcf9 Mon Sep 17 00:00:00 2001 From: Georges Jamous Date: Tue, 5 Jul 2022 17:59:23 +0200 Subject: [PATCH] Export thread timestamp (#82) * adding new "created_thread_ts_env_name" flag * cleaning up the code * fixing code and adding log * code cleanup * Update outputs.go * Update outputs.go with proper function comments Co-authored-by: Isaac Halvorson * Update outputs.go with proper variable naming Co-authored-by: Isaac Halvorson * code fix variable name. * Handle error from exportOutputs method Co-authored-by: Isaac Halvorson --- main.go | 19 +++++++++++----- outputs.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ step.yml | 9 ++++++++ 3 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 outputs.go diff --git a/main.go b/main.go index 1c26ba6..36a7cd0 100644 --- a/main.go +++ b/main.go @@ -58,6 +58,9 @@ type Config struct { TimeStamp bool `env:"timestamp,opt[yes,no]"` Fields string `env:"fields"` Buttons string `env:"buttons"` + + // Step Outputs + ThreadTsOutputVariableName string `env:"output_thread_ts"` } // success is true if the build is successful, false otherwise. @@ -103,12 +106,12 @@ func newMessage(c Config) Message { FooterIcon: c.FooterIcon, Buttons: parseButtons(c.Buttons), }}, - IconEmoji: selectValue(c.IconEmoji, c.IconEmojiOnError), - IconURL: selectValue(c.IconURL, c.IconURLOnError), - LinkNames: c.LinkNames, - Username: selectValue(c.Username, c.UsernameOnError), - ThreadTs: selectValue(c.ThreadTs, c.ThreadTsOnError), - ReplyBroadcast: selectBool(c.ReplyBroadcast, c.ReplyBroadcastOnError), + IconEmoji: selectValue(c.IconEmoji, c.IconEmojiOnError), + IconURL: selectValue(c.IconURL, c.IconURLOnError), + LinkNames: c.LinkNames, + Username: selectValue(c.Username, c.UsernameOnError), + ThreadTs: selectValue(c.ThreadTs, c.ThreadTsOnError), + ReplyBroadcast: selectBool(c.ReplyBroadcast, c.ReplyBroadcastOnError), } if c.TimeStamp { msg.Attachments[0].TimeStamp = int(time.Now().Unix()) @@ -156,6 +159,10 @@ func postMessage(conf Config, msg Message) error { return fmt.Errorf("server error: %s, response: %s", resp.Status, body) } + if err := exportOutputs(&conf, resp); err != nil { + return fmt.Errorf("failed to export outputs: %s", err) + } + return nil } diff --git a/outputs.go b/outputs.go new file mode 100644 index 0000000..a47a7f2 --- /dev/null +++ b/outputs.go @@ -0,0 +1,66 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + "os/exec" + "strings" + + "github.com/bitrise-io/go-utils/log" +) + +// SendMessageResponse is the response from Slack POST +type SendMessageResponse struct { + /// The Thread Timestamp + Timestamp string `json:"ts"` +} + +/// Export the output variables after a successful response +func exportOutputs(conf *Config, resp *http.Response) error { + + if !isRequestingOutput(conf) { + log.Debugf("Not requesting any outputs") + return nil + } + + isWebhook := strings.TrimSpace(selectValue(string(conf.WebhookURL), string(conf.WebhookURLOnError))) != "" + + // Slack webhooks do not return any useful response information + if isWebhook { + return fmt.Errorf("For output support, do not submit a WebHook URL") + } + + var response SendMessageResponse + parseError := json.NewDecoder(resp.Body).Decode(&response) + if parseError != nil { + // here we want to fail, because the user is expecting an output + return fmt.Errorf("Failed to parse response: %s", parseError) + } + + if string(conf.ThreadTsOutputVariableName) != "" { + log.Debugf("Exporting output: %s=%s\n", string(conf.ThreadTsOutputVariableName), response.Timestamp) + err := exportEnvVariable(string(conf.ThreadTsOutputVariableName), response.Timestamp) + if err != nil { + return err + } + } + + return nil + +} + +/// Checks if we are requesting an output of anything +func isRequestingOutput(conf *Config) bool { + return string(conf.ThreadTsOutputVariableName) != "" +} + +/// Exports env using envman +func exportEnvVariable(variable string, value string) error { + c := exec.Command("envman", "add", "--key", variable, "--value", value) + err := c.Run() + if err != nil { + return fmt.Errorf("Failed to run envman %s", err) + } + return nil +} diff --git a/step.yml b/step.yml index d3697c7..d117210 100644 --- a/step.yml +++ b/step.yml @@ -350,3 +350,12 @@ inputs: The *text* is the label for the button. The *url* is the fully qualified http or https url to deliver users to. An attachment may contain 1 to 5 buttons. + +# Step Outputs + + - output_thread_ts: + opts: + title: The newly created thread timestamp environment variable name + description: Will export the created thread's timestamp to the environment with the supplied name (if not already in thread) + is_required: false + is_sensitive: false \ No newline at end of file