github.com/smartcontractkit/chainlink-testing-framework/libs@v0.0.0-20240227141906-ec710b4eb1a3/testreporters/slack_notification.go (about)

     1  // Package testreporters holds all the tools necessary to report on tests that are run utilizing the testsetups package
     2  package testreporters
     3  
     4  import (
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  
     9  	"github.com/rs/zerolog/log"
    10  	"github.com/slack-go/slack"
    11  
    12  	"github.com/smartcontractkit/chainlink-testing-framework/libs/k8s/config"
    13  )
    14  
    15  // Common Slack Notification Helpers
    16  
    17  // Values for reporters to use slack to notify user of test end
    18  var (
    19  	SlackAPIKey  = os.Getenv(config.EnvVarSlackKey)
    20  	SlackChannel = os.Getenv(config.EnvVarSlackChannel)
    21  	SlackUserID  = os.Getenv(config.EnvVarSlackUser)
    22  )
    23  
    24  // Uploads a slack file to the designated channel using the API key
    25  func UploadSlackFile(slackClient *slack.Client, uploadParams slack.FileUploadParameters) error {
    26  	log.Info().
    27  		Str("Slack API Key", SlackAPIKey).
    28  		Str("Slack Channel", SlackChannel).
    29  		Str("User Id to Notify", SlackUserID).
    30  		Str("File", uploadParams.File).
    31  		Msg("Attempting to upload file")
    32  	if SlackAPIKey == "" {
    33  		return fmt.Errorf("unable to upload file without a Slack API Key")
    34  	}
    35  	if SlackChannel == "" {
    36  		return fmt.Errorf("unable to upload file without a Slack Channel")
    37  	}
    38  	if uploadParams.Channels == nil || uploadParams.Channels[0] == "" {
    39  		uploadParams.Channels = []string{SlackChannel}
    40  	}
    41  	if uploadParams.File != "" {
    42  		if _, err := os.Stat(uploadParams.File); errors.Is(err, os.ErrNotExist) {
    43  			return fmt.Errorf("unable to upload file as it does not exist: %w", err)
    44  		} else if err != nil {
    45  			return err
    46  		}
    47  	}
    48  	_, err := slackClient.UploadFile(uploadParams)
    49  	return err
    50  }
    51  
    52  // Sends a slack message, and returns an error and the message timestamp
    53  func SendSlackMessage(slackClient *slack.Client, msgOptions ...slack.MsgOption) (string, error) {
    54  	log.Info().
    55  		Str("Slack API Key", SlackAPIKey).
    56  		Str("Slack Channel", SlackChannel).
    57  		Msg("Attempting to send message")
    58  	if SlackAPIKey == "" {
    59  		return "", fmt.Errorf("unable to send message without a Slack API Key")
    60  	}
    61  	if SlackChannel == "" {
    62  		return "", fmt.Errorf("unable to send message without a Slack Channel")
    63  	}
    64  	msgOptions = append(msgOptions, slack.MsgOptionAsUser(true))
    65  	_, timeStamp, err := slackClient.PostMessage(SlackChannel, msgOptions...)
    66  	return timeStamp, err
    67  }
    68  
    69  // creates a directory if it doesn't already exist
    70  func MkdirIfNotExists(dirName string) error {
    71  	if _, err := os.Stat(dirName); os.IsNotExist(err) {
    72  		if err = os.MkdirAll(dirName, os.ModePerm); err != nil {
    73  			return fmt.Errorf("failed to create directory: %s err: %w", dirName, err)
    74  		}
    75  	}
    76  	return nil
    77  }
    78  
    79  func CommonSlackNotificationBlocks(
    80  	headerText, namespace,
    81  	reportCsvLocation string,
    82  ) []slack.Block {
    83  	return SlackNotifyBlocks(headerText, namespace, []string{
    84  		fmt.Sprintf("Summary CSV created on _remote-test-runner_ at _%s_\nNotifying <@%s>",
    85  			reportCsvLocation, SlackUserID)})
    86  }
    87  
    88  // SlackNotifyBlocks creates a slack payload and writes into the specified json
    89  func SlackNotifyBlocks(headerText, namespace string, msgtext []string) []slack.Block {
    90  	var notificationBlocks slack.Blocks
    91  	notificationBlocks.BlockSet = append(notificationBlocks.BlockSet,
    92  		slack.NewHeaderBlock(slack.NewTextBlockObject("plain_text", headerText, true, false)))
    93  	notificationBlocks.BlockSet = append(notificationBlocks.BlockSet,
    94  		slack.NewContextBlock("context_block", slack.NewTextBlockObject("plain_text", namespace, false, false)))
    95  	notificationBlocks.BlockSet = append(notificationBlocks.BlockSet, slack.NewDividerBlock())
    96  	msgtexts := ""
    97  	for _, text := range msgtext {
    98  		msgtexts = fmt.Sprintf("%s%s\n", msgtexts, text)
    99  	}
   100  	notificationBlocks.BlockSet = append(notificationBlocks.BlockSet, slack.NewSectionBlock(slack.NewTextBlockObject("mrkdwn",
   101  		msgtexts, false, true), nil, nil))
   102  	return notificationBlocks.BlockSet
   103  }