[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

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!

**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." ```