├── Jenkinsfile ├── src ├── main │ ├── resources │ │ ├── org │ │ │ └── jenkinsci │ │ │ │ └── plugins │ │ │ │ └── all_changes │ │ │ │ ├── AllChangesPortlet │ │ │ │ ├── help-name.html │ │ │ │ ├── help-jenkinsJobName.html │ │ │ │ ├── help-numChanges.html │ │ │ │ ├── portlet.jelly │ │ │ │ └── config.groovy │ │ │ │ ├── Messages_de.properties │ │ │ │ ├── Messages.properties │ │ │ │ ├── Messages_es.properties │ │ │ │ ├── AllChangesAction │ │ │ │ ├── index.properties │ │ │ │ ├── index_de.properties │ │ │ │ ├── index_es.properties │ │ │ │ ├── index.groovy │ │ │ │ └── main.groovy │ │ │ │ └── AllChangesWorkflowAction │ │ │ │ ├── index.properties │ │ │ │ ├── index_de.properties │ │ │ │ ├── index_es.properties │ │ │ │ ├── index.groovy │ │ │ │ └── main.groovy │ │ └── index.jelly │ └── java │ │ └── org │ │ └── jenkinsci │ │ └── plugins │ │ └── all_changes │ │ ├── Util.java │ │ ├── ChangesAggregator.java │ │ ├── AllChanges.java │ │ ├── AllChangesWorkflow.java │ │ ├── DependencyChangesAggregator.java │ │ ├── AllChangesPortlet.java │ │ ├── AllChangesWorkflowAction.java │ │ ├── SubProjectChangesAggregator.java │ │ └── AllChangesAction.java └── test │ └── java │ └── org │ └── jenkinsci │ └── plugins │ └── all_changes │ └── AllChangesActionTest.java ├── .gitignore ├── README.markdown └── pom.xml /Jenkinsfile: -------------------------------------------------------------------------------- 1 | buildPlugin() 2 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesPortlet/help-name.html: -------------------------------------------------------------------------------- 1 |
2 | Name of the portlet. 3 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesPortlet/help-jenkinsJobName.html: -------------------------------------------------------------------------------- 1 |
2 | Jenkins Job Name of which the latest changes should be shown. 3 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesPortlet/help-numChanges.html: -------------------------------------------------------------------------------- 1 |
2 | Number of displayable changes within the portlet (defaults to 10). 3 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/Messages_de.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/all-changes-plugin/master/src/main/resources/org/jenkinsci/plugins/all_changes/Messages_de.properties -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X files 2 | .DS_Store 3 | 4 | # Intellij files 5 | *.iml 6 | .idea/* 7 | classes 8 | 9 | # Maven 10 | target/* 11 | pom.xml.releaseBackup 12 | release.properties 13 | 14 | # Jenkins workplace files 15 | work* 16 | 17 | # Gradle 18 | .gradle 19 | build 20 | libsrc/* 21 | 22 | # Eclipse 23 | /.classpath 24 | /.project 25 | /.settings* 26 | /target/ -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | All Changes Plugin 2 | ======================= 3 | 4 | Shows all changes which influenced the build. 5 | 6 | Features 7 | -------- 8 | - Shows changes by dependent builds (via fingerprinting) 9 | - Shows changes by subprojects added via a BuildStep from the [parameterized-trigger-plugin](https://github.com/jenkinsci/parameterized-trigger-plugin) 10 | 11 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/Messages.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | AllChanges.allChanges=All Changes -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/Messages_es.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | AllChanges.allChanges=Todos los cambios -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesAction/index.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title={0} All Changes 26 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction/index.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title={0} All Changes 26 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesPortlet/portlet.jelly: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |

${'Job with name '+ it.jenkinsJobName +' is not available.'}

18 |
19 |
20 |
21 | 22 |
23 |
-------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesAction/index_de.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title=Alle \u00c4nderungen in {0} 26 | detail=Details 27 | All\ Changes=Alle \u00c4nderungen 28 | No\ builds.=Keine Builds. 29 | No\ changes\ in\ any\ of\ the\ builds.=Keine \u00c4nderungen in den Builds. 30 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesAction/index_es.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title=Todos los cambios de {0} 26 | All\ Changes=Todos los cambios 27 | No\ builds.=Sin ejecuciones. 28 | detail=detalles 29 | No\ changes\ in\ any\ of\ the\ builds.=No hay nuevos cambios en ninguna ejecuci\u00f3n. -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction/index_de.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title=Alle \u00c4nderungen in {0} 26 | detail=Details 27 | All\ Changes=Alle \u00c4nderungen 28 | No\ builds.=Keine Builds. 29 | No\ changes\ in\ any\ of\ the\ builds.=Keine \u00c4nderungen in den Builds. 30 | -------------------------------------------------------------------------------- /src/main/resources/index.jelly: -------------------------------------------------------------------------------- 1 | 24 | 25 | 28 | 29 |
30 | This plugin shows all changes (also from dependent projects, sub-projects, ...) for a project 31 |
32 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction/index_es.properties: -------------------------------------------------------------------------------- 1 | # 2 | # The MIT License 3 | # 4 | # Copyright (c) 2011, Stefan Wolf 5 | # 6 | # Permission is hereby granted, free of charge, to any person obtaining a copy 7 | # of this software and associated documentation files (the "Software"), to deal 8 | # in the Software without restriction, including without limitation the rights 9 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | # copies of the Software, and to permit persons to whom the Software is 11 | # furnished to do so, subject to the following conditions: 12 | # 13 | # The above copyright notice and this permission notice shall be included in 14 | # all copies or substantial portions of the Software. 15 | # 16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | # THE SOFTWARE. 23 | # 24 | 25 | all.changes.title=Todos los cambios de {0} 26 | All\ Changes=Todos los cambios 27 | No\ builds.=Sin ejecuciones. 28 | detail=detalles 29 | No\ changes\ in\ any\ of\ the\ builds.=No hay nuevos cambios en ninguna ejecuci\u00f3n. -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesPortlet/config.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2016, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes.AllChangesPortlet 26 | 27 | f = namespace(lib.FormTagLib) 28 | t = namespace("/lib/hudson") 29 | 30 | 31 | f.entry(field:"name", title: "Name") { 32 | f.textbox() 33 | } 34 | 35 | f.entry(field:"jenkinsJobName", title: "Job Name") { 36 | f.textbox() 37 | } 38 | 39 | f.entry(field:"numChanges", title: "Number of changes to show") { 40 | f.number(default: 10, clazz:"required number") 41 | } -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2016, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | package org.jenkinsci.plugins.all_changes; 25 | 26 | import jenkins.model.Jenkins; 27 | 28 | /** 29 | * Created by suresh on 6/5/2016. 30 | */ 31 | public class Util { 32 | 33 | public static Jenkins getInstance() { 34 | Jenkins instance = Jenkins.getInstance(); 35 | if (instance == null) { 36 | throw new IllegalStateException("Jenkins has not been started, or was already shut down"); 37 | } 38 | return instance; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/ChangesAggregator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import hudson.ExtensionList; 28 | import hudson.ExtensionPoint; 29 | import hudson.model.AbstractBuild; 30 | import jenkins.model.Jenkins; 31 | 32 | import java.util.Collection; 33 | 34 | public abstract class ChangesAggregator implements ExtensionPoint { 35 | public abstract Collection aggregateBuildsWithChanges(AbstractBuild build); 36 | 37 | public static ExtensionList all() { 38 | return Util.getInstance().getExtensionList(ChangesAggregator.class); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/AllChanges.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import hudson.Extension; 28 | import hudson.model.AbstractProject; 29 | import hudson.model.Action; 30 | import hudson.model.TransientProjectActionFactory; 31 | 32 | import java.util.Collection; 33 | import java.util.Collections; 34 | 35 | /** 36 | * @author wolfs 37 | */ 38 | @Extension 39 | public class AllChanges extends TransientProjectActionFactory { 40 | @Override 41 | public Collection createFor(AbstractProject target) { 42 | return Collections.singleton(new AllChangesAction(target)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/AllChangesWorkflow.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2017, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import hudson.Extension; 28 | import hudson.model.Action; 29 | import jenkins.model.TransientActionFactory; 30 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 31 | 32 | import java.util.Collection; 33 | import java.util.Collections; 34 | 35 | @Extension 36 | public class AllChangesWorkflow extends TransientActionFactory { 37 | 38 | @Override 39 | public Class type() { 40 | return WorkflowJob.class; 41 | } 42 | 43 | @Override 44 | public Collection createFor(WorkflowJob target) { 45 | return Collections.singleton(new AllChangesWorkflowAction(target)); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction/index.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2017, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes.AllChangesWorkflowAction 26 | 27 | import com.google.common.collect.Multimap 28 | import hudson.Functions 29 | import hudson.scm.ChangeLogSet 30 | import org.jenkinsci.plugins.workflow.job.WorkflowRun 31 | 32 | import java.text.DateFormat 33 | import org.jvnet.localizer.LocaleProvider 34 | 35 | f = namespace(lib.FormTagLib) 36 | l = namespace(lib.LayoutTagLib) 37 | t = namespace("/lib/hudson") 38 | st = namespace("jelly:stapler") 39 | 40 | l.layout(title: _("all.changes.title", my.project.name)) { 41 | st.include(page: "sidepanel.jelly", it: my.project) 42 | l.main_panel() { 43 | h1(_("All Changes")) 44 | st.include(page: "main.groovy", it: my) 45 | } 46 | } 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesAction/index.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes.AllChangesAction 26 | 27 | import com.google.common.collect.Multimap 28 | import hudson.Functions 29 | import hudson.model.AbstractBuild 30 | import hudson.model.AbstractBuild.DependencyChange 31 | import hudson.scm.ChangeLogSet 32 | import java.text.DateFormat 33 | import org.jvnet.localizer.LocaleProvider 34 | 35 | f = namespace(lib.FormTagLib) 36 | l = namespace(lib.LayoutTagLib) 37 | t = namespace("/lib/hudson") 38 | st = namespace("jelly:stapler") 39 | 40 | l.layout(title: _("all.changes.title", my.project.name)) { 41 | st.include(page: "sidepanel.jelly", it: my.project) 42 | l.main_panel() { 43 | h1(_("All Changes")) 44 | st.include(page: "main.groovy", it: my) 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/DependencyChangesAggregator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ImmutableList; 28 | import hudson.Extension; 29 | import hudson.model.AbstractBuild; 30 | import hudson.model.AbstractProject; 31 | 32 | import java.util.Collection; 33 | import java.util.Map; 34 | 35 | /** 36 | * @author wolfs 37 | */ 38 | @Extension 39 | public class DependencyChangesAggregator extends ChangesAggregator { 40 | @Override 41 | public Collection aggregateBuildsWithChanges(AbstractBuild build) { 42 | ImmutableList.Builder builder = ImmutableList.builder(); 43 | Map depChanges = build.getDependencyChanges((AbstractBuild) build.getPreviousBuild()); 44 | for (AbstractBuild.DependencyChange depChange : depChanges.values()) { 45 | builder.addAll(depChange.getBuilds()); 46 | } 47 | return builder.build(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/AllChangesPortlet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2016, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ArrayListMultimap; 28 | import com.google.common.collect.HashMultimap; 29 | import com.google.common.collect.ImmutableList; 30 | import com.google.common.collect.Multimap; 31 | import com.google.common.collect.Sets; 32 | import hudson.Extension; 33 | import hudson.model.AbstractBuild; 34 | import hudson.model.AbstractProject; 35 | import hudson.model.Descriptor; 36 | import hudson.plugins.view.dashboard.DashboardPortlet; 37 | import hudson.scm.ChangeLogSet; 38 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 39 | import org.kohsuke.stapler.DataBoundConstructor; 40 | 41 | import java.util.List; 42 | import java.util.Set; 43 | 44 | /** 45 | * Portlet to calculate all changes for a build 46 | * It uses ChangesAggregators to do so. 47 | * 48 | * @author suresh 49 | */ 50 | public class AllChangesPortlet extends DashboardPortlet { 51 | 52 | private final String jenkinsJobName; 53 | private final int numChanges; 54 | 55 | @DataBoundConstructor 56 | public AllChangesPortlet(String name, String jenkinsJobName, int numChanges) { 57 | super(name); 58 | this.jenkinsJobName = jenkinsJobName; 59 | this.numChanges = numChanges; 60 | } 61 | 62 | public String getJenkinsJobName() { 63 | return jenkinsJobName; 64 | } 65 | 66 | public String getJenkinsJobNameForUrl() { 67 | return jenkinsJobName == null ? "" : jenkinsJobName.replace(" ", "%20"); 68 | } 69 | 70 | public int getNumChanges() { 71 | return numChanges; 72 | } 73 | 74 | public Object getProjectAction() { 75 | return resolveProject(jenkinsJobName); 76 | } 77 | 78 | private Object resolveProject(String name) { 79 | Object project = Util.getInstance().getItem(name, Util.getInstance(), AbstractProject.class); 80 | if (project == null) { 81 | project = Util.getInstance().getItem(name, Util.getInstance(), WorkflowJob.class); 82 | } 83 | if (project instanceof AbstractProject) { 84 | return new AllChangesAction((AbstractProject) project, this.numChanges); 85 | } else if (project instanceof WorkflowJob) { 86 | return new AllChangesWorkflowAction((WorkflowJob) project, this.numChanges); 87 | } 88 | return null; 89 | } 90 | 91 | @Extension 92 | public static class AllChangesPortletDescriptor extends Descriptor { 93 | 94 | @Override 95 | public String getDisplayName() { 96 | return "All Changes Portlet"; 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2017, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ArrayListMultimap; 28 | import com.google.common.collect.HashMultimap; 29 | import com.google.common.collect.ImmutableList; 30 | import com.google.common.collect.Multimap; 31 | import com.google.common.collect.Sets; 32 | import hudson.model.Action; 33 | import hudson.scm.ChangeLogSet; 34 | import org.jenkinsci.plugins.workflow.job.WorkflowJob; 35 | import org.jenkinsci.plugins.workflow.job.WorkflowRun; 36 | 37 | import java.util.Set; 38 | 39 | public class AllChangesWorkflowAction implements Action { 40 | 41 | private WorkflowJob project; 42 | private int numChanges = 0; 43 | 44 | AllChangesWorkflowAction(WorkflowJob project) { 45 | this.project = project; 46 | } 47 | 48 | AllChangesWorkflowAction(WorkflowJob project, int numChanges) { 49 | this.project = project; 50 | this.numChanges = numChanges; 51 | } 52 | 53 | public String getIconFileName() { 54 | return "notepad.png"; 55 | } 56 | 57 | public String getDisplayName() { 58 | return Messages.AllChanges_allChanges(); 59 | } 60 | 61 | public String getUrlName() { 62 | return "all-changes"; 63 | } 64 | 65 | /** 66 | * Returns all changes which contribute to a build. 67 | * 68 | * @param build 69 | * @return 70 | */ 71 | public Multimap getAllChanges(WorkflowRun build) { 72 | Set builds = getContributingBuilds(build); 73 | Multimap changes = ArrayListMultimap.create(); 74 | for (WorkflowRun changedBuild : builds) { 75 | for (ChangeLogSet changeLogSet : changedBuild.getChangeSets()) { 76 | ChangeLogSet changeSet = (ChangeLogSet)changeLogSet; 77 | for (ChangeLogSet.Entry entry : changeSet) { 78 | changes.put(entry.getCommitId() + entry.getMsgAnnotated() + entry.getTimestamp(), entry); 79 | } 80 | } 81 | } 82 | Multimap change2Build = HashMultimap.create(); 83 | for (String changeKey : changes.keySet()) { 84 | ChangeLogSet.Entry change = changes.get(changeKey).iterator().next(); 85 | for (ChangeLogSet.Entry entry : changes.get(changeKey)) { 86 | change2Build.put(change, (WorkflowRun) entry.getParent().getRun()); 87 | } 88 | } 89 | return change2Build; 90 | } 91 | 92 | /** 93 | * Uses all ChangesAggregators to calculate the contributing builds 94 | * 95 | * @return all changes which contribute to the given build 96 | */ 97 | public Set getContributingBuilds(WorkflowRun build) { 98 | Set builds = Sets.newHashSet(); 99 | builds.add(build); 100 | return builds; 101 | } 102 | 103 | public WorkflowJob getProject() { 104 | return project; 105 | } 106 | 107 | public int getNumChanges() { 108 | return numChanges; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/test/java/org/jenkinsci/plugins/all_changes/AllChangesActionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ImmutableList; 28 | import com.google.common.collect.ImmutableSet; 29 | import com.google.common.collect.Lists; 30 | import hudson.model.AbstractBuild; 31 | import org.junit.Test; 32 | 33 | import java.util.Set; 34 | 35 | import static org.junit.Assert.assertTrue; 36 | import static org.mockito.Mockito.*; 37 | 38 | /** 39 | * @author wolfs 40 | */ 41 | public class AllChangesActionTest { 42 | 43 | @Test 44 | public void getContributingBuildsShouldWorkTransitively() throws Exception { 45 | AllChangesAction changesAction = new AllChangesAction(null); 46 | ChangesAggregator aggregatorMock = mock(ChangesAggregator.class); 47 | AbstractBuild build = mock(AbstractBuild.class); 48 | AbstractBuild build2 = mock(AbstractBuild.class); 49 | AbstractBuild build3 = mock(AbstractBuild.class); 50 | when(aggregatorMock.aggregateBuildsWithChanges(build)).thenReturn(ImmutableList.of(build2)); 51 | when(aggregatorMock.aggregateBuildsWithChanges(build2)).thenReturn(ImmutableList.of(build3)); 52 | 53 | changesAction.aggregators = Lists.newArrayList(aggregatorMock); 54 | 55 | Set foundBuilds = changesAction.getContributingBuilds(build); 56 | 57 | assertTrue(foundBuilds.equals(ImmutableSet.of(build, build2, build3))); 58 | } 59 | 60 | @Test 61 | public void getContributingBuildsShouldWorkHandleCycles() throws Exception { 62 | AllChangesAction changesAction = new AllChangesAction(null); 63 | ChangesAggregator aggregatorMock = mock(ChangesAggregator.class); 64 | AbstractBuild build = mock(AbstractBuild.class); 65 | AbstractBuild build2 = mock(AbstractBuild.class); 66 | AbstractBuild build3 = mock(AbstractBuild.class); 67 | when(aggregatorMock.aggregateBuildsWithChanges(build)).thenReturn(ImmutableList.of(build2)); 68 | when(aggregatorMock.aggregateBuildsWithChanges(build2)).thenReturn(ImmutableList.of(build3)); 69 | when(aggregatorMock.aggregateBuildsWithChanges(build3)).thenReturn(ImmutableList.of(build)); 70 | 71 | changesAction.aggregators = Lists.newArrayList(aggregatorMock); 72 | 73 | Set foundBuilds = changesAction.getContributingBuilds(build); 74 | 75 | assertTrue(foundBuilds.equals(ImmutableSet.of(build, build2, build3))); 76 | } 77 | 78 | @Test 79 | public void getContributingBuildsWorksWithMoreThanOneAggregator() throws Exception { 80 | AllChangesAction changesAction = new AllChangesAction(null); 81 | ChangesAggregator aggregatorMock = mock(ChangesAggregator.class); 82 | ChangesAggregator aggregatorMock2 = mock(ChangesAggregator.class); 83 | AbstractBuild build = mock(AbstractBuild.class); 84 | AbstractBuild build2 = mock(AbstractBuild.class); 85 | AbstractBuild build3 = mock(AbstractBuild.class); 86 | when(aggregatorMock.aggregateBuildsWithChanges(build)).thenReturn(ImmutableList.of(build2)); 87 | when(aggregatorMock2.aggregateBuildsWithChanges(build2)).thenReturn(ImmutableList.of(build3)); 88 | 89 | changesAction.aggregators = Lists.newArrayList(aggregatorMock, aggregatorMock2); 90 | 91 | Set foundBuilds = changesAction.getContributingBuilds(build); 92 | 93 | assertTrue(foundBuilds.equals(ImmutableSet.of(build, build2, build3))); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 24 | 25 | 26 | 4.0.0 27 | 28 | org.jenkins-ci.plugins 29 | plugin 30 | 2.5 31 | 32 | 33 | 34 | org.jenkins-ci.plugins 35 | all-changes 36 | 1.6-SNAPSHOT 37 | hpi 38 | All changes plugin 39 | Shows more changes on the project page 40 | http://wiki.jenkins-ci.org/display/JENKINS/All+Changes+Plugin 41 | 42 | 43 | The MIT license 44 | http://www.opensource.org/licenses/mit-license.php 45 | repo 46 | 47 | 48 | 49 | 50 | wolfs 51 | Stefan Wolf 52 | 53 | 54 | pskumar448 55 | Suresh Kumar 56 | pskumar448@gmail.com 57 | 58 | 59 | 60 | 1.625.3 61 | 7 62 | 2.1 63 | 64 | 65 | 66 | 67 | org.jenkins-ci.plugins 68 | parameterized-trigger 69 | 2.30 70 | true 71 | 72 | 73 | 74 | org.jenkins-ci.plugins 75 | dashboard-view 76 | 2.9.9 77 | false 78 | 79 | 80 | org.jenkins-ci.plugins.workflow 81 | workflow-job 82 | 1.14 83 | 84 | 85 | org.mockito 86 | mockito-core 87 | 1.10.19 88 | test 89 | 90 | 91 | org.apache.httpcomponents 92 | httpclient 93 | 4.5.2 94 | test 95 | 96 | 97 | 98 | 100 | 101 | 102 | repo.jenkins-ci.org 103 | https://repo.jenkins-ci.org/public/ 104 | 105 | 106 | 107 | 108 | 109 | repo.jenkins-ci.org 110 | https://repo.jenkins-ci.org/public/ 111 | 112 | 113 | 114 | scm:git:git://github.com/jenkinsci/all-changes-plugin.git 115 | scm:git:git@github.com:jenkinsci/all-changes-plugin.git 116 | http://github.com/jenkinsci/all-changes-plugin 117 | HEAD 118 | 119 | 120 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesWorkflowAction/main.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2017, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | import com.google.common.collect.Multimap 26 | import hudson.Functions 27 | import hudson.scm.ChangeLogSet 28 | import org.jenkinsci.plugins.workflow.job.WorkflowRun 29 | import org.jvnet.localizer.LocaleProvider 30 | 31 | import java.text.DateFormat 32 | 33 | f = namespace(lib.FormTagLib) 34 | l = namespace(lib.LayoutTagLib) 35 | t = namespace("/lib/hudson") 36 | st = namespace("jelly:stapler") 37 | 38 | 39 | def from = buildNumber(request.getParameter('from')); 40 | def to = buildNumber(request.getParameter('to')); 41 | 42 | def builds = Functions.filter(my.project.buildsAsMap, from, to).values() 43 | if (builds.empty) { 44 | text(_("No builds.")) 45 | } else { 46 | showChanges(builds) 47 | } 48 | 49 | 50 | private buildNumber(String build) { 51 | if (build?.isInteger()) { 52 | return build 53 | } else { 54 | def permaLink = my.project.getPermalinks().get(build) 55 | def run = permaLink?.resolve(my.project) 56 | return run?.number?.toString() 57 | } 58 | } 59 | 60 | private showChanges(Collection builds) { 61 | def changedBuildCount = 1; 62 | boolean hadChanges = false; 63 | for (WorkflowRun build in builds) { 64 | Multimap changes = my.getAllChanges(build); 65 | if (changes.empty) { 66 | continue 67 | } 68 | if(changedBuildCount > my.numChanges && my.numChanges != 0) 69 | { 70 | break 71 | } 72 | hadChanges = true 73 | h2() { 74 | a(href: "${my.project.absoluteUrl}/${build.number}/changes", 75 | """${build.displayName} (${ 76 | DateFormat.getDateTimeInstance( 77 | DateFormat.MEDIUM, 78 | DateFormat.MEDIUM, 79 | LocaleProvider.locale).format(build.timestamp.time)})""") 80 | } 81 | ul() { 82 | for (entry in changes.keySet()) { 83 | li() { 84 | showEntry(entry, build, changes.get(entry)) 85 | } 86 | } 87 | } 88 | changedBuildCount++; 89 | } 90 | if (!hadChanges) { 91 | text(_("No changes in any of the builds.")) 92 | } 93 | } 94 | 95 | private def showEntry(entry, WorkflowRun build, Collection builds) { 96 | showChangeSet(entry) 97 | boolean firstDrawn = false 98 | for (WorkflowRun b in builds) { 99 | if (b != build) { 100 | if (!firstDrawn) { 101 | text(" (") 102 | firstDrawn = true 103 | } 104 | else { 105 | text(", ") 106 | } 107 | a(href: "${rootURL}/${b.project.url}") {text(b.project.displayName)} 108 | st.nbsp() 109 | a(href: "${rootURL}/${b.url}") { 110 | text(b.displayName) 111 | } 112 | } 113 | } 114 | if (firstDrawn) { 115 | text(")") 116 | } 117 | } 118 | 119 | private def showChangeSet(ChangeLogSet.Entry c) { 120 | def build = c.parent.run 121 | def browser = c.parent.browser 122 | raw(c.getCommitId()) 123 | raw(" » ") 124 | raw(c.msgAnnotated) 125 | raw(" — ") 126 | if (browser?.getChangeSetLink(c)) { 127 | a(href: browser.getChangeSetLink(c), _("detail")) 128 | } else { 129 | a(href: "${build.absoluteUrl}changes", _("detail")) 130 | } 131 | } -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/SubProjectChangesAggregator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ImmutableList; 28 | import com.google.common.collect.Lists; 29 | import com.google.common.collect.Sets; 30 | import hudson.Extension; 31 | import hudson.Plugin; 32 | import hudson.model.AbstractBuild; 33 | import hudson.model.AbstractProject; 34 | import hudson.model.Cause; 35 | import hudson.model.FreeStyleProject; 36 | import hudson.plugins.parameterizedtrigger.BlockableBuildTriggerConfig; 37 | import hudson.plugins.parameterizedtrigger.TriggerBuilder; 38 | import hudson.tasks.Builder; 39 | import hudson.util.RunList; 40 | import jenkins.model.Jenkins; 41 | 42 | import java.util.Collection; 43 | import java.util.List; 44 | import java.util.Set; 45 | 46 | /** 47 | * @author wolfs 48 | */ 49 | @Extension 50 | public class SubProjectChangesAggregator extends ChangesAggregator { 51 | @Override 52 | public Collection aggregateBuildsWithChanges(AbstractBuild build) { 53 | Plugin parameterizedTrigger = Util.getInstance().getPlugin("parameterized-trigger"); 54 | if (parameterizedTrigger == null) { 55 | return ImmutableList.of(); 56 | } 57 | 58 | AbstractProject project = build.getProject(); 59 | Set> subProjects = Sets.newHashSet(); 60 | Set builds = Sets.newHashSet(); 61 | if (project instanceof FreeStyleProject) { 62 | subProjects.addAll(getSubProjects((FreeStyleProject) project)); 63 | builds.addAll(getTriggeredBuilds(build, subProjects)); 64 | } 65 | 66 | return builds; 67 | } 68 | 69 | private List getTriggeredBuilds(AbstractBuild build, Collection> subProjects) { 70 | List builds = Lists.newArrayList(); 71 | for (AbstractProject subProject : subProjects) { 72 | RunList> subBuildsDuringBuild = subProject.getBuilds().byTimestamp(build.getTimeInMillis(), build.getTimeInMillis() + build.getDuration()); 73 | for (AbstractBuild candidate : subBuildsDuringBuild) { 74 | if (isSubBuild(build, candidate)) { 75 | builds.add(candidate); 76 | } 77 | } 78 | } 79 | return builds; 80 | } 81 | 82 | private List> getSubProjects(FreeStyleProject project) { 83 | List> subProjects = Lists.newArrayList(); 84 | List builders = project.getBuilders(); 85 | for (Builder builder : builders) { 86 | if (builder instanceof TriggerBuilder) { 87 | TriggerBuilder tBuilder = (TriggerBuilder) builder; 88 | for (BlockableBuildTriggerConfig config : tBuilder.getConfigs()) { 89 | for (AbstractProject abstractProject : config.getProjectList(null)) { 90 | if (config.getBlock() != null) { 91 | subProjects.add(abstractProject); 92 | } 93 | } 94 | } 95 | } 96 | } 97 | return subProjects; 98 | } 99 | 100 | private boolean isSubBuild(AbstractBuild build, AbstractBuild subBuild) { 101 | List causes = subBuild.getCauses(); 102 | for (Cause cause : causes) { 103 | if (cause instanceof Cause.UpstreamCause) { 104 | Cause.UpstreamCause upstreamCause = (Cause.UpstreamCause) cause; 105 | if (upstreamCause.pointsTo(build)) { 106 | return true; 107 | } 108 | } 109 | } 110 | return false; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/org/jenkinsci/plugins/all_changes/AllChangesAction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2011, Stefan Wolf 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes; 26 | 27 | import com.google.common.collect.ArrayListMultimap; 28 | import com.google.common.collect.HashMultimap; 29 | import com.google.common.collect.ImmutableList; 30 | import com.google.common.collect.Multimap; 31 | import com.google.common.collect.Sets; 32 | import hudson.model.AbstractBuild; 33 | import hudson.model.AbstractProject; 34 | import hudson.model.Action; 35 | import hudson.scm.ChangeLogSet; 36 | 37 | import java.util.List; 38 | import java.util.Set; 39 | 40 | /** 41 | * Action to calculate all changes for a build 42 | * It uses ChangesAggregators to to so. 43 | * 44 | * @author wolfs 45 | */ 46 | public class AllChangesAction implements Action { 47 | 48 | private AbstractProject project; 49 | private int numChanges = 0; 50 | transient 51 | List aggregators; 52 | 53 | AllChangesAction(AbstractProject project) { 54 | this.project = project; 55 | } 56 | 57 | AllChangesAction(AbstractProject project, int numChanges) { 58 | this.project = project; 59 | this.numChanges = numChanges; 60 | } 61 | 62 | public String getIconFileName() { 63 | return "notepad.png"; 64 | } 65 | 66 | public String getDisplayName() { 67 | return Messages.AllChanges_allChanges(); 68 | } 69 | 70 | public String getUrlName() { 71 | return "all-changes"; 72 | } 73 | 74 | /** 75 | * Returns all changes which contribute to a build. 76 | * 77 | * @param build 78 | * @return 79 | */ 80 | public Multimap getAllChanges(AbstractBuild build) { 81 | Set builds = getContributingBuilds(build); 82 | Multimap changes = ArrayListMultimap.create(); 83 | for (AbstractBuild changedBuild : builds) { 84 | ChangeLogSet changeSet = changedBuild.getChangeSet(); 85 | for (ChangeLogSet.Entry entry : changeSet) { 86 | changes.put(entry.getCommitId() + entry.getMsgAnnotated() + entry.getTimestamp(), entry); 87 | } 88 | } 89 | Multimap change2Build = HashMultimap.create(); 90 | for (String changeKey : changes.keySet()) { 91 | ChangeLogSet.Entry change = changes.get(changeKey).iterator().next(); 92 | for (ChangeLogSet.Entry entry : changes.get(changeKey)) { 93 | change2Build.put(change, entry.getParent().build); 94 | } 95 | } 96 | return change2Build; 97 | } 98 | 99 | /** 100 | * Uses all ChangesAggregators to calculate the contributing builds 101 | * 102 | * @return all changes which contribute to the given build 103 | */ 104 | public Set getContributingBuilds(AbstractBuild build) { 105 | if (aggregators == null) { 106 | aggregators = ImmutableList.copyOf(ChangesAggregator.all()); 107 | } 108 | Set builds = Sets.newHashSet(); 109 | builds.add(build); 110 | int size = 0; 111 | // Saturate the build Set 112 | do { 113 | size = builds.size(); 114 | Set newBuilds = Sets.newHashSet(); 115 | for (ChangesAggregator aggregator : aggregators) { 116 | for (AbstractBuild depBuild : builds) { 117 | newBuilds.addAll(aggregator.aggregateBuildsWithChanges(depBuild)); 118 | } 119 | } 120 | builds.addAll(newBuilds); 121 | } while (size < builds.size()); 122 | return builds; 123 | } 124 | 125 | public AbstractProject getProject() { 126 | return project; 127 | } 128 | 129 | public int getNumChanges() { 130 | return numChanges; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/main/resources/org/jenkinsci/plugins/all_changes/AllChangesAction/main.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * 4 | * Copyright (c) 2017, Suresh 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | 25 | package org.jenkinsci.plugins.all_changes.AllChangesAction 26 | 27 | import com.google.common.collect.Multimap 28 | import hudson.Functions 29 | import hudson.model.AbstractBuild 30 | import hudson.scm.ChangeLogSet 31 | import org.jvnet.localizer.LocaleProvider 32 | 33 | import java.text.DateFormat 34 | 35 | f = namespace(lib.FormTagLib) 36 | l = namespace(lib.LayoutTagLib) 37 | t = namespace("/lib/hudson") 38 | st = namespace("jelly:stapler") 39 | 40 | 41 | def from = buildNumber(request.getParameter('from')); 42 | def to = buildNumber(request.getParameter('to')); 43 | 44 | def builds = Functions.filter(my.project.buildsAsMap, from, to).values() 45 | if (builds.empty) { 46 | text(_("No builds.")) 47 | } else { 48 | showChanges(builds) 49 | } 50 | 51 | private buildNumber(String build) { 52 | if (build?.isInteger()) { 53 | return build 54 | } else { 55 | def permaLink = my.project.getPermalinks().get(build) 56 | def run = permaLink?.resolve(my.project) 57 | return run?.number?.toString() 58 | } 59 | } 60 | 61 | private showChanges(Collection builds) { 62 | def changedBuildCount = 1; 63 | boolean hadChanges = false; 64 | for (AbstractBuild build in builds) { 65 | Multimap changes = my.getAllChanges(build); 66 | if (changes.empty) { 67 | continue 68 | } 69 | if(changedBuildCount > my.numChanges && my.numChanges != 0) 70 | { 71 | break 72 | } 73 | hadChanges = true 74 | h2() { 75 | a(href: "${my.project.absoluteUrl}/${build.number}/changes", 76 | """${build.displayName} (${ 77 | DateFormat.getDateTimeInstance( 78 | DateFormat.MEDIUM, 79 | DateFormat.MEDIUM, 80 | LocaleProvider.locale).format(build.timestamp.time)})""") 81 | } 82 | ul() { 83 | for (entry in changes.keySet()) { 84 | li() { 85 | showEntry(entry, build, changes.get(entry)) 86 | } 87 | } 88 | } 89 | changedBuildCount++; 90 | } 91 | if (!hadChanges) { 92 | text(_("No changes in any of the builds.")) 93 | } 94 | } 95 | 96 | private def showEntry(entry, AbstractBuild build, Collection builds) { 97 | showChangeSet(entry) 98 | boolean firstDrawn = false 99 | for (AbstractBuild b in builds) { 100 | if (b != build) { 101 | if (!firstDrawn) { 102 | text(" (") 103 | firstDrawn = true 104 | } 105 | else { 106 | text(", ") 107 | } 108 | a(href: "${rootURL}/${b.project.url}") {text(b.project.displayName)} 109 | st.nbsp() 110 | a(href: "${rootURL}/${b.url}") { 111 | text(b.displayName) 112 | } 113 | } 114 | } 115 | if (firstDrawn) { 116 | text(")") 117 | } 118 | } 119 | 120 | private def showChangeSet(ChangeLogSet.Entry c) { 121 | def build = c.parent.build 122 | def browser = build.project.scm.effectiveBrowser 123 | raw(c.getCommitId()) 124 | raw(" » ") 125 | raw(c.msgAnnotated) 126 | raw(" — ") 127 | if (browser?.getChangeSetLink(c)) { 128 | a(href: browser.getChangeSetLink(c), _("detail")) 129 | } else { 130 | a(href: "${build.absoluteUrl}changes", _("detail")) 131 | } 132 | } 133 | 134 | private def showDependencyChanges(AbstractBuild.DependencyChange dep) { 135 | a(href: "${rootURL}/${dep.project.url}") {text(dep.project.displayName)} 136 | st.nbsp() 137 | a(href: "${rootURL}/${dep.from.url}") { 138 | delegate.img(src: "${imagesURL}/16x16/${dep.from.buildStatusUrl}", 139 | alt: "${dep.from.iconColor.description}", height: "16", width: "16") 140 | text(dep.from.displayName) 141 | } 142 | 143 | raw("→") // right arrow 144 | a(href: "${rootURL}/${dep.to.url}") { 145 | delegate.img(src: "${imagesURL}/16x16/${dep.to.buildStatusUrl}", 146 | alt: "${dep.to.iconColor.description}", height: "16", width: "16") 147 | text(dep.to.displayName) 148 | } 149 | } --------------------------------------------------------------------------------