mirror of https://github.com/harness/drone.git
112 lines
3.3 KiB
Go
112 lines
3.3 KiB
Go
// Copyright 2023 Harness, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package githook
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/base64"
|
|
"encoding/gob"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
const (
|
|
// envNamePayload defines the environment variable name used to send the payload to githook binary.
|
|
envNamePayload = "GIT_HOOK_PAYLOAD"
|
|
)
|
|
|
|
var (
|
|
// ErrEnvVarNotFound is an error that is returned in case the environment variable isn't found.
|
|
ErrEnvVarNotFound = errors.New("environment variable not found")
|
|
)
|
|
|
|
// GenerateEnvironmentVariables generates the environment variables that should be used when calling git
|
|
// to ensure the payload will be available to the githook cli.
|
|
func GenerateEnvironmentVariables(payload any) (map[string]string, error) {
|
|
// serialize the payload
|
|
payloadBuff := &bytes.Buffer{}
|
|
encoder := gob.NewEncoder(payloadBuff)
|
|
if err := encoder.Encode(payload); err != nil {
|
|
return nil, fmt.Errorf("failed to encode payload: %w", err)
|
|
}
|
|
|
|
// send it as base64 to avoid issues with any problematic characters
|
|
// NOTE: this will blow up the payload by ~33%, though it's not expected to be too big.
|
|
// On the other hand, we save a lot of size by only needing one environment variable name.
|
|
payloadBase64 := base64.StdEncoding.EncodeToString(payloadBuff.Bytes())
|
|
|
|
return map[string]string{
|
|
envNamePayload: payloadBase64,
|
|
}, nil
|
|
}
|
|
|
|
// LoadPayloadFromMap loads the payload from a map containing environment variables in a map format.
|
|
func LoadPayloadFromMap[T any](envVars map[string]string) (T, error) {
|
|
var payload T
|
|
|
|
// retrieve payload from environment variables
|
|
payloadBase64, ok := envVars[envNamePayload]
|
|
if !ok {
|
|
return payload, ErrEnvVarNotFound
|
|
}
|
|
|
|
return decodePayload[T](payloadBase64)
|
|
}
|
|
|
|
// LoadPayloadFromEnvironment loads the githook payload from the environment.
|
|
func LoadPayloadFromEnvironment[T any]() (T, error) {
|
|
var payload T
|
|
|
|
// retrieve payload from environment variables
|
|
payloadBase64, err := getEnvironmentVariable(envNamePayload)
|
|
if err != nil {
|
|
return payload, fmt.Errorf("failed to load payload from environment variables: %w", err)
|
|
}
|
|
|
|
return decodePayload[T](payloadBase64)
|
|
}
|
|
|
|
func decodePayload[T any](encodedPayload string) (T, error) {
|
|
var payload T
|
|
// decode base64
|
|
payloadBytes, err := base64.StdEncoding.DecodeString(encodedPayload)
|
|
if err != nil {
|
|
return payload, fmt.Errorf("failed to base64 decode payload: %w", err)
|
|
}
|
|
|
|
// deserialize the payload
|
|
decoder := gob.NewDecoder(bytes.NewReader(payloadBytes))
|
|
err = decoder.Decode(&payload)
|
|
if err != nil {
|
|
return payload, fmt.Errorf("failed to deserialize payload: %w", err)
|
|
}
|
|
|
|
return payload, nil
|
|
}
|
|
|
|
func getEnvironmentVariable(name string) (string, error) {
|
|
val, ok := os.LookupEnv(name)
|
|
if !ok {
|
|
return "", ErrEnvVarNotFound
|
|
}
|
|
|
|
if val == "" {
|
|
return "", fmt.Errorf("'%s' found in env but it's empty", name)
|
|
}
|
|
|
|
return val, nil
|
|
}
|