ï¼ã¨ã ã¹ãªã¼ Advent Calendar 2020 ã¾ã§æ®ã4æ¥ã¨ãªãã¾ãããæ°åãããªãããæ¬ç·¨ãæ¸ããã©ãAdvent Calendaræ¬ç·¨ã«å ããã¦å·çãã¾ããï¼
ããã«ã¡ã¯ãã¨ã ã¹ãªã¼ã¨ã³ã¸ãã¢ãªã³ã°ã°ã«ã¼ãã®ç¦æ (@fukubaya) ã§ãã
ãã®è¨äºã¨ããã®è¨äºã§ æ¸ãã¦ããããã«ãå¼ç¤¾ã§ã¯ãªã³ãã¬ç°å¢ã§ç¨¼åãããµã¼ãã¹ã®AWSãGCPã¸ã®ç§»è¡ãé²è¡ä¸ã§ãã ããããªãµã¼ãã¹ããDockeråãã¦Fargateã§åãããã«ãªã£ã¦ããã®ã§ã ãããã®ãµã¼ãã¹ã®ãããã¤ã«ä½¿ãJenkinsãã³ã¼ã管çãã¦Fargateã§åãããããããã¦ãããã¤ã楽ã«ããããã¨ãã話ã§ãã
- éãã楽ã«ãã§ã確å®ã«ãããã¤ããã
- Google Formã¨JIRAã§æ¿èªããã¼ã®ç®¡çã¨è¨é²
- Jenkinséç¨ã®èª²é¡
- Dockerfileã®æ§æ
éãã楽ã«ãã§ã確å®ã«ãããã¤ããã
éçºãçããªãµã¼ãã¹ã»ã©ããããã¤ã®é »åº¦ãå¤ããªãã®ã§ã1åã®ãããã¤ã«ãããæéã¯ã§ããã ãæ¸ããããã§ãã ä¸æ¹ã§ãã¨ã«ããèªååãçååã ããç®æãã¨ãäºæ ã£ãæã®ãªã«ããªã調æ»ãé ãããå°é£ã«ãªãã¾ãã ç¹ã«ããµã¼ãã¹èªä½ãåºåãããã° ä»¥å¤ ã®è¨é²ã誰ããã¤å®è¡ããã®ããã©ãã¾ã§æåãã¦ã©ãã§å¤±æããã®ãããªã©ã®è¨é²ããªã«ããªã調æ»ã«ã¯å¿ è¦ã§ãã ããã«äºæ ãæªç¶ã«é²ãããã«ã¯ã権é管çãè¨å®ã®ç®¡çã¯å¿ é ã§ãã
以ä¸ã®èæ¯ãã以ä¸ã®è¦ä»¶ãæãã¾ããã
- éçºãå®æ½ããã¨ã³ã¸ãã¢ããããã¤ã®ä¾é ¼ããã
- å¿ è¦ãªãã©ã¡ã¼ã¿ã¯å¯è½ãªç¯å²ã§äºåã«æ¤è¨¼ãã¦ãææ»ããæ¸ãã
- ãããã¤ã®ä¾é ¼ã¯QAæ
å½è
ã®æ¿èªãå¿
é ã¨ãã
- QAæ å½è ãææ¡ããªããããã¤ã¯ãããªã
- ãããã¤ã®å®æ½ã¯ãã¼ã ã®SREæ
å½ã¡ã³ãã¼ã ããã§ãã
- 権éãããã¡ã³ãã¼ã®è¿½å ãåé¤ã¯å®¹æã«ã§ãã
- ãããã¤æã®è¨é²(ãã°)ãæ®ã
- ãããã¤æããããã¤å¾ã«é害ããã£ãæã«èª¿æ»ã§ããããã«ãããã
- ãããã¤ã®ããã®ã¹ã¯ãªãããã¸ã§ãã¯ã³ã¼ã管ç
- ç´ ã®Jenkinsã®ããã«éä¸æ¹å¤ãããªã
- ã§ããã°è¨å®ããã©ã°ã¤ã³ãã¸ã§ãå®ç¾©ã丸ãã¨å«ããDocker imageã«ããã
Google Formã¨JIRAã§æ¿èªããã¼ã®ç®¡çã¨è¨é²
æ¿èªããå®æ½ã¾ã§ã®ããã¼ç®¡çã¨è¨é²ã¯Google Formã¨JIRAã§å®æ½ãããã¨ã«ãã¾ããã
ä¾é ¼
Google Formã§ä¾é ¼ãä½æããæç¹ã§ãæ å½è ã¸ã®éç¥ã¨JIRAãã±ããã®ä½æãåæã«å®äºãã¾ãã
- ãããã¤ã®ä¾é ¼è ã¯ãGoogle Formã«å¿ è¦äºé ãè¨å ¥ãã¦ä¾é ¼ã
- Google Formã¸ã®éä¿¡ãããªã¬ã¼ã¨ãã¦ãAppScriptãå®è¡ããã
- ã¹ã¯ãªããå ã§QAæ å½è ããããã¤æ å½è ãã©ã³ãã ã§å²ãå½ã¦
- ãããã¤ä¾é ¼è èªèº«ãQAæ å½è ããããã¤æ å½è ã«ã¡ã¼ã«ã¨slackã§éç¥
- åæã«JIRAå°ç¨ã¢ãã¬ã¹ã«ãéä¿¡ãã¡ã¼ã«ãããã±ãããä½æããJIRAã®æ©è½ãå©ç¨ãã¦ãJIRAã«ä¾é ¼ãã±ãããã§ããã
cc:
ã®å é ã®ã¦ã¼ã¶ãæ å½è ã«æå®ã§ããæ©è½ãããã®ã§ãæ¿èªããQAæ å½è ãcc:
ã®å é ã«è¨å®ããã
ãã®JIRAãã±ããã«å¿ è¦ãªçµç·¯ãè¨é²ãªã©ãèªåãããã¯å¿ è¦ãªãæåã§è¨é²ãã¦ããã¾ãã
Google Formã§ã¯ãå ¥åå 容ã®ã«ã¼ã«ãæ£è¦è¡¨ç¾ã§æå®ã§ããã®ã§ãééã£ã¦å¤ãªå¤ãå ¥ãã®ãããç¨åº¦é²ããã¨ãã§ãã¾ãã
æ¿èª
QAæ å½è ã¯ãä¾é ¼å 容ã確èªããã¹ãã¼ã¿ã¹ããªãªã¼ã¹å¾ ã¡ã«å¤æ´ãã¦ããããã¤æ å½è ããã±ããã®æ å½è ã«å¤æ´ãããã¨ã§æ¿èªãå®äºãã¾ãã ãªãããã±ããã®ã¹ãã¼ã¿ã¹ã¯QAæ å½è (ã¨ãããã¤æ å½è )ã ããå¤æ´å¯è½ãªã®ã§ãä»ã®ã¡ã³ãã¼ãåæã«æ¿èªãããã¨ã¯ã§ãã¾ããã
å®æ½ã¨çµæã®è¨é²
ãããã¤æ å½è ã¯ãä¾é ¼æãããå 容ã«å¾ã£ã¦ãå¾è¿°ããJenkinsã§ã¸ã§ããå®è¡ãã¾ãã ãªããJenkinsã§ã¸ã§ããå®è¡ããéã«ãJIRAã®ãã±ããã®æå®ãå¿ é ã¨ãã¦ãã¾ãã ããã¯ãå®è¡ããçµæããã±ããã«èªåã§æ¸ãè¾¼ã(JIRAã¸ã®ã¡ã¼ã«éä¿¡ã§å®æ½ãã)ããã§ãã
Jenkinséç¨ã®èª²é¡
Jenkinsãã¯ã©ã¦ã(AWS)ã«æ§ç¯ããã«ããã£ã¦ã課é¡ã2ã¤ããã¾ããã
課é¡1: Fargateã ã¨Jenkinsã使ããªãã£ãåé¡
Jenkinsã¯ã¸ã§ãã®å®è¡çµæããææç©ããµã¼ãå ã«ãã¡ã¤ã«ã¨ãã¦ä¿åããã®ã§ã AWSã®å ´åãEC2ã«ç«ã¦ããECS on EC2ã使ãã®ãä¸è¬çã§ããã
ããããªãããFargate1.4ã§EFSã使ããããã«ãªã£ãã®ã§ã
EFS㧠/var/jenkins_home
ããã¦ã³ããã¦Fargateã§Jenkinsã使ããããã«ãªãã¾ããã
課é¡2: Jenkinsèªä½ã®è¨å®ããã©ã°ã¤ã³ãã¸ã§ãè¨å®ã©ã管çãããåé¡
Jenkinsã¯æ¬ä½ã®ãã©ã°ã¤ã³è¨å®ããã¸ã§ãã®è¨å®ãèªç±åº¦é«ãè¨å®ã§ããããã éç¨ãã¦ãããã¡ã«è¨å®ãå¤ãã£ã¦ãã£ã¦ãã¾ããåãç°å¢ãåç¾ãããã¨ãå°é£ã«ãªãã¾ãã åãç°å¢ãåç¾ã§ããªãã¨ãããã¨ã¯ã移è¨ãã§ããªãã§ããããã©ãã«æã®å¾©æ§ã調æ»ãå°é£ã§ãã ãããé¿ããããè¨å®ãã¸ã§ãå®ç¾©ãåºå®ããç°å¢ãåç¾ã§ããããã«ãããã§ãã
ä»åã¯ãJCasC(Jenkins Configuration as Code) pluginãç¨ãã¦è¨å®ã¯åºå®åãã ããã«ãã®è¨å®ãåæ ããDocker Imageãä½ãã¾ãã Jenkinsè¨å®æ¨©éãã¸ã§ãã®è¨å®æ¨©éãadminã ãã«è¨±å¯ãããã¨ã§ããããã¤æ å½è ã§ãã£ã¦ãè¨å®å¤æ´ãã§ããªãããã«ãã¾ãã
Dockerfileã®æ§æ
Jenkinsã¯ãã¼ã¹ã¨ãªãå ¬å¼imageãããã®ã§ããã使ãã¾ãã
ç´ ã®Jenkinsã¤ã¡ã¼ã¸ã«å¯¾ãã¦ãDockerfileå ã§ã ãã©ã°ã¤ã³ã®ã¤ã³ã¹ãã¼ã«ãåå¥ã®è¨å®ãã¸ã§ãå®ç¾©ã®çæãå®æ½ãã¦ããã¾ãã
ãªãããã©ã°ã¤ã³ã®é¸å®ãå ã¨ãªãè¨å®ã¯ç»é¢ä¸ã§è¡ã£ã¦ãããDockerfileã«åæ ããã¦ãããã¨ã«ãªãã®ã§ã ã¾ãã¯ç´ ã®Jenkinsããã¼ã«ã«ã§èµ·åãã¦ã¯ãããã®ãããã¨æãã¾ãã
docker run --rm -p 8080:8080 -v $(pwd)/jekins_home:/var/jenkins_home jenkins/jenkins:lts-alpine
ãã©ã°ã¤ã³ã®ã¤ã³ã¹ãã¼ã«ãã³ã¼ãå
å ¬å¼ã«ã¤ã³ã¹ãã¼ã«ç¨ã®ã¹ã¯ãªãããç¨æããã¦ãã¾ãã ãã®ã¹ã¯ãªããã«ã¤ã³ã¹ãã¼ã«ãããã©ã°ã¤ã³ã®ãªã¹ãã渡ãã ãã§ã¤ã³ã¹ãã¼ã«ãå®äºãã¾ãã
# Dockerfile COPY ./config/plugins.txt /config/plugins.txt RUN ... \ /usr/local/bin/install-plugins.sh < /config/plugins.txt
ãã©ã°ã¤ã³ã®ãªã¹ãã¯ãä¸æ¦èµ·åããJenkinsã®GUIã§å¿ è¦ãªãã®ãã¤ã³ã¹ãã¼ã«ããå¾ã Jenkinsã®ç®¡çâã¹ã¯ãªããã³ã³ã½ã¼ã«ã§groovyã¹ã¯ãªãããå®è¡ãã¦çæããã¨ä¾¿å©ã§ãã ãªããã¢ãããã¼ãæã®å·®åãæ確ã«ãªãããããªã¹ãã¯ååé ã§ã½ã¼ããã¦ããã¨ããã§ãã
Jenkins.instance.pluginManager.plugins.collect{ plugin -> "${plugin.getShortName()}:${plugin.getVersion()}" }.sort().each{ p -> println(p) }
Jenkinsã®è¨å®ãã³ã¼ãå
JCasC pluginãå ¥ã£ã¦ããã¨ãJenkinsã®ç®¡çâConfiguration as Codeã®ç»é¢ã§ãç¾å¨ã®è¨å®ããã¡ã¤ã«ã«åºåã§ãã¾ãã ãã®ãã¡ã¤ã«ãDockerfileã«åãè¾¼ãã§ãè¨å®æ¸Docker imageãä½ãã¾ãã
# Dockerfile ENV CASC_JENKINS_CONFIG /config/jenkins.yaml COPY ./config/jenkins.yaml $CASC_JENKINS_CONFIG
ãªããç°å¢ãã¨ã«å¤ããè¨å®ãç§å¯ã«ãã¹ãè¨å®ã¯ç°å¢å¤æ°ã§è¨å®ããããã åºåãã¦å¾ããããã¡ã¤ã«ãç·¨éãã¦ç°å¢å¤æ°ã§æ¸ãæãã¾ãã
# jenkins.yaml credentials: system: domainCredentials: - credentials: - string: id: "slack-token" scope: GLOBAL secret: ${SLACK_TOKEN} description: Slack token for plugin ... mailer: charset: "UTF-8" smtpHost: "${SMTP_HOST}" smtpPort: "${SMTP_PORT}" useSsl: false useTls: false resourceRoot: url: "https://${JENKINS_DOMAIN}/"
ç°å¢å¤æ°ã§ãªã¹ããè¨å®ããã
ã¦ã¼ã¶ã¨æ¨©éã®è¨å®ããã¡ã¤ã«ã§è¨å®ã§ããã®ã§ããã ä½æãããã¼ã«ãå²ãå½ã¦ãã¡ã³ãã¼ãyamlã®ãªã¹ãå½¢å¼ã§è¨å®ããªããã°ãªããããããç°å¢å¤æ°ã§è¨å®ã§ãã¾ããã
jenkins: authorizationStrategy: roleBased: roles: ... items: - assignments: #ããããªã¹ã - "user1" - "user2" name: "operator" pattern: "mygroup-.*" permissions: - "Job/Cancel" - "Job/ExtendedRead" - "Job/Build" - "Job/Discover" - "Job/Read"
ã©ã工夫ãã¦ããç°å¢å¤æ°ã®å±éã§ã¯ãã¾ããããªãã£ãã®ã§ã èµ·åã¹ã¯ãªããå ã§ãJenkinsã®èµ·ååã«ç°å¢å¤æ°ãå±éãããã¹ã¯ãªãããå®è¡ããããã¨ã«ãã¾ããã
# inject_variables.sh readonly CONFIG_FILE=$1 readonly TEMP_FILE="${CONFIG_FILE}.tmp" touch "$TEMP_FILE" trap "rm -f ${TEMP_FILE}" EXIT cat "${CONFIG_FILE}" \ | sed -e "s/##USERS_ADMIN##/${USERS_ADMIN:-NO_USERS_ADMIN}/g" \ | sed -e "s/##USERS_OPERATOR##/${USERS_OPERATOR:-NO_USERS_OPERATOR}/g" \ | sed -e "s/##USERS_READONLY##/${USERS_READONLY:-NO_USERS_READONLY}/g" \ > "${TEMP_FILE}" mv "${TEMP_FILE}" "${CONFIG_FILE}"
ããã§yamlå ã®æå®ã®æååãèµ·ååã«ç°å¢å¤æ°ã®å¤ã§æ¸ãæãã¾ãã
- assignments: [ ##USERS_OPERATOR## ] â - assignments: [ user1,user2 ]
ã¸ã§ãå®ç¾©ã®ã³ã¼ãå
ã¸ã§ãå®ç¾©ã«é¢ãã¦ã Jenkinsfile
ã¨å¼ã°ããgroovyã¹ã¯ãªããã§ã³ã¼ãã¨ãã¦æ¸ããããã«ãªã£ã¦ãã¾ãã
ããå®éã«ã¸ã§ãå®ç¾©ã¨ãã¦å¿
è¦ãªãã¡ã¤ã«ã¯ /var/jenkins_home/jobs/${ã¸ã§ãå}/config.xml
ã§ãã
ãã®XMLãç·¨éãããã³ã¼ã管ç対象ã«ããã®ã¯è¾ãã®ã§ããã®xmlãdocker buildæã« Jenkinsfile
ããçæãããã¨ã«ãã¾ãã
ãã®ããããã«ãã¹ãã¼ã¸ã®ãã«ãã«ãã¾ããã
1åç®
1åç®ã§ã¯ãå
é¨ã§å¿
è¦ãªãã©ã°ã¤ã³ãã¤ã³ã¹ãã¼ã«å¾ãå®éã«Jenkinsãèµ·åãã¦ã
åã¸ã§ããå®éã«ãç»é²ãå®è¡ãã¾ããå®è¡ããªãã¨ãã©ã¡ã¼ã¿ä»ããã«ãã®å®ç¾©ãã¡ã¤ã«ãçæãããªãããã§ãã
ãã ããæ¬å½ã«ãããã¤ãå®è¡ããã¦ã¯å°ãã®ã§ããã®æ®µéã§ã¯ Jenkinsfile
ãèªãã ãã§ä½ãããã«çµäºããããã«ã¸ã§ããæ¸ãã¾ãã
å
·ä½çã«ã¯ãã¸ã§ãã®å¤æ°ã¨ã㦠RELOAD_JOB_DEF
ãå®ç¾©ãã¦ãããããã true
ã®å ´åã¯ä½ãããçµäºããããã«ãã¾ãã
ãªãã1åç®ã§ä½¿ãJenkinsã®è¨å®ã¯æä½éã§ããã®ã§ãã«ãç¨ã® jenkins.build.yml
ãç¨æãã¾ãã
ã¸ã§ãã®ç»é²ãå¿
è¦ãªã®ã§ãå
¨æ¨©éãæã¤adminã¦ã¼ã¶ãè¨å®ãã¦ããå¿
è¦ãããã¾ãã
# Dockerfile FROM jenkins/jenkins:2.249.1-lts-alpine as builder USER root ENV TZ="Asia/Tokyo" ENV CASC_JENKINS_CONFIG /config/jenkins.build.yaml ENV JAVA_OPTS "-Djenkins.install.runSetupWizard=false -Xmx800m -Dorg.apache.commons.jelly.tags.fmt.timeZone=Asia/Tokyo -Duser.timezone=Asia/Tokyo" # ãã¡ã¤ã«ãã³ãã¼ããå ´æã®ç¨æ RUN mkdir -p /config && \ mkdir -p /jobs && \ mkdir -p /script # 1åç®ç¨Jenkinsè¨å® COPY ./config/jenkins.build.yaml $CASC_JENKINS_CONFIG # ãã©ã°ã¤ã³ã®ã¤ã³ã¹ãã¼ã« COPY ./config/plugins.txt /config/plugins.txt # ã¸ã§ãå®ç¾©ã®ã³ãã¼ COPY ./jobs/*.groovy /jobs/ # å種ã¹ã¯ãªããã®ã³ãã¼ COPY ./script/* /script/ # å®è¡ RUN apk add --no-cache git tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ /usr/local/bin/install-plugins.sh < /config/plugins.txt && \ bash -c "/usr/local/bin/jenkins.sh &" && \ # èµ·å sleep 30 && \ # æä½å¯è½ã«ãªãã¾ã§30ç§ãããå¾ ã¤ /bin/bash /script/make_job.sh # /jobs/*.groovy ãã xmlãçæ
make_job.sh
ã¯ä»¥ä¸ã®ãããªå¦çã§ãã
#!/bin/bash readonly JENKINS_CLI_JAR="$(pwd)/jenkins-cli.jar" readonly JENKINS_URL="http://127.0.0.1:8080" function download_jar() { if test ! -f "${JENKINS_CLI_JAR}"; then wget -q -O "${JENKINS_CLI_JAR}" "${JENKINS_URL}/jnlpJars/jenkins-cli.jar" fi } function generate_job_xml() { local jenkinsfile=$1 local scriptbody scriptbody="$(cat $jenkinsfile)" cat << __EOS__ <?xml version='1.1' encoding='UTF-8'?> <flow-definition plugin="[email protected]"> <actions/> <description></description> <keepDependencies>false</keepDependencies> <properties> <hudson.model.ParametersDefinitionProperty> <parameterDefinitions> <hudson.model.BooleanParameterDefinition> <name>RELOAD_JOB_DEF</name> <description>ã¸ã§ãå®ç¾©ã®ãªãã¼ãããæã«ã ã使ããé常ã¯falseã</description> <defaultValue>false</defaultValue> </hudson.model.BooleanParameterDefinition> </parameterDefinitions> </hudson.model.ParametersDefinitionProperty> <hudson.plugins.jira.JiraProjectProperty plugin="[email protected]"/> </properties> <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="[email protected]"> <script>${scriptbody}</script> <sandbox>true</sandbox> </definition> <triggers/> <disabled>false</disabled> </flow-definition> __EOS__ } function main() { # èµ·åããJenkinsããjenkins-cli.jarããã¦ã³ãã¼ããã download_jar # /jobs/*.groovy ããããã«å¯¾ãã¦ãç»é²ãå®è¡ for jenkinsfile in /jobs/*.groovy; do local job_name local job_xml # ãã¡ã¤ã«åããã®ã¾ã¾ã¸ã§ãåã«ãªã job_name=$(basename "$jenkinsfile" .groovy) # ã¸ã§ãå®ç¾© job_xml=$(generate_job_xml $jenkinsfile) # ç»é² echo "$job_xml" | java -jar "$JENKINS_CLI_JAR" -s "$JENKINS_URL" -auth admin:admin create-job "${job_name}" # æ´æ° echo "$job_xml" | java -jar "$JENKINS_CLI_JAR" -s "$JENKINS_URL" -auth admin:admin update-job "${job_name}" # 空å®è¡ java -jar "$JENKINS_CLI_JAR" -s "$JENKINS_URL" -auth admin:admin build "${job_name}" -s -p RELOAD_JOB_DEF=true || true # ã§ããxmlãã³ãã¼ãã¦ãã cp "/var/jenkins_home/jobs/${job_name}/config.xml" "/jobs/${job_name}.xml" done } # ã¨ã³ããªã¼å¦ç if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi
ã¸ã§ãå®ç¾©ã®ä¾ã
# /jobs/sample.groovy pipeline { agent any # ã¸ã§ãå®è¡æã«æå®ãããã©ã¡ã¼ã¿ parameters { validatingString description: 'JIRAãã±ããçªå·', defaultValue: 'JIRA-', name: 'jira_issue', regex: 'JIRA-\\p{Digit}+', failedValidationMessage: 'JIRA-1234 å½¢å¼ã§ãã' validatingString description: 'docker image ã¿ã°', defaultValue: '', name: 'tag', regex: '(v\\p{Digit}+|latest)', failedValidationMessage: 'ã¿ã°ã¯v123å½¢å¼ãlatestã®ã¿æå®å¯è½ã§ãã' validatingString description: 'docker image digestå¤', defaultValue: 'sha256:', name: 'digest', regex: 'sha256:\\p{XDigit}+', failedValidationMessage: 'sha256:xxxx å½¢å¼ã§ãã' booleanParam description: 'ã¸ã§ãå®ç¾©ã®ãªãã¼ãããæã«ã ã使ããé常ã¯falseã', defaultValue: false, name: 'RELOAD_JOB_DEF' } # ç°å¢å¤æ°ã«ãã£ã¦æ¸ãæãããã©ã¡ã¼ã¿ environment { AWS_REGION = "ap-northeast-1" ECR_REPO_NAME = "my-service-prod" ECS_CLUSTER = "my-service-prod" ECS_SERVICE = "my-service" CURRENT_TAG = "latest" } stages { # xmlçææã«çµäºããããã stage('load job definition') { when { expression { return params.RELOAD_JOB_DEF } } steps { script { currentBuild.description = "reload job definition" } sh 'exit 1' } } # ç°å¢å¤æ°ã®æ¸ãæã stage('override variables only if QA') { when { expression { return env.APP_ENV == "qa" } } steps { script { ECR_REPO_NAME = "my-service-qa1" ECS_CLUSTER = "my-service-qa1" } } } stage('latest ã¿ã°ã®ç½®ãæã') { steps { echo "tag=${tag}" # ECRã§æå®ãããã¤ã¡ã¼ã¸ã«latestã¿ã°ãã¤ãã } post { failure { # 失æãã¡ã¼ã«ã¨slackã§éç¥ãã } } } stage('ECS service ã®ã¢ãããã¼ã') { steps { echo "digest=${digest}" # ECSãforce-update } post { failure { # 失æãã¡ã¼ã«ã¨slackã§éç¥ãã } success { # çµæãã¡ã¼ã«ã¨slackã§éç¥ãã } } } } }
ã¸ã§ãXMLçæã®ä»çµã¿ã¯ã以ä¸ã®è¨äºãåèã«ããã¦ããã ãã¾ããã
Jenkinsã®ã¸ã§ããGit管çãã¦è¨å®æ´æ°ãèªååãã
2åç®
2åç®ã§ã¯çæããããã¡ã¤ã«ã /jobs/
ããã³ãã¼ãã¾ãã
ãã ãã /var/jenkins_home/
ã¯EFSã§ãã¦ã³ãããã®ã§ãããã§ã¯ãªã
Docker imageä¸ã§ã¯ /jobs/
å
ã«ã³ãã¼ãã¦ããã¾ãã
# Dockerfile 1åç®ããã®ç¶ã FROM jenkins/jenkins:2.249.1-lts-alpine as app USER root ENV TZ="Asia/Tokyo" ENV CASC_JENKINS_CONFIG /config/jenkins.yaml ENV JAVA_OPTS "-Djenkins.install.runSetupWizard=false -Xmx800m -Dorg.apache.commons.jelly.tags.fmt.timeZone=Asia/Tokyo -Duser.timezone=Asia/Tokyo" # ãã¡ã¤ã«ãã³ãã¼ããå ´æã®ç¨æ RUN mkdir -p /config && \ mkdir -p /jobs && \ mkdir -p /script # Jenkinsè¨å® COPY ./config/jenkins.yaml $CASC_JENKINS_CONFIG # ãã©ã°ã¤ã³ã®ã¤ã³ã¹ãã¼ã« COPY ./config/plugins.txt /config/plugins.txt # 1åã§ä½ã£ãã¸ã§ãå®ç¾©ã®ã³ãã¼ COPY --from=builder /jobs/* /jobs/ # å種ã¹ã¯ãªããã®ã³ãã¼ COPY ./script/* /script/ # setup RUN apk add --no-cache git python3 py-pip tzdata && \ ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ pip install awscli && \ /usr/local/bin/install-plugins.sh < /config/plugins.txt # èµ·åã¹ã¯ãªãã RUN { \ echo '#!/bin/sh'; \ echo '/script/entrypoint.sh &'; \ echo 'pid="$!"'; \ echo 'trap "kill -0 $pid" SIGTERM'; \ echo 'wait'; \ } > /script/start && chmod a+x /script/start CMD ["/script/start"]
èµ·åæã® /script/entrypoint.sh
å
ã§Jenkinsã®èµ·ååã«ã /jobs/
ã«ç¨æããxmlã /var/jenkins_home/jobs
å
ã«ã³ãã¼ãã¾ãã
# entrypoint.sh #!/bin/bash # JCasCã§å¯¾å¿ã§ããªãç°å¢å¤æ°ã®å±é /bin/bash /script/inject_variables.sh /config/jenkins.yaml # ã¸ã§ãå®ç¾©ãEFSã§ãã¦ã³ããã¦ãã /var/jenkins_home/jobs/ ã«ã³ãã¼ /bin/bash /script/install_job.sh # Jenkinsã®èµ·å /usr/local/bin/jenkins.sh
# install_job.sh #!/bin/bash set -eu function main() { # æ¬ä½ for job_xml in /jobs/*.xml; do local job_name # ãã¡ã¤ã«åããã®ã¾ã¾ã¸ã§ãåã«ãªã job_name=$(basename "$job_xml" .xml) # EFSã«ãã¦ã³ããã¦ãã/var/jenkins_homeå ã«ãã£ã¬ã¯ããªãä½ãã mkdir -p "/var/jenkins_home/jobs/${job_name}" # ã³ãã¼ãã cp "${job_xml}" "/var/jenkins_home/jobs/${job_name}/config.xml" done } # ã¨ã³ããªã¼å¦ç if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi
以ä¸ã§ãè¨å®ããã©ã°ã¤ã³ãã¸ã§ãå®ç¾©ããã¹ã¦å ¥ã£ãdocker imageãä½ããã¨ãã§ãã¾ããã
ãã©ã°ã¤ã³
ä»åã®ç°å¢ãæ§ç¯ããä¸ã§å¿ è¦ã«ãªã£ããã©ã°ã¤ã³ãç´¹ä»ãã¾ãã
Simple Theme
è¦ãç®ãåãæ¿ãããã©ã°ã¤ã³ã§ãã
ãã è¦ãç®ãåãæ¿ãããã®ã§ã¯ãªãã æ¬çªã¨æ¤è¨¼ç°å¢ãééããªãããã«ãè²ãç°å¢ãã¨ã«åããããã«ä½¿ã£ã¦ãã¾ãã
simple-theme-plugin: elements: - cssUrl: url: ${THEME_URL}
Google Login
Googleã¢ã«ã¦ã³ãã§ãã°ã¤ã³ç®¡çããããã«å ¥ãã¦ãã¾ãã Google Groupã§è¨å®ããã°ã«ã¼ãåä½ã§ã ã¦ã¼ã¶ããã¼ã«ã®ç®¡çãã§ããã°ããã£ãã®ã§ãããããã¯ã§ããªãã®ã§ã1ã¦ã¼ã¶ãã¨ã«è¨å®ãå¿ è¦ã§ãã ããã§ããJenkinså´ã§idããã¹ã¯ã¼ãã管çããªãã¦ããã®ã§ã管çã楽ã«ãªãã¾ãã
Validating String Parameter
ãã©ã¡ã¼ã¿ä»ããã«ãã®ãã©ã¡ã¼ã¿ãäºåã«æ¤è¨¼ããããã«å ¥ãã¦ãã¾ãã ããã§äºæ ã¯å®å ¨ã«ã¯é²ãã¾ããããã¡ãã£ã¨ããã³ãããã¹ã§ééã£ã¦å®è¡ãã¦ãã¾ããªã¹ã¯ã ãåéãã§å¤ãªå¤ãå ¥ãã¦ããããããªããã¨ããä¸å®ã¯æãããã¾ã(çµæ§éè¦)ã
validatingString description: 'docker image digestå¤', defaultValue: 'sha256:', name: 'digest', regex: 'sha256:\\p{XDigit}+', failedValidationMessage: 'sha256:xxxx å½¢å¼ã§ãã'
We are hiring!
ã¨ã ã¹ãªã¼ã®ã¯ã©ã¦ãåæ¨é²ã¯ã¾ã ã¾ã éä¸ã§ã課é¡ãããããããã¾ãã ä¸ç·ã«åå ãã¦ããã仲éãåéä¸ã§ãã ãæ°è»½ã«ãåãåãããã ããã