J'ai un AWS CodePipeline qui invoque CodeBuild dans la phase de construction.
La question est de savoir comment passer une variable d'environnement de CodePipeline qui peut être lue dans le buildspec.yml de CodeBuild?
Je sais que je peux définir des variables d'environnement dans CodeBuild, mais je veux utiliser le même projet CodeBuild pour les environnements dev, qa et prod. Je ne vois pas comment je peux passer une variable d'environnement de CodePipeline qui fait tout le chemin vers le buildspec.yml
Exemple buildspec.yml
version: 0.1
phases:
build:
commands:
- npm install
- npm build -- --env ${CURRENT_ENVIRONMENT}
Où CURRENT_ENVIRONMENT serait la variable que j'ai définie dans l'action de l'étape CodePipeline.
Cette fonctionnalité n'est pas disponible aujourd'hui.
Une solution de contournement serait de créer un projet CodeBuild différent pour chaque étape avec différentes variables d'environnement.
Vous pouvez trouver des détails sur l'utilisation d'une variable d'environnement dans vos commandes builspec.yml ici: http://docs.aws.Amazon.com/codebuild/latest/userguide/build-spec-ref.html
Vous pouvez réellement passer les variables d'environnement dans CodeBuild cloudformation comme ci-dessous:
Build:
Type: AWS::CodeBuild::Project
Properties:
Name:
!Sub Build-${AWS::StackName}
Description: Build your project
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: node8
EnvironmentVariables:
- Name: CURRENT_ENVIRONMENT
Type: PLAINTEXT
Value: staging
Et dans votre buildspec.yml
vous pouvez référencer l'environnement comme ceci,
version: 0.2
phases:
install:
commands:
- npm install
build:
commands:
- npm build -- --env ${CURRENT_ENVIRONMENT}
Si vous ne souhaitez pas utiliser CF, vous pouvez définir des variables ENV sur votre projet CodeBuild dans l'interface utilisateur AWS.
Dans AWS, accédez à votre projet de générateur de code, dans le coin supérieur droit, cliquez sur "modifier" et sélectionnez "environnement". Sur la page d'édition de l'environnement, cliquez sur le menu déroulant "Configuration supplémentaire". Vous y verrez des entrées pour "nom" et "valeur". "Nom" est l'endroit où vous définissez votre ENV et "valeur" est l'endroit où vous définissez votre valeur pour cette variable.
Exemple: définissez API_ENV
dans "nom" et development
dans "valeur". Ensuite, dans votre buildspec.yml, vous pouvez utiliser $ API_ENV.
Vous pouvez utiliser construire des variables d'environnement pour passer conditionnellement de buildspec à npm build
en détectant le travail CodeBuild ou le travail CodePipeline en cours d'exécution. Si vous avez un CodePipeline écoutant les validations/dev et un autre écoutant les validations/master, par exemple, cela fonctionne parfaitement.
Voici un exemple qui exécute une version PROD vs DEV différente:
build:
commands:
- |
if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProjectDev-" >/dev/null; then
yarn run build-dev;
fi
- |
if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProject-" >/dev/null; then
yarn run build-prod;
fi
J'ai créé un petit script python pour analyser le $CODEBUILD_INITIATOR
variable transmise. Ci-dessous se trouve le buildspec.yml et en dessous se trouve le script python que j'inclus avec la build et l'appel.
build:
commands:
- |
PIPELINE_ENV=$(python3 codebuild_env_parser.py $CODEBUILD_INITIATOR)
OUTPUT_STATUS=$?
if [ "$OUTPUT_STATUS" = "0" ]; then
echo "Success finding a valid environment from codebuild_env_parser.py."
else
echo "Failure finding a valid environment from codebuild_env_parser.py. Check the script to see if the codepipeline env was passed correctly."
fi
Script Python (codebuild_env_parser.py
):
import sys
def main():
args = sys.argv
if len(args) == 2:
env_list = ["dev", "prod"]
pipeline_invoker = args[1].lower()
code_pipeline_name = pipeline_invoker.split("codepipeline/")[1]
env_name = code_pipeline_name.split("-project-name")[0]
if env_name in env_list:
print("{}".format(env_name))
sys.exit(0)
else:
sys.exit(1)
else:
sys.exit(1)
main()
Vous devrez ajuster quelques valeurs de variables ici si vous voulez que cela fonctionne. À savoir, "-project-name"
.
J'ai créé une fonction lambda qui met à jour les variables d'environnement d'un projet de construction de code existant. Vous pouvez démarrer la génération (codebuild.start) après avoir mis à jour les variables. Ressemble à quelque chose comme ça (nodejs):
var params = {
"name": "Build-project-name",
"description": "Build this project.",
"environment": {
"type": "LINUX_CONTAINER",
"image": "aws/codebuild/standard:1.0",
"computeType": "BUILD_GENERAL1_LARGE",
"environmentVariables": [
{
"name": "MY_ENVIRONMENT_VARIABLE",
"value": "VALUE_OF_ENVIRONMENT_VARIABLE",
"type": "PLAINTEXT"
}]
}
}
codebuild.updateProject(params, function(err, data) {
if (err) {
console.log(err, err.stack); // an error occurred
}
else {
console.log(data); // successful response
}
});
L'initiateur CodeBuild est une variable d'environnement dans CodeBuild et cela peut être utilisé pour lire le nom CodePipeline.
Donc, si vous incluez votre environnement dans votre nom CodePipeline en tant que suffixe (-dev ou -prod, par exemple), vous pouvez l'analyser de cette façon.
version: 0.2
phases:
build:
commands:
- CURRENT_ENVIRONMENT=`echo $CODEBUILD_INITIATOR | cut -d '-' -f2 | tr '[:upper:]' '[:lower:]'`
- echo "My env is $CURRENT_ENVIRONMENT"