Executando verificação de segurança...
1

[Dúvida] GitHub Actions

Olá a todos!

Estou atualmente explorando o uso de scripts em Shell (sh) para automatizar processos, especialmente aqueles relacionados à gestão de ambientes no GitHub. O objetivo é agilizar e tornar mais eficiente a criação de ambientes, como o "prod", e a configuração de variáveis dentro desses ambientes.

Estou com os seguintes problemas:

Dificuldade na criação da Environment "prod" via script: O script atual enfrenta dificuldades ao tentar criar automaticamente a Environment "prod". No entanto, se eu criar manualmente a Environment e, em seguida, executar o script, ele consegue adicionar com sucesso as variáveis, conforme especificado na lista de segredos ("teste:1", "var:2").
Limitação na criação de variáveis não secretas: Além disso, tentei de algumas formas fazer com que o script realize a adição de variáveis não secretas, possibilitando a inclusão de variáveis públicas ou não sensíveis. Porém não consegui encontrar um meio para adicionar elas.

Esses problemas representam obstáculos para a automação eficiente do processo de configuração de ambientes no GitHub. Vou continuar a explorar e aprimorar o código para superar essas limitações e tornar a automação mais robusta e versátil.

Se alguém tiver alguma sugestão ou experiência semelhante para compartilhar, seria muito bem-vinda!

#!/bin/bash 

REPO_OWNER="REPO_OWNER"
REPO_NAME="REPO_NAME"
TOKEN="TOKEN"

base64_encode() {
    echo -n "$1" | base64
}

create_environment_if_not_exists() {
    local environments_url="https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments"
    local response=$(curl -s -H "Authorization: token $TOKEN" "$environments_url")
    if ! echo "$response" | grep -q "id"; then
        echo "Não existem ambientes definidos para este repositório. Criando o ambiente 'prod'..."
        response=$(curl -X POST \
            -H "Authorization: token $TOKEN" \
            -H "Accept: application/vnd.github.antiope-preview+json" \
            -H "Content-Type: application/json" \
            -d '{"name": "prod"}' \
            "$environments_url")
        if ! echo "$response" | grep -q "id"; then
            local message=$(echo "$response" | jq -r '.message')
            echo "Erro ao criar a environment 'prod': $message"
            exit 1
        fi
        echo "Ambiente 'prod' criado com sucesso."
    else
        echo "Ambientes já existem para este repositório."
    fi
}

add_secret_to_environment() {
    local name=$1
    local value=$2

    echo "Adicionando a secret '$name' com valor '$value' ao ambiente 'prod'..."

    local encoded_value=$(base64_encode "$value")

    local key_id=$(curl -s -X GET \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/actions/secrets/public-key" | jq -r '.key_id')

    local response=$(curl -X PUT \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        -d "{\"encrypted_value\": \"$encoded_value\", \"key_id\": \"$key_id\"}" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/secrets/$name")

    local status=$(echo "$response" | jq -r '.status')
    if [ "$status" != "204" ]; then
        local message=$(echo "$response" | jq -r '.message')
        echo "Erro ao adicionar a secret '$name': $message"
        exit 1
    fi

    echo "$encoded_value"
}

add_public_to_environment() {
    local name=$1
    local value=$2

    echo "Adicionando a secret '$name' com valor '$value' ao ambiente 'prod'..."

    local encoded_value=$(base64_encode "$value")

    local key_id=$(curl -s -X GET \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/actions/secrets/public-key" | jq -r '.key_id')

    local response=$(curl -X PUT \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        -d "{\"encrypted_value\": \"$encoded_value\", \"key_id\": \"$key_id\"}" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/secrets/$name")

    local status=$(echo "$response" | jq -r '.status')
    if [ "$status" != "204" ]; then
        local message=$(echo "$response" | jq -r '.message')
        echo "Erro ao adicionar a secret '$name': $message"
        exit 1
    fi

    echo "$encoded_value"
}

secrets=("teste:1" "var:2")

for secret in "${secrets[@]}"; do

    echo "Processando secret: $secret"

    IFS=':' read -r name value <<< "$secret"

    echo "Nome: $name"
    echo "Valor (antes de adicionar): $value"

    value=$(add_secret_to_environment "$name" "$value")

    echo "Valor (após adicionar): $value"
done

1

Oi Cassiel, tudo bem? Vou tentar te ajudar :smille: :)

Lendo a documentação, acredito que seu erro seja uma coisa bem besta hahahaha.

tem um trecho no seu código que está escrito:

response=$(curl -X POST \
            -H "Authorization: token $TOKEN" \
            -H "Accept: application/vnd.github.antiope-preview+json" \
            -H "Content-Type: application/json" \
            -d '{"name": "prod"}' \
            "$environments_url")

Onde você pode verificar que está utilizando o método POST, mas esse endpoint da API aceita somente PUT e também tem um segundo problema que o seu header de Accept está com o conteúdo Accept: application/vnd.github.antiope-preview+json, sendo que deveria estar assim: Accept: application/vnd.github+json. Olhando melhor aqui, percebo que tem vários problemas na chamada.

Vou deixar aqui um exemplo de como o GitHub mostra na documentação:

curl -L \
  -X PUT \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <YOUR-TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/OWNER/REPO/environments/ENVIRONMENT_NAME \
  -d '{"wait_timer":30,"prevent_self_review":false,"reviewers":[{"type":"User","id":1},{"type":"Team","id":1}],"deployment_branch_policy":{"protected_branches":false,"custom_branch_policies":true}}'

Espero ter ajudado, tmj!

1

Opa muito obrigado
Após a correção fiz mais alguns ajustes!!

ainda não está 100%, porém está funcional, falta melhorar pra deixar o processo o mais automatizado possivel...

ficou do seguinte modo!! se um dia for util pra voce :smille: :)

#!/bin/bash

# Definição das variáveis
REPO_OWNER="EU"
REPO_NAME="repositorio"
TOKEN="token_git"

base64_encode() {
    echo -n "$1" | base64
}

print_progress_bar() {
    local width=50
    local current=$1
    local total=$2
    local progress=$((current * width / total))
    printf "["
    for ((i = 0; i < width; i++)); do
        if ((i <= progress)); then
            printf "="
        else
            printf " "
        fi
    done
    printf "] %d%%\r" $((current * 100 / total))
}

create_environment_if_not_exists() {
    local environments_url="https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments"
    local response=$(curl -s -H "Authorization: token $TOKEN" "$environments_url")
    
    # Verificar se o ambiente 'prod' existe na resposta
    if [[ "$response" == *"\"name\": \"prod\""* ]]; then
        echo "Ambiente 'prod' já existe para este repositório."
    else
        echo "O ambiente 'prod' não existe. Criando o ambiente..."
       response=$(curl -s -w "%{http_code}" -X PUT \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.antiope-preview+json" \
        -H "Content-Type: application/json" \
        "$environments_url/prod")
        local status=${response: -3}
        echo "Status: $status"
        if [ "$status" != "200" ]; then
            echo "Erro ao criar o ambiente 'prod'. Status: $status"
            exit 1
        fi
        echo "Ambiente 'prod' criado com sucesso."
    fi
}


add_secret_to_environment() {
    local name=$1
    local value=$2

    local encoded_value=$(base64_encode "$value")

    local key_id=$(curl -s -X GET \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/actions/secrets/public-key" | jq -r '.key_id')

    local response=$(curl -s -w "%{http_code}" -o /dev/null -X PUT \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        -d "{\"encrypted_value\": \"$encoded_value\", \"key_id\": \"$key_id\"}" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/secrets/$name")

    local status=${response: -3}

    if [ "$status" != "204" ] && [ "$status" != "200" ] && [ "$status" != "201" ]; then
        echo "Erro ao adicionar a secret '$name'. Status: $status"
    fi

    local progress=$((current_secret * 100 / total_secrets))
    echo -ne "Adicionando secrets: $progress%\r"
}

add_variable_to_environment() {
    local name=$1
    local value=$2

    local existing_var=$(curl -s -X GET \
        -H "Authorization: token $TOKEN" \
        -H "Accept: application/vnd.github.v3+json" \
        "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/variables/$name")

    if [[ "$existing_var" == *"Not Found"* ]]; then
        local add_response=$(curl -s -w "%{http_code}" -o /dev/null -X POST \
            -H "Authorization: token $TOKEN" \
            -H "Accept: application/vnd.github.v3+json" \
            -d "{\"name\": \"$name\", \"value\": \"$value\"}" \
            "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/variables")

        local status=${add_response: -3}

        if [ "$status" != "204" ] && [ "$status" != "200" ] && [ "$status" != "201" ]; then
            echo "Erro ao adicionar a variável '$name'. Status: $status"
        fi
    else
        local update_response=$(curl -s -w "%{http_code}" -o /dev/null -X PATCH \
            -H "Authorization: token $TOKEN" \
            -H "Accept: application/vnd.github.v3+json" \
            -d "{\"value\": \"$value\"}" \
            "https://api.github.com/repos/$REPO_OWNER/$REPO_NAME/environments/prod/variables/$name")

        local status=${update_response: -3}

        if [ "$status" != "204" ]; then
            echo "Erro ao atualizar a variável '$name'. Status: $status"
        fi
    fi

    if [ "$status" == "204" ] || [ "$status" == "200" ] || [ "$status" == "201" ]; then
        local progress=$((current_variable * 100 / total_variables))
        echo -ne "Adicionando variáveis: $progress%\r"
    else
        echo -ne "\r\033[K"
    fi

    if [ "$current_variable" -eq "$total_variables" ]; then
        echo "Adição de variáveis concluída."
    fi
}

secrets=(
"SECRET_1:SECRET_1_VALUE"
"SECRET_2:SECRET_2_VALUE"
"SECRET_3:SECRET_3_VALUE"
)


total_secrets=${#secrets[@]}
current_secret=0

echo "Criando ambiente 'prod'..."

create_environment_if_not_exists

echo "Adicionando secrets..."

for secret in "${secrets[@]}"; do
    ((current_secret++))
    IFS=':' read -r name value <<< "$secret"

    add_secret_to_environment "$name" "$value"

    print_progress_bar $current_secret $total_secrets
done

echo "Adição de secrets concluída."

variables=(
"VARIABLE_1:VARIABLE_1_VALUE"
"VARIABLE_2:VARIABLE_2_VALUE"
"VARIABLE_3:VARIABLE_3_VALUE"
)

total_variables=${#variables[@]}
current_variable=0

echo "Adicionando variáveis..."

for variable in "${variables[@]}"; do
    IFS=':' read -r name value <<< "$variable"

    add_variable_to_environment "$name" "$value"

    print_progress_bar $((++current_variable)) $total_variables
done
echo "Adição de variáveis concluída."