├── jenkins
├── workflow-version.txt
├── jenkins_home
│ ├── org.jenkinsci.plugins.workflow.flow.FlowExecutionList.xml
│ ├── org.jenkinsci.plugins.workflow.support.steps.StageStep.xml
│ ├── hudson.model.UpdateCenter.xml
│ ├── hudson.tasks.Maven.xml
│ ├── hudson.plugins.git.GitTool.xml
│ ├── scriptApproval.xml
│ ├── nodeMonitors.xml
│ ├── config.xml
│ ├── jobs
│ │ ├── freestylebuild
│ │ │ └── config.xml
│ │ └── wf-build
│ │ │ └── config.xml
│ └── gerrit-trigger.xml
├── demo_key_rsa.pub
├── plugins.txt
├── Dockerfile
└── demo_key_rsa
├── gerrit
├── repos
│ ├── primary
│ │ ├── output.txt
│ │ ├── src
│ │ │ ├── test
│ │ │ │ └── java
│ │ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── app
│ │ │ │ │ └── AppTest.java
│ │ │ └── main
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── app
│ │ │ │ └── App.java
│ │ └── pom.xml
│ ├── secondary
│ │ ├── test.txt
│ │ ├── src
│ │ │ ├── test
│ │ │ │ └── java
│ │ │ │ │ └── com
│ │ │ │ │ └── example
│ │ │ │ │ └── app
│ │ │ │ │ └── AppTest.java
│ │ │ └── main
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── app
│ │ │ │ └── App.java
│ │ └── pom.xml
│ ├── umbrella
│ │ ├── default.xml
│ │ └── jenkins.xml
│ └── workflow
│ │ └── demoscript.groovy
├── ReviewDB.h2.db
└── Dockerfile
├── util
└── copy_docker_db.sh
├── start.sh
├── docker-compose.yml
├── testme.sh
├── config-gerrit-mac.sh
├── config-gerrit.sh
├── .gitignore
├── demoscript-rawgerrit.groovy
├── demoscript.groovy
├── lessons.md
├── README.md
└── LICENSE
/jenkins/workflow-version.txt:
--------------------------------------------------------------------------------
1 | 1.10
--------------------------------------------------------------------------------
/gerrit/repos/primary/output.txt:
--------------------------------------------------------------------------------
1 | sample text
2 |
--------------------------------------------------------------------------------
/gerrit/repos/secondary/test.txt:
--------------------------------------------------------------------------------
1 | SDUO$!@#"
2 |
--------------------------------------------------------------------------------
/gerrit/ReviewDB.h2.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svanoort/gerrit-workflow-demo/HEAD/gerrit/ReviewDB.h2.db
--------------------------------------------------------------------------------
/jenkins/jenkins_home/org.jenkinsci.plugins.workflow.flow.FlowExecutionList.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/org.jenkinsci.plugins.workflow.support.steps.StageStep.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/hudson.model.UpdateCenter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | default
5 | http://updates.jenkins-ci.org/update-center.json
6 |
7 |
--------------------------------------------------------------------------------
/util/copy_docker_db.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Assuming you're running docker natively, copy the review db to local copy
4 | sudo docker cp gerrit:/var/gerrit/db/ReviewDB.h2.db gerrit/ReviewDB.h2.db
5 | sudo chown "$USER":"$USER" gerrit/ReviewDB.h2.db
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | # Starts both containers in daemon mode
2 | docker rm -f gerrit && docker rm -f jenkins
3 | docker run -d -h gerrit -p 8080:8080 -p 29418:29418 --name gerrit jenkins-gerrit-wfdemo-gerrit:1.0
4 | docker run -d -h jenkins -p 8081:8080 --name jenkins --link gerrit:gerrit jenkins-gerrit-wfdemo-jenkins:1.0
5 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/hudson.tasks.Maven.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Maven 3.x
6 | /usr/local/maven
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/jenkins/demo_key_rsa.pub:
--------------------------------------------------------------------------------
1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDVAg824XdUvLJimi6a3ey6+lDxYJy0HC3+/3V+IVj30vuNvMwqSMsRb/7aTmcxtetLe0vJhBbUsVoJxK4M8MW9CFMiYP7gKnMcoVoZxrGbQTwt0eAdKZCMIXXWmacQ7Lpy277dNj1dsxSNVde+2fEKeiSlBKjI54StioSuxEQngy5/mQzX35xAvya+XH+UApkERbinR6xZtbl7AdKZgEGnNrW54e3UrVJMw5ry3X9+n2e77BJzA2Q7ZiPOcmARXUbRAP+3YL9yvQaITu33w8cH4+oKO4GB9+SeLfuQS0jElObHC3+HPViGcpah2H1cZkniJZ/j7IWMi8IssBhsuvSp demouser@example.com
2 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/hudson.plugins.git.GitTool.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Default
6 | git
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/gerrit/repos/umbrella/default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/gerrit/repos/umbrella/jenkins.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/gerrit/repos/secondary/src/test/java/com/example/app/AppTest.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 |
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.fail;
7 |
8 | /**
9 | * Testcase that always fail after 15 sec so this build will crash unless tests are skipped
10 | */
11 | public class AppTest {
12 |
13 | @Test
14 | public void fails() throws Exception {
15 | Thread.sleep(15000);
16 | fail("Always fails");
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/scriptApproval.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | method groovy.lang.GroovyObject invokeMethod java.lang.String java.lang.Object
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | gerrit:
2 | container_name: gerrit
3 | hostname: gerrit
4 | build: ./gerrit
5 | ports:
6 | - "8080:8080"
7 | - "29418:29418"
8 |
9 | jenkins:
10 | container_name: jenkins
11 | build: ./jenkins
12 | hostname: jenkins
13 | links:
14 | - gerrit
15 | ports:
16 | - "8081:8080"
17 | # Use caution when mountaining the home directory as a volume
18 | # Repo will fail to init, and performance issues may occur
19 | # volumes:
20 | # - ./jenkins/jenkins_home:/var/jenkins_home
21 |
--------------------------------------------------------------------------------
/gerrit/repos/secondary/src/main/java/com/example/app/App.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 | /**
4 | * Generates arguments for invoking the string generator in primary project
5 | */
6 | public class App
7 | {
8 | public static void main( String[] args ) {
9 | // TWO MODES: normal and legacy
10 | StringBuilder output = new StringBuilder()
11 | .append(" -d 10")
12 | // .append("-n") //Unsupported
13 | .append(" -l 50");
14 | System.out.println(output);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/testme.sh:
--------------------------------------------------------------------------------
1 | # Debugging use, runs removable containers in interactive mode if needed
2 |
3 | sudo docker run -h gerrit -i -t --rm=true --name gerrit -p 8080:8080 -p 29418:29418 jenkins-gerrit-wfdemo-gerrit:1.0 /bin/bash
4 |
5 | # Note when you run jenkins this way, something in the volumes means you have to run /usr/local/bin/jenkins.sh
6 | # Twice (killing java in between)
7 | # NOTE: using Jenkins home in a volume will interact poorly with gerrit
8 | sudo docker run -h jenkins -i -t --rm=true -v `pwd`/jenkins/jenkins_home:/var/jenkins_home -p 8081:8080 --name jenkins --link gerrit:gerrit jenkins-gerrit-wfdemo-jenkins:1.0 /bin/bash
9 |
--------------------------------------------------------------------------------
/config-gerrit-mac.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | USERNAME="`git config user.name`"
3 | EMAIL="`git config user.email`"
4 | USERNAME="$USER"
5 | HTTP_PASS=goober
6 | FULLNAME="`git config user.name`"
7 |
8 | # Fixes issues with repo url getting wrong username, since it uses local part of
9 | # email for SSH username
10 | git config --global review.http://gerrit:8080/.username $USER
11 | chmod 400 jenkins/demo_key_rsa
12 | cat ~/.ssh/id_rsa.pub | ssh -i jenkins/demo_key_rsa -p 29418 demouser@gerrit \
13 | gerrit create-account --group Workers --group \"Non-Interactive Users\" --full-name \"$FULLNAME\" --email \"$EMAIL\" --http-password \"$HTTP_PASS\" --ssh-key - $USERNAME
--------------------------------------------------------------------------------
/config-gerrit.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | USERNAME="`git config user.name`"
3 | EMAIL="`git config user.email`"
4 | USERNAME="$USER"
5 | HTTP_PASS=goober
6 | FULLNAME="`git config user.name`"
7 |
8 | # Fixes issues with repo url getting wrong username, since it uses local part of
9 | # email for SSH username
10 | git config --global review.http://localhost:8080/.username $USER
11 | chmod 400 jenkins/demo_key_rsa
12 | cat ~/.ssh/id_rsa.pub | ssh -i jenkins/demo_key_rsa -p 29418 demouser@localhost \
13 | gerrit create-account --group Workers --group \"Non-Interactive Users\" --full-name \"$FULLNAME\" --email \"$EMAIL\" --http-password \"$HTTP_PASS\" --ssh-key - $USERNAME
--------------------------------------------------------------------------------
/jenkins/plugins.txt:
--------------------------------------------------------------------------------
1 | branch-api:0.2-beta-4
2 | durable-task:1.6
3 | gerrit-trigger:2.15.1
4 | git:2.3.5
5 | git-client:1.17.0
6 | git-server:1.6
7 | javadoc:1.3
8 | junit:1.5
9 | mailer:1.15
10 | mapdb-api:1.0.6.0
11 | mercurial:1.54
12 | scm-api:0.2
13 | script-security:1.15
14 | subversion:2.5
15 | workflow-aggregator:@VERSION@
16 | workflow-api:@VERSION@
17 | workflow-basic-steps:@VERSION@
18 | workflow-cps:@VERSION@
19 | workflow-cps-global-lib:@VERSION@
20 | workflow-durable-task-step:@VERSION@
21 | workflow-job:@VERSION@
22 | workflow-multibranch:1.9-beta-2
23 | workflow-scm-step:@VERSION@
24 | workflow-step-api:@VERSION@
25 | workflow-support:@VERSION@
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 |
4 | # Mobile Tools for Java (J2ME)
5 | .mtj.tmp/
6 |
7 | # Package Files #
8 | *.jar
9 | *.war
10 | *.ear
11 |
12 | # Java build and projects
13 | target/
14 | *.iml
15 | .eclipse
16 | .idea/
17 |
18 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
19 | hs_err_pid*
20 |
21 | # Jenkins unneeded data
22 | plugins/
23 | .java/
24 | war/
25 | userContent/
26 | updates/
27 | secrets/
28 | nodes/
29 | builds/
30 | jenkins/jenkins_home/init.groovy.d/
31 | .bashrc
32 | .*
33 | *.bak
34 | *.log
35 | *.key*
36 | jobs/*/last*
37 | nextBuildNumber
38 | lastStable
39 | lastSuccessful
40 | workspace/
41 | workspace*/
42 | queue.xml
--------------------------------------------------------------------------------
/gerrit/repos/primary/src/test/java/com/example/app/AppTest.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 | import java.util.HashSet;
7 |
8 | import static org.junit.Assert.*;
9 |
10 | /**
11 | * Basic unit tests for command generation
12 | */
13 | public class AppTest {
14 |
15 | @Test
16 | public void testRandomStrings() throws Exception {
17 | String chars = "ABCDEDF";
18 | String output = App.randomString(chars, 10);
19 | assertEquals(10, output.length());
20 |
21 | // Check output
22 | HashSet validChars = new HashSet();
23 | for (char v : chars.toCharArray()) {
24 | validChars.add(v);
25 | }
26 |
27 | for (char v : output.toCharArray()) {
28 | assertTrue(validChars.contains(new Character(v)));
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/nodeMonitors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 | false
8 |
9 |
10 | false
11 | 1GB
12 |
13 |
14 | false
15 |
16 |
17 | false
18 | 1GB
19 |
20 |
21 | false
22 |
23 |
--------------------------------------------------------------------------------
/gerrit/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM gerritforge/gerrit-ubuntu15.04:2.11.3
2 | MAINTAINER svanoort
3 |
4 | USER root
5 | RUN apt-get update && \
6 | apt-get install -y curl python net-tools && \
7 | rm -rf /var/lib/apt/lists/*
8 | RUN curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo \
9 | && chmod a+x /bin/repo
10 |
11 | COPY ReviewDB.h2.db /var/gerrit/db/ReviewDB.h2.db
12 | COPY repos /tmp/repos-wc
13 | RUN chown -R gerrit:gerrit /tmp/repos-wc var/gerrit/db/ReviewDB.h2.db
14 |
15 | USER gerrit
16 | RUN git config --global user.email "demouser@example.com" && \
17 | git config --global user.name "Demo User"
18 |
19 | # This is how we save gerrit user/project configuration
20 |
21 | # Create repo working copies & then do bare clones to expose for work
22 | RUN cd /tmp/repos-wc && mkdir /tmp/repos && \
23 | for r in primary secondary umbrella workflow; do ( \
24 | cd $r; git init && git add . && git commit -am "Initial commit"; \
25 | git clone --bare /tmp/repos-wc/$r /var/gerrit/git/$r.git; \
26 | ); done;
27 |
28 | CMD /var/gerrit/bin/gerrit.sh start && tail -f /var/gerrit/logs/error_log
29 |
30 | # Docker doesn't set this to user home by default
31 | ENV HOME /var/gerrit
32 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.609.2
5 | 4
6 | NORMAL
7 | true
8 |
9 |
10 | false
11 |
12 | ${ITEM_ROOTDIR}/workspace
13 | ${ITEM_ROOTDIR}/builds
14 |
15 |
16 |
17 |
18 | 1
19 | 0
20 |
21 |
22 |
23 | All
24 | false
25 | false
26 |
27 |
28 |
29 | All
30 | 50000
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/jenkins/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM jenkins:1.609.2
2 | MAINTAINER svanoort
3 |
4 | # Workflow demo, jenkins host setup
5 |
6 | USER root
7 | ENV JENKINS_UC http://jenkins-updates.cloudbees.com
8 |
9 | # Google repo install
10 | RUN apt-get install -y curl python && \
11 | rm -rf /var/lib/apt/lists/*
12 | RUN curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo \
13 | && chmod a+x /bin/repo
14 |
15 | # Maven install
16 | ENV MAVEN_VERSION 3.3.9
17 | RUN cd /usr/local; wget -O - http://mirrors.ibiblio.org/apache/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz | tar xvzf -
18 | RUN ln -sv /usr/local/apache-maven-$MAVEN_VERSION /usr/local/maven
19 |
20 | # Keys for gerrit user, passphrase is EMPTY
21 | COPY demo_key_rsa /tmp/
22 | COPY workflow-version.txt /tmp/
23 | COPY plugins.txt /tmp/
24 | RUN sed -i "s/@VERSION@/`cat /tmp/workflow-version.txt`/g" /tmp/plugins.txt
25 | RUN chown jenkins:jenkins /tmp/demo_key_rsa
26 |
27 | # Set up jenkins home folder for starting point
28 | ADD jenkins_home /usr/share/jenkins/ref
29 | RUN chown -R jenkins.jenkins /usr/share/jenkins/ref
30 |
31 | USER jenkins
32 | RUN /usr/local/bin/plugins.sh /tmp/plugins.txt
33 | CMD /usr/local/bin/jenkins.sh
34 |
35 | # Fix for issues with the 'repo' tool needing an ident
36 | RUN git config --global user.email "demouser@example.com" && \
37 | git config --global user.name "Demo User"
38 |
39 | # COPY KEYS FOR USER TO JENKINS DIR
40 | EXPOSE 8080
--------------------------------------------------------------------------------
/jenkins/jenkins_home/jobs/freestylebuild/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | freestyle parallel build
5 | false
6 |
7 |
8 |
9 |
10 | sample
11 |
12 | noparam
13 |
14 |
15 |
16 |
17 | hour
18 | 0
19 |
20 |
21 |
22 | true
23 | false
24 | false
25 | false
26 |
27 | false
28 |
29 |
30 | echo "$sample"
31 | rm -rf sources
32 | mkdir sources
33 | cd sources
34 | sleep 30
35 | repo init -u http://gerrit:8080/umbrella -m jenkins.xml
36 | repo sync
37 | /usr/local/maven/bin/mvn clean compile install -Dmaven.test.skip -f primary/pom.xml
38 | /usr/local/maven/bin/mvn clean compile install -Dmaven.test.skip -f secondary/pom.xml
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/jenkins/demo_key_rsa:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEogIBAAKCAQEA1QIPNuF3VLyyYpoumt3suvpQ8WCctBwt/v91fiFY99L7jbzM
3 | KkjLEW/+2k5nMbXrS3tLyYQW1LFaCcSuDPDFvQhTImD+4CpzHKFaGcaxm0E8LdHg
4 | HSmQjCF11pmnEOy6ctu+3TY9XbMUjVXXvtnxCnokpQSoyOeErYqErsREJ4Muf5kM
5 | 19+cQL8mvlx/lAKZBEW4p0esWbW5ewHSmYBBpza1ueHt1K1STMOa8t1/fp9nu+wS
6 | cwNkO2YjznJgEV1G0QD/t2C/cr0GiE7t98PHB+PqCjuBgffkni37kEtIxJTmxwt/
7 | hz1YhnKWodh9XGZJ4iWf4+yFjIvCLLAYbLr0qQIDAQABAoIBAAK67AcADM+BO6gX
8 | 4dEKVyZuXus5GckVM2G5VIAxXTqP8bl3WgaQuEmY7eNObfQtKL7m7am/j6taOpU1
9 | eCWiUGaD3MzsAVhOMvuC9eyup0geJe9QaVb2WWvyYdhGT+XfouQl/ORI9bBlwzWs
10 | i/9eO8CuoBmdXax1izXOOLUkvtrixZFY/3AuaFZ446yGF3ZX9Y9LwseenkwxRBr5
11 | gn/u0lcJkjnCTApRC9K8rN58bPH1PzMNdJmYvf4xtKM6hqkbfVxi4f7jinf97lyo
12 | oewGJa6e+rqCS6E7wUwIzyehmGiV73kkOXM584DTIgaXqhtUj3EPQBkvLZx/jYAz
13 | rK6I86ECgYEA6ZhOXyY3/buaYAcWUm1KTlH1hrWJjgVn5xvZ4QWD/VoycmfA54N4
14 | YrGnPUSgdBey5jNrp3w7ZYEz6e3u0Qk/l8uaaDL6yFrjY1ISaXubVhfsds3rY4P+
15 | ykUmOVb8W6i++i1Guy8kXTrc19M3eiKaRxJ6Rbj8OIWZEMCJGmToVfcCgYEA6XBD
16 | H+zTWMQo/5SaS36q6WZUcE321FRv3UUQVRmtjhif6ojTrSPFWbqndRkeveApGwq9
17 | eeGl/J0H6lqsbjqpHzYWoLrJg20Pxv53duAZSumrdThX/6jTwqP4KH1Yqp2PM5Y0
18 | ISi8uJ7lVXF3WhWht/Sjr15b8bJ6nf4Ub/KZ4l8CgYBisF4sBNGS+Td3aocbu+Cw
19 | xh+dEgVTYyVKlpGuZ84js3+spfjx1rF9wOCPGfdQFNMYPpE06V+Ous9b/ZHv7qBX
20 | WUWa0C7zhrKau4nb1sUB0omsh8LzAEkc26oSf5WOg/RrbcV8P6Z1XPEAndPKXeQg
21 | MsZFvqmQl6DbWvyRkiA2cQKBgCKrFnz2SgkD0ObsJeISZMWW+fFX0tGD3L0q1Zsd
22 | 3iWdSJqnSXCMQHHsA5Sjb2pZkSE//hXMyj7y/0rxvmv8cEN/X+rs8qJ/Hvm5rvpL
23 | m9YBUAJvpLoGU7Szb1ZsDy//iFXr97/48dYlWv/OgyAw2Dyeq3SO+e6yR/2Qz240
24 | xF/XAoGAJJ5fofDlo/tBqDxcSQqYTmj1JnoBilzuzWF49+ilIL/vd6WA5Rn/P5+q
25 | 4+o2Z9VHw5J9VejKPbl7F8qTeQh0as0eTXUXeMBxYbnmdoyZwcv7rlj0riVndzqN
26 | 3F7KhwevTZWeDzS95yAm+WNPnVohRB5xrfWMfXmbQultC9V4uPM=
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/gerrit/repos/secondary/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.example.app
5 | secondary
6 | jar
7 | 1.0-SNAPSHOT
8 | secondary
9 | http://maven.apache.org
10 |
11 |
12 | junit
13 | junit
14 | 4.11
15 | test
16 |
17 |
18 | commons-cli
19 | commons-cli
20 | 1.3.1
21 |
22 |
23 |
24 |
25 |
26 | org.apache.maven.plugins
27 | maven-assembly-plugin
28 | 2.4.1
29 |
30 |
31 | jar-with-dependencies
32 |
33 |
34 |
35 | com.example.app.App
36 |
37 |
38 | false
39 |
40 |
41 |
42 | make-assembly
43 |
44 | package
45 |
46 | single
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/gerrit/repos/primary/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | com.example.app
5 | primary
6 | jar
7 | 1.0-SNAPSHOT
8 | primary
9 | http://maven.apache.org
10 |
11 |
12 | junit
13 | junit
14 | 4.11
15 | test
16 |
17 |
18 | commons-cli
19 | commons-cli
20 | 1.3.1
21 | compile
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.apache.maven.plugins
29 | maven-assembly-plugin
30 | 2.4.1
31 |
32 |
33 | jar-with-dependencies
34 |
35 |
36 |
37 | com.example.app.App
38 |
39 |
40 | false
41 |
42 |
43 |
44 | make-assembly
45 |
46 | package
47 |
48 | single
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/demoscript-rawgerrit.groovy:
--------------------------------------------------------------------------------
1 | // Run this with mvn args on each node
2 | def mvn(args) {
3 | sh "${tool 'Maven 3.x'}/bin/mvn ${args}"
4 | }
5 |
6 | def fetch_repo() {
7 | // def changeBranch = "change-${GERRIT_CHANGE_NUMBER}-${GERRIT_PATCHSET_NUMBER}"
8 | // sh 'git clone http://gerrit:8080/primary'
9 | // sh 'git clone http://gerrit:8080/secondary'
10 | sh 'repo init stuff'
11 | sh "cd $GERRIT_PROJECT"
12 | sh "git checkout git fetch origin ${GERRIT_REFSPEC}:${changeBranch}"
13 | sh "git checkout ${changeBranch}"
14 | sh "cd .."
15 | }
16 |
17 | // TOOD patchset use
18 | // TODO supply branch name to script for easy customization
19 |
20 | def builds = [:]
21 | builds['workflowrun'] = {
22 | node {
23 | sh 'rm -rf source'
24 | // Remove dir component in 1.11, replaced with deletedir
25 | dir ('source') {
26 | fetch_repo()
27 | mvn("clean compile install -f primary/pom.xml")
28 | mvn("clean compile install -Dmaven.test.skip -f secondary/pom.xml")
29 | sh "mv */target/*.jar ."
30 | stash includes: '*.jar', name: 'jars'
31 | }
32 | }
33 |
34 | def slowtests = [:]
35 | slowtests['Functional Tests'] = {
36 | node {
37 | // Fetch both artifacts
38 | unstash name:'jars'
39 | sleep 2
40 |
41 | // Verify both jars can run successfully
42 | sh 'java -jar primary*.jar -delay 1 --length 100'
43 | sh 'java -jar secondary*.jar'
44 | }
45 | }
46 | slowtests['Integration tests'] = {
47 | node {
48 | sleep 30
49 | unstash name:'jars'
50 | sh 'java -jar primary*.jar `java -jar secondary*.jar`'
51 | }
52 | }
53 | slowtests['failFast'] = true
54 | parallel slowtests
55 | }
56 |
57 | // PARALLEL BUILD STEP
58 | builds['parallelbuild'] = {
59 | build job: 'freestylebuild-sample', parameters: [[$class: 'StringParameterValue', name: 'sample', value: 'val']]
60 | }
61 |
62 | builds['failFast'] = true
63 | parallel builds
--------------------------------------------------------------------------------
/demoscript.groovy:
--------------------------------------------------------------------------------
1 | // Run this with mvn args on each node
2 | def mvn(args) {
3 | sh "${tool 'Maven 3.x'}/bin/mvn ${args}"
4 | }
5 |
6 | def fetch_repo() {
7 | sh 'repo init -u http://gerrit:8080/umbrella -m jenkins.xml'
8 | sh 'repo sync'
9 | sh "repo download $GERRIT_PROJECT $GERRIT_CHANGE_NUMBER/$GERRIT_PATCHSET_NUMBER"
10 | }
11 |
12 | // Builds are defined before being run!
13 | // We are building up a set of parallel pipelines, one using workflow for build +
14 | //builds... they're defined first as a name : {block} pairs, then run by 'parallel' DSL step
15 | def builds = [:]
16 | // Core build/run inlined with workflow
17 | builds['workflowrun'] = {
18 | node {
19 | sh 'rm -rf source'
20 | // Remove dir component in 1.11, replaced with deletedir
21 | dir ('source') {
22 | fetch_repo()
23 | mvn("clean compile install -f primary/pom.xml")
24 | mvn("clean compile install -Dmaven.test.skip -f secondary/pom.xml")
25 | sh "mv */target/*.jar ."
26 | stash includes: '*.jar', name: 'jars'
27 | }
28 | }
29 |
30 | // Set of tests that run slowly and are run in parallel for speed
31 | def slowtests = [:]
32 |
33 | // Fast functional tests run in parallel with slower integration tests
34 | slowtests['Functional Tests'] = {
35 | node {
36 | // Fetch both artifacts
37 | unstash name:'jars'
38 | sleep 2
39 |
40 | // Verify both jars can run successfully
41 | sh 'java -jar primary*.jar -delay 1 --length 100'
42 | sh 'java -jar secondary*.jar'
43 | }
44 | }
45 |
46 | // Slower integration tests that are run
47 | slowtests['Integration tests'] = {
48 | node {
49 | sleep 15
50 | unstash name:'jars'
51 | sh 'java -jar primary*.jar `java -jar secondary*.jar`'
52 | }
53 | }
54 | slowtests['failFast'] = true
55 | parallel slowtests // This is where it actually will run this step when block is executed
56 | }
57 |
58 | // PARALLEL NESTED PIPE
59 | builds['parallelbuild'] = {
60 | build job: 'freestylebuild', parameters: [[$class: 'StringParameterValue', name: 'sample', value: 'val']]
61 | }
62 |
63 | builds['failFast'] = true
64 | parallel builds // This is where the block is finally run
--------------------------------------------------------------------------------
/gerrit/repos/workflow/demoscript.groovy:
--------------------------------------------------------------------------------
1 | // Run this with mvn args on each node
2 | def mvn(args) {
3 | sh "${tool 'Maven 3.x'}/bin/mvn ${args}"
4 | }
5 |
6 | def fetch_repo() {
7 | sh 'repo init -u http://gerrit:8080/umbrella -m jenkins.xml'
8 | sh 'repo sync'
9 | sh "repo download $GERRIT_PROJECT $GERRIT_CHANGE_NUMBER/$GERRIT_PATCHSET_NUMBER"
10 | }
11 |
12 | // Builds are defined before being run!
13 | // We are building up a set of parallel pipelines, one using workflow for build +
14 | //builds... they're defined first as a name : {block} pairs, then run by 'parallel' DSL step
15 | def builds = [:]
16 | // Core build/run inlined with workflow
17 | builds['workflowrun'] = {
18 | node {
19 | sh 'rm -rf source'
20 | // Remove dir component in 1.11, replaced with deletedir
21 | dir ('source') {
22 | fetch_repo()
23 | mvn("clean compile install -f primary/pom.xml")
24 | mvn("clean compile install -Dmaven.test.skip -f secondary/pom.xml")
25 | sh "mv */target/*.jar ."
26 | stash includes: '*.jar', name: 'jars'
27 | }
28 | }
29 |
30 | // Set of tests that run slowly and are run in parallel for speed
31 | def slowtests = [:]
32 |
33 | // Fast functional tests run in parallel with slower integration tests
34 | slowtests['Functional Tests'] = {
35 | node {
36 | // Fetch both artifacts
37 | unstash name:'jars'
38 | sleep 2
39 |
40 | // Verify both jars can run successfully
41 | sh 'java -jar primary*.jar -delay 1 --length 100'
42 | sh 'java -jar secondary*.jar'
43 | }
44 | }
45 |
46 | // Slower integration tests that are run
47 | slowtests['Integration tests'] = {
48 | node {
49 | sleep 15
50 | unstash name:'jars'
51 | sh 'java -jar primary*.jar `java -jar secondary*.jar`'
52 | }
53 | }
54 | slowtests['failFast'] = true
55 | parallel slowtests // This is where it actually will run this step when block is executed
56 | }
57 |
58 | // PARALLEL NESTED PIPE
59 | builds['parallelbuild'] = {
60 | build job: 'freestylebuild', parameters: [[$class: 'StringParameterValue', name: 'sample', value: 'val']]
61 | }
62 |
63 | builds['failFast'] = true
64 | parallel builds // This is where the block is finally run
--------------------------------------------------------------------------------
/gerrit/repos/primary/src/main/java/com/example/app/App.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 | import org.apache.commons.cli.CommandLine;
4 | import org.apache.commons.cli.CommandLineParser;
5 | import org.apache.commons.cli.DefaultParser;
6 | import org.apache.commons.cli.HelpFormatter;
7 | import org.apache.commons.cli.Options;
8 |
9 | import java.lang.Character;
10 | import java.nio.charset.Charset;
11 | import java.util.Random;
12 |
13 | /**
14 | * Generate random string content from command line and return output
15 | * Adds a configurable delay (default 1 sec)
16 | */
17 | public class App {
18 |
19 | public static String randomString(String chars, int length) {
20 | Random rand = new Random();
21 | StringBuilder buf = new StringBuilder();
22 | for (int i=0; i Gerrit Trigger > edit next to server name > Advanced button at bottom
16 | - Under "Gerrit Verified Commands" remove the "--verified " section from each and it won't send this (just normal code review vote)
17 |
18 | # Repo problems
19 |
20 | ## Problem: repo behaves eratically if the old .repo folder is not removed
21 | * Solution: rm and recreate the folder every time (using sh rm and the workflow dir step, or shell)
22 |
23 | ## Problem: repo needs a git user configured to init a repo
24 | * Solution: configure a local git user for jenkins user, in the Dockerfile
25 |
26 | ## Problem: By default repo sets the SSH user name used to upload to gerrit using committer email and not username
27 | * Solution: Explicitly Set the Reviewer username for the review URL
28 | - 'git config --global review.http://reviewhost:8080/.username $USER'
29 | - http://stackoverflow.com/questions/11804469/debugging-repo-upload-problems-permission-denied-publickey
30 | - See: config-gerrit.sh
31 |
32 | ## Problem: On Init, repo will try to fetch content from googlesource if this fails it will not work
33 | * Solution: ensure you have external connectivity to https://gerrit.googlesource.com/git-repo/clone.bundle
34 | * Possible other solution: use the --repo-url argument to point it at a local repo, and clone from there
35 | - See: http://stackoverflow.com/questions/18895382/how-to-repo-init-on-a-disconnected-system
36 |
37 | ## Problem: repo init will fail if Jenkins Home is mounted as a Docker volume
38 | * Solution: don't mount it as a volume, repo installs hooks using symlinks in a way that is not compatible with Docker volumes
39 |
40 |
41 | # Dockerizing problems
42 |
43 | ## Problem: gerrit needs to have a user configured for jenkins & baked into the image in order for the jenkins gerrit trigger to work
44 | * Solution: create the user in a Gerrit container and copy in the DB into your container
45 | - This is conveniently set up in: util/copy_docker_db.sh - see gerrit/Dockerfile for the COPY
46 |
47 | ## Problem: Jenkins Gerrit Trigger Needs a User With Stream Event Permissions, which are not on by default
48 | * For an unDockerized Gerrit config, you'd simply create a new group "Streaming Events Users", add the jenkins user to it, and add give that group permission for streaming events in Projects > All Projects > Access within Gerrit UI
49 | * For Dockerized configs, the "All Projects" access configuration is in a git repo in gerrit, and landing the configuration for this repo within your gerrit container is a problem
50 |
51 | * Solution: Add the jenkins user to group "Non-Interactive Users" which has the Stream Events permission by default
52 |
53 | ## Problem: Jenkins needs consistent hostname for the gerrit container to speak to it
54 | * Solution: Explicitly set names for containers
55 |
56 | ## Problem: How do I preload git repos into my gerrit container? It has its own git stores under $GERRIT_BASE/git/
57 | * Solution: you can simply do `git clone --bare` for your repos while gerrit isn't running, when gerrit starts it'll pick them up
--------------------------------------------------------------------------------
/jenkins/jenkins_home/jobs/wf-build/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Main workflow build!
5 |
6 | -1
7 | 4
8 | -1
9 | -1
10 |
11 | false
12 |
13 |
14 | hour
15 | 0
16 |
17 |
18 |
19 |
20 | 2
21 |
22 |
23 | http://gerrit:8080/workflow.git
24 |
25 |
26 |
27 |
28 | */master
29 |
30 |
31 | false
32 |
33 |
34 |
35 | demoscript.groovy
36 |
37 |
38 |
39 |
40 |
41 |
42 | REG_EXP
43 | .*
44 |
45 |
46 | REG_EXP
47 | .*
48 |
49 |
50 |
51 |
52 |
53 | false
54 | false
55 | false
56 | false
57 |
58 | false
59 |
60 | false
61 | true
62 | false
63 |
64 | false
65 |
66 |
67 |
68 |
69 |
70 |
71 | local
72 |
73 |
74 | false
75 | false
76 | false
77 |
78 |
79 | false
80 |
81 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/jenkins/jenkins_home/gerrit-trigger.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | local
6 | false
7 |
8 | gerrit
9 | 29418
10 |
11 | demouser
12 | demouser@example.com
13 | /tmp/demo_key_rsa
14 | geQ0/Xw/RKYdz242QyVsRg==
15 | false
16 | false
17 | false
18 | gerrit review <CHANGE>,<PATCHSET> --message 'Build Successful <BUILDS_STATS>' --code-review <CODE_REVIEW>
19 | gerrit review <CHANGE>,<PATCHSET> --message 'Build Unstable <BUILDS_STATS>' --code-review <CODE_REVIEW>
20 | gerrit review <CHANGE>,<PATCHSET> --message 'Build Failed <BUILDS_STATS>' --code-review <CODE_REVIEW>
21 | gerrit review <CHANGE>,<PATCHSET> --message 'Build Started <BUILDURL> <STARTED_STATS>' --code-review <CODE_REVIEW>
22 | gerrit review <CHANGE>,<PATCHSET> --message 'No Builds Executed <BUILDS_STATS>' --code-review <CODE_REVIEW>
23 | http://gerrit:8080/
24 | 0
25 | 0
26 | 1
27 | 1
28 | -1
29 | -1
30 | 0
31 | -1
32 | 0
33 | 0
34 | true
35 | true
36 | 3
37 | 30
38 | true
39 | 3600
40 | 0
41 |
42 |
43 | CRVW
44 | Code Review
45 |
46 |
47 | VRIF
48 | Verified
49 |
50 |
51 |
52 | false
53 |
54 | false
55 |
56 | 2
57 |
58 |
59 |
60 |
61 | ALL
62 |
63 | true
64 | false
65 | false
66 |
67 |
68 |
69 |
70 |
71 | 3
72 | 1
73 | 360
74 |
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # gerrit-workflow-demo
2 | Demo of Dockerized gerrit/jenkins workflow functionality
3 |
4 | # What?
5 | * Dockerized demonstration of an integrated Jenkins/Gerrit environment, using Jenkins workflow to construct a build/test pipeline that is triggered when patchsets are submitted for review
6 | * Mimics the work environment of a real world user doing mobile development
7 |
8 | # Why?
9 | * To demonstrate how Jenkins workflow facilitates complex build/testing schemes
10 | * Show how one can construct a Dockerized code review/automation environment with full integration
11 | * Demonstrate an integrated, containerized setup of Jenkins + Gerrit
12 |
13 | This comprises 3 parts:
14 | * Jenkins server using workflow and the gerrit trigger plugin to work with gerrit patchsets
15 | * Gerrit server: acts as a central git repository and provides code review
16 | * Installation of git-repo tool (in both Jenkins and Gerrit), to support projects spanning multiple repositories
17 | * Code repos in gerrit for repo (umbrella manifest) and two sample Java projects
18 |
19 | In fitting with Docker best practices, this is split into two Docker containers:
20 |
21 | * jenkins-gerrit-wfdemo-jenkins - the jenkins host, complete with its own home directory (runs on port 8081)
22 | * jenkins-gerrit-wfdemo-gerrit - gerrit server on port 8080, with local git repos and repo running in server mode
23 |
24 |
25 | # Setup
26 | * Prerequisite: Linux or Mac with a working Docker installation (Boot2Docker or Docker machine will work), and *optionally* Docker Compose
27 | * Prerequisite for use of repo tool: installation
28 | - Linux: `sudo curl https://storage.googleapis.com/git-repo-downloads/repo > /bin/repo && sudo chmod a+x /bin/repo`
29 | - Mac: `curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo && chmod a+x ~/bin/repo`
30 | * Create Host Mappings (optional for linux, **required on Mac for Docker Machine / Boot2Docker** ):
31 | - Find your Docker host's IP and write it down
32 | - In linux on native docker, use 127.0.0.1
33 | - For boot2docker, run `boot2docker ip`
34 | - For Docker Machine, run `docker-machine ls` and finding the matching host
35 | - In your favorite text editor (in sudo mode) open /etc/hosts for editing, ex `sudo vi /etc/hosts`
36 | - Add two new lines mapping this IP to hostname 'jenkins' and 'gerrit' and save the file, ex:
37 |
38 | ```
39 | 192.168.99.100 gerrit
40 | 192.168.99.100 jenkins
41 | ```
42 |
43 | # To run:
44 |
45 | * Using Docker Compose: simply run 'docker-compose up'
46 | * Vanilla Docker:
47 | - To build: run build.sh (using sudo if needed) - it will need a couple minutes
48 | - To run: run start.sh
49 |
50 | # Using it:
51 | * Jenkins is available at localhost:8081 (Linux) or jenkins:8081 (Mac or with hosts entry)
52 | * Gerrit is available at localhost:8080 (Linux) or gerrit:8080 (Mac or with hosts entry)
53 | * To set up the local user with push permissions for gerrit:
54 | - **Linux:** `sh config-gerrit.sh`
55 | - **Mac or with hosts entry:** `sh config-gerrit-mac.sh`
56 |
57 | By default, this will use your git name & email, set the gerrit username as local username, and your HTTP gerrit password as 'goober' (and add your local SSH public RSA key). You can always set this up manually and change it from the gerrit interface.
58 |
59 | # Sample project
60 | * By default, there are three repositories, each with a gerrit project
61 | - 'umbrella' - this contains a manifest for repo
62 | - 'primary' - Java command line tool to generate random text, after a delay. Mimics an API provider, built with maven.
63 | - 'secondary' - Very basic java program to generate arguments to the program in 'primary.' Mimics an API consumer, also built in maven
64 |
65 | # Creating commits and pushing to gerrit directly
66 | 1. You must have a gerrit user configured (see "using it")
67 | 2. Git clone repositories (replace 'gerrit' with localhost if using native Docker)
68 | - http://gerrit:8080/primary
69 | - http://gerrit:8080/secondary
70 | 3. Go into each repository and do the following to install Gerrit hooks:
71 | - *Linux*: `curl -Lo .git/hooks/commit-msg http://localhost:8080/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg`
72 | - *Mac*: `curl -Lo .git/hooks/commit-msg http://gerrit:8080/tools/hooks/commit-msg && chmod u+x .git/hooks/commit-msg`
73 | 4. Create a test commit
74 | - `echo 'blahblahblah' > newfile.txt && git add newfile.txt`
75 | - `git commit -a -m "Test"`
76 | 5. Push by SSH
77 | - *Linux:* `git push ssh://$USER@localhost:29418/primary HEAD:refs/for/master`
78 | - *Mac:* `git push ssh://$USER@gerrit:29418/primary HEAD:refs/for/master`
79 | 6. You should see new changes for review in Gerrit... and responses back from Jenkins after running 'wf-build'
80 |
81 |
82 | # Creating and uploading changes by repo
83 | 1. You must have a gerrit user configured (see "using it") and repo installed
84 | 2. Pull down the project structure via repo (must be installed, see prerequisites)
85 | - *Linux, native docker:* `repo init -u http://localhost:8080/umbrella && repo sync`
86 | - *Mac or linux with hosts entry*: `repo init -u http://gerrit:8080/umbrella -m jenkins.xml && repo sync`
87 | 3. Start a new working branch in repo
88 | - `repo start feature-testing --all`
89 | 4. Push back changes for review:
90 | - `repo upload`
91 | 5. You should see changes ready for review, and Jenkins test results from 'wf-build'
92 | 6. Feel free to go back to the master branch:
93 | - `repo sync -d`
94 |
95 | # To stop:
96 | * Using Docker Compose: 'docker-compose kill && docker-compose rm'
97 | * Vanilla Docker: 'docker rm -f gerrit && docker rm -f jenkins'
98 |
99 | # Troubleshooting
100 |
101 | 1. Verifying Gerrit access by SSH for jenkins
102 | * go to the gerrit-workflow-demo/jenkins
103 | * run the following:
104 | - Linux: `ssh -i demo_key_rsa -p 29418 demouser@localhost`
105 | - Mac: `ssh -i demo_key_rsa -p 29418 demouser@gerrit`
106 | * you should see the following:
107 | ```
108 | Enter passphrase for key 'demo_key_rsa':
109 |
110 | **** Welcome to Gerrit Code Review ****
111 |
112 | Hi demouser, you have successfully connected over SSH.
113 |
114 | Unfortunately, interactive shells are disabled.
115 | To clone a hosted Git repository, use:
116 |
117 | git clone ssh://demouser@gerrit:29418/REPOSITORY_NAME.git
118 |
119 | Connection to localhost closed.
120 | ```
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------