Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…ugin into AngryGami/master
  • Loading branch information
jglick committed Dec 4, 2023
2 parents 6a485b7 + c3031ab commit ce46777
Show file tree
Hide file tree
Showing 365 changed files with 20,739 additions and 6,863 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @jenkinsci/workflow-cps-plugin-developers
17 changes: 14 additions & 3 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
# Intentionally not adding automatic NPM updates because I do
# not trust the plugin's tests to catch issues caused by updates.
# TODO or enable, but avoid merging without first doing a local interactive test?
- package-ecosystem: "maven"
directory: "/"
reviewers:
- "dwnusbaum"
schedule:
interval: "daily"
interval: "weekly"
ignore:
- dependency-name: org.codehaus.groovy:groovy
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "/plugin"
schedule:
interval: "weekly"
2 changes: 0 additions & 2 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
_extends: .github
name-template: v$NEXT_MINOR_VERSION 🌈
tag-template: workflow-cps-$NEXT_MINOR_VERSION
15 changes: 15 additions & 0 deletions .github/workflows/cd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins

name: cd
on:
workflow_dispatch:
check_run:
types:
- completed

jobs:
maven-cd:
uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
secrets:
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
16 changes: 0 additions & 16 deletions .github/workflows/release-drafter.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ node_modules
.classpath
.project
.settings/
*.log
2 changes: 1 addition & 1 deletion .mvn/extensions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
<extension>
<groupId>io.jenkins.tools.incrementals</groupId>
<artifactId>git-changelist-maven-extension</artifactId>
<version>1.2</version>
<version>1.7</version>
</extension>
</extensions>
1 change: 1 addition & 0 deletions .mvn/maven.config
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
-Pconsume-incrementals
-Pmight-produce-incrementals
-Dchangelist.format=%d.v%s
15 changes: 11 additions & 4 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
buildPlugin(useAci: false, configurations: [
[ platform: "linux", jdk: "8", jenkins: null ],
[ platform: "windows", jdk: "8", jenkins: null ],
[ platform: "linux", jdk: "11", jenkins: "2.276", javaLevel: 8 ]
/*
See the documentation for more options:
https://github.com/jenkins-infra/pipeline-library/
*/
buildPlugin(
useContainerAgent: true, // Set to `false` if you need to use Docker for containerized tests
configurations: [
[platform: 'linux', jdk: 21],
[platform: 'windows', jdk: 17],
])
31 changes: 19 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
# Pipeline: Groovy Plugin

[![Jenkins Plugin](https://img.shields.io/jenkins/plugin/v/workflow-cps)](https://plugins.jenkins.io/workflow-cps)
[![Changelog](https://img.shields.io/github/v/tag/jenkinsci/workflow-cps-plugin?label=changelog)](https://github.com/jenkinsci/workflow-cps-plugin/blob/master/CHANGELOG.md)
[![Jenkins Plugin Installs](https://img.shields.io/jenkins/plugin/i/workflow-cps?color=blue)](https://plugins.jenkins.io/workflow-cps)

## Introduction

A key component of the Pipeline plugin suite, this provides the standard execution engine for Pipeline steps, based on a custom [Groovy](http://www.groovy-lang.org/) interpreter that runs inside the Jenkins controller process.
A key component of the Pipeline plugin suite, this provides the standard execution engine for Pipeline steps, based on a custom [Groovy](https://www.groovy-lang.org/) interpreter that runs inside the Jenkins controller process.

(In principle other execution engines could be supported, with `FlowDefinition` being the API entry point, but none has been prototyped and it would likely be a very substantial effort to write one.)

Pipeline Groovy script code such as

```groovy
retry(3) {
for (int i = 0; i < 10; i++) {
branches["branch${i}"] = {
node {
retry(3) {
checkout scm
for (int i = 0; i < 10; i++) {
branches["branch${i}"] = {
node {
retry(3) {
checkout scm
}
sh 'make world'
}
sh 'make world'
}
}
}
Expand Down Expand Up @@ -53,7 +50,7 @@ This plugin was previously the "Workflow CPS plugin" or "Workflow Groovy Plugin"

## Technical design

The plugin uses the [Groovy CPS library](https://github.com/cloudbees/groovy-cps/) to implement a [continuation-passing style transformation](https://en.wikipedia.org/wiki/Continuation-passing_style) on the program as it is compiled.
The plugin uses the Groovy CPS library to implement a [continuation-passing style transformation](https://en.wikipedia.org/wiki/Continuation-passing_style) on the program as it is compiled.
The standard Groovy compiler is used to create the AST, but generation of bytecode is intercepted by a `CompilationCustomizer` which replaces most operations with variants that throw a special “error”, `CpsCallableInvocation`.
This is then caught by the engine, which uses information from it (such as arguments about to be passed to a method call) to pass control on to the next continuation.

Expand All @@ -76,3 +73,13 @@ The `parallel` step uses “green threads” (also known as coöperative multita
The program may seem to perform tasks concurrently, but only because most steps run asynchronously, while the VM thread is idle, and they may overlap in time.
No Java thread is consumed except during the typically brief intervals when Groovy code is actually being run on the VM thread.
The executor widget only displays an entry for the “flyweight” executor on the built-in node when the VM thread is busy; normally it is hidden.

* [Basics of CPS](doc/cps-basics.md)
* [Continuation, Next, and Env](doc/cps-model.md) and how we interpret Groovy program
* [How interpreted program is represented](doc/block-tree.md)
* [CPS + Sandbox](doc/sandbox.md)

## Development

When developing the editor, edit `plugin/package.json` to set `mvnbuild` to `yarn dev` instead of `yarn prod`.
This will allow you to do in situ debugging of JavaScript in your browser.
73 changes: 73 additions & 0 deletions dgm-builder/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps-parent</artifactId>
<version>${changelist}</version>
</parent>

<groupId>com.cloudbees</groupId>
<artifactId>groovy-cps-dgm-builder</artifactId>

<name>CpsDefaultGroovyMethods generator</name>

<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>com.cloudbees.groovy.cps.tool.Driver</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.kohsuke.codemodel</groupId>
<artifactId>codemodel</artifactId>
<version>2.7</version>
</dependency>
<dependency>
<groupId>org.jenkins-ci.main</groupId>
<artifactId>remoting</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<classifier>sources</classifier>
<version>${groovy.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.cloudbees.groovy.cps.tool;

import com.sun.codemodel.writer.FileCodeWriter;
import groovy.lang.GroovyShell;
import hudson.remoting.Which;

import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Set;

public class Driver {
public static void main(String[] args) throws Exception {
new Driver().run(new File(args[0]));
}

public void run(File dir) throws Exception {
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
DiagnosticListener<JavaFileObject> errorListener = createErrorListener();

try (StandardJavaFileManager fileManager = javac.getStandardFileManager(errorListener, Locale.getDefault(), Charset.defaultCharset())) {
fileManager.setLocation(StandardLocation.CLASS_PATH,
Set.of(Which.jarFile(GroovyShell.class)));

File groovySrcJar = Which.jarFile(Driver.class.getClassLoader().getResource("groovy/lang/GroovyShell.java"));

// classes to translate
// TODO include other classes mentioned in DefaultGroovyMethods.DGM_LIKE_CLASSES if they have any applicable methods
List<String> fileNames = List.of("DefaultGroovyMethods",
"DefaultGroovyStaticMethods",
"StringGroovyMethods");

List<JavaFileObject> src = new ArrayList<>();
for (JavaFileObject jfo : fileManager.list(StandardLocation.CLASS_PATH, "org.codehaus.groovy.runtime", Set.of(JavaFileObject.Kind.SOURCE), true)) {
for (String name : fileNames) {
if (jfo.toUri().toString().endsWith("/org/codehaus/groovy/runtime/" + name + ".java")) {
src.add(jfo);
break;
}
}
}

// annotation processing appears to cause the source files to be reparsed
// (even though I couldn't find exactly where it's done), which causes
// Tree symbols created by the original JavacTask.parse() call to be thrown away,
// which breaks later processing.
// So for now, don't perform annotation processing
List<String> options = List.of("-proc:none");

Translator t = new Translator(javac.getTask(null, fileManager, errorListener, options, null, src));

for (String name : fileNames) {
t.translate(
"org.codehaus.groovy.runtime."+name,
"com.cloudbees.groovy.cps.Cps"+name,
groovySrcJar.getName());
}


Files.createDirectories(dir.toPath());
t.generateTo(new FileCodeWriter(dir));
}
}

private DiagnosticListener<JavaFileObject> createErrorListener() {
return System.out::println;
}

}
Loading

0 comments on commit ce46777

Please sign in to comment.