jenkinsci / java-client-api Goto Github PK
View Code? Open in Web Editor NEWA Jenkins API client for Java
License: MIT License
A Jenkins API client for Java
License: MIT License
It would be a good idea having the changeset and details from the change sets.
something like this: json:
"firstBuild" : {
"number" : 1,
"url" : "http://ci.soebes.de:8080/view/SoEBeS/job/iterator-maven-plugin/1/"
},
Extract the version from http header.
Continuing the problem I reported a few days ago about the crumbIssuer #51, I stumbled upon the following:
In case of delete a job, if you don't have enable the crumbIssuer feature in your Jenkins instance you can't delete jobs.
public void deleteJob(String jobName) throws IOException {
client.post("/job/" + encode(jobName) + "/doDelete");
}
public <R extends BaseModel, D> R post(String path, D data, Class<R> cls) throws IOException {
HttpPost request = new HttpPost(api(path));
Crumb crumb = get("/crumbIssuer", Crumb.class);
if (crumb != null) {
request.addHeader(new BasicHeader(crumb.getCrumbRequestField(), crumb.getCrumb()));
}
//(the rest of the method)
}
The problem: deleteJob() need to make a POST call, this post() method before make the concrete HTTP call to delete the job, makes a GET call to get the crumbIssuer, for example in my case that i don't have the crumbIssuer enabled, this method explode with a HTTP exception:
org.apache.http.client.HttpResponseException: Not Found
at com.offbytwo.jenkins.client.validator.HttpResponseValidator.validateResponse(HttpResponseValidator.java:11)
at com.offbytwo.jenkins.client.JenkinsHttpClient.get(JenkinsHttpClient.java:108)
at com.offbytwo.jenkins.client.JenkinsHttpClient.post(JenkinsHttpClient.java:165)
at com.offbytwo.jenkins.client.JenkinsHttpClient.post(JenkinsHttpClient.java:232)
at com.offbytwo.jenkins.JenkinsServer.deleteJob(JenkinsServer.java:239)
By now the only method affected by this post() method is deleteJob(), just because is the only which is using it, but if more method start to use it, also will been failing.
The most important thing that i see is the design issue in post() method, is not cohesive, making a GET call inside of the method in charge of making POST is not the best way, we need to decouple the crumbIssuer thing of the post() method, because is taking more responsibility than they should.
Thanks
Esteban
Would it be possible to release as 0.1.5 with the new APIs? I think I am done adding now but woudl like to consume them via maven in my continuous build. Thanks!
-Carl
Assuming MyJob builds a Maven multi-module project with 1 module foo.package:my-module.
The Jenkins plugin for Maven creates a subproject for each submodule, these are accessible over REST API like any other job, the job name looks like "MyJob/foo.package:my-module".
For that kind of job, the encode method is not required, calling jenkinsServer.getJob does even fail because of this encode method for that kind of job.
I'm using version 0.2.1.302.1 which is not showing here and I'm not able to get it from http://repo.jenkins-ci.org/public/com/offbytwo/jenkins/jenkins-client/
Until now I used my nexus to download this artifact, but now I'm planning to release my apps as OS so I can't leave any references to my nexus.
Can you return this release or this method?
I guess I can use the jenkins-client source code under the apache LA (2.0), but I rather avoid that if possible.
Hi,
I'm using this library. This is great. Thanks for the work done.
There are some details not yet implemented, so I'm working on it. But, I'd like to perform some of the integration tests. Unfortunately, for the moment, 4 of the tests are failing:
testUpdateJob
shouldReturnBuildStatusForBuild
shouldReturnBuildsForJob
testCreateJob
What is the Jenkins version you currently use for those Integration tests.
Also, I'm working on upgrading those integration tests to use:
maven-failsafe-plugin
jenkins-test-harness
so we won't need a Jenkins instance to perform Integration tests, also tests will be isolated and Unit tests and Integration test won't be mixed.
Also, using jenkins-test-harness will allow us to perform integration test against almost any Jenkins versions:
mvn clean verify -Djenkins-version=1.447.3
or
mvn clean verify -Djenkins-version=1.563
and so, we could create a "Built against" table to know if we can use the library.
Regards,
-- Adrien
JenkinsHttpClient client = new JenkinsHttpClient(new URI("xxx"), "admin", "token");
HashMap<String, String> params = new HashMap();
params.put("test", "test");
ObjectMapper mapper = new ObjectMapper();
DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
mapper.setDeserializationConfig(deserializationConfig.without(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES));
System.out.println(mapper.writeValueAsString(params));
client.post("build", params, null);
The above code throws below exception.
{"test":"test"}
Exception in thread "main" java.nio.charset.IllegalCharsetNameException: application/json
at java.nio.charset.Charset.checkName(Charset.java:284)
at java.nio.charset.Charset.lookup2(Charset.java:458)
at java.nio.charset.Charset.lookup(Charset.java:437)
at java.nio.charset.Charset.forName(Charset.java:502)
at org.apache.http.entity.ContentType.create(ContentType.java:180)
at org.apache.http.entity.StringEntity.(StringEntity.java:127)
at com.offbytwo.jenkins.client.JenkinsHttpClient.post(JenkinsHttpClient.java:136)
JobWithDetails buildJob = jenkinsServer.getJob(jobName);
buildJob.getLastBuild()
java.lang.NullPointerException
at com.offbytwo.jenkins.model.Build.(Build.java:19) [jenkins-client.jar:0.2.2-20141202]
at com.offbytwo.jenkins.model.JobWithDetails.buildWithClient(JobWithDetails.java:47) [jenkins-client.jar:0.2.2-20141202]
at com.offbytwo.jenkins.model.JobWithDetails.getLastBuild(JobWithDetails.java:53) [jenkins-client.jar:0.2.2-20141202]
The stop method throws exception (405) due to inconsistency at Jenkins.
Jenkins changed their API from post to get and from get to post and so on.
For example version 1.565 is supporting stop method as a post call, version 1.609.1 support it as a get call and version 1.609.2 support it as a post call.
We will create a fix for it shortly.
There is no method on JenkinsServer to getViews.
This should be easily retrievable from the API in $servername/api/<format>
edit:
As a note, the intended use case here is to be able to build a graph of the Pipeline view.
It will improve the code if we start using a logging framework here, cause just simple printStackTrace()
is in general not a good idea.
Oops - this is probably a fault in my latest patch. I will work on a solution soon, but for now the client can work around it by simply catching the exception and checking the response code to see if it is 302.
Example stacktrace:
[INFO] [talledLocalContainer] 2013-06-03 17:11:48,015 ERROR [AtlassianEvent::pool-3-thread-5] admin 1031x221x1 1b4iha6 127.0.0.1 "POST /scm/project_1/rep_1.git/git-receive-pack HTTP/1.1" c.p.s.s.managers.JenkinsManager HTTP Error (resp code 302
[INFO] [talledLocalContainer] org.apache.http.client.HttpResponseException: Found
[INFO] [talledLocalContainer] at com.offbytwo.jenkins.client.JenkinsHttpClient.post(JenkinsHttpClient.java:142) ~[stashbot-helper-1.0-SNAPSHOT_1370304253000.jar:na]
[INFO] [talledLocalContainer] at com.offbytwo.jenkins.model.Job.build(Job.java:58) ~[stashbot-helper-1.0-SNAPSHOT_1370304253000.jar:na]
[INFO] [talledLocalContainer] at <my code here>
Hey Cosmin,
For my usecase, I require an ancient, stupid version of guava. I've managed to make things work for me using the jarjar plugin to bundle jenkins-client's dependency on guava. Is this something I should just continue to do myself, or do you think it makes sense to do this in the main project?
I would completely understand it if this dependency tragedy is something you think should stay outside the library - but if other people also have this issue, it may help to bundle up our dependencies.
Thoughts?
It would be nice having information about installed plugins and their dependencies.
Right now , there is no api to get testng reports from a maven build(The available mvnJob.getLastSuccessfulBuild().getTestReport() doesn't get tesng reports). There should be one to get this information , the URI looks like JENKINS_BASE_URI/testngreports/api/json.
Also to add jacoco report api
The README says how to use the library from maven, but I can't find it in any maven repos. Can you please publish a jar to maven?
Thanks!
-Carl
When invoking job.build Jenkins will not return the BuildNumber, instead the Location Header is set to a build queue item (https://issues.jenkins-ci.org/browse/JENKINS-12827) because triggering a build does actually only queue that job.
Therefore the job build* methods should return that queue item reference so a caller can then use the queue api to detect if a build had actually be started.
Getting following exception while invoking the same jenkins method couple of times:
"Invalid use of BasicClientConnManager: connection still allocated.
Make sure to release the connection before allocating another one."
Hey all,
I need to be able to create credentials in jenkins programmatically. Based upon some research, the standard way to do this seems to be a heredoc full of groovy extreme sadface
See line 105: https://github.com/opscode-cookbooks/jenkins/blob/master/libraries/credentials.rb
On the bright side, implementing "run me some random groovy" endpoint would probably give us control to do whatever we wanted to in jenkins. We'd still want typesafe APIs wherever possible, but where not, groovy!
Thoughts? Any advice if I try to implement this?
Hey guys,
Just a heads-up, I am working on folder support. Here is a snapshot of what I have so far:
213bb62
If you have any advice/feedback about how you'd like it done, feel free to chime in, but don't feel like you need to waste any time on it necessarily until I'm done. I've examined the code pretty carefully and I think I am making decisions similar to the structure of other things fairly consistently, so hopefully it will be an easy PR to take.
My basic approach so far is adding a FolderJob object, and JenkinsServer.getFolder(Job someJob) which returns a FolderJob object (regardless of job type), on which you can call isFolder() to see if it is a valid folder. Then, on the FolderJob, you can call getJobs() to get the jobs under it.
I'll also add JenkinsServer.createFolder() and FolderJob.createFolder(), which will probably throw an error if you don't have the cloudbees plugin installed.
The linked history also includes some bugfixes and refactorings.
In my Java App i do the following:
jenkins.createJob("my-new-job", config.toString());
(where "config.toString() is the XML config.)
My App works perfectly with 0.2.0 version.
An exception is thrown with following stack trace:
org.apache.http.client.HttpResponseException: Not Found
at com.offbytwo.jenkins.client.validator.HttpResponseValidator.validateResponse(HttpResponseValidator.java:11)
at com.offbytwo.jenkins.client.JenkinsHttpClient.get(JenkinsHttpClient.java:108)
at com.offbytwo.jenkins.client.JenkinsHttpClient.post_xml(JenkinsHttpClient.java:206)
at com.offbytwo.jenkins.client.JenkinsHttpClient.post_xml(JenkinsHttpClient.java:200)
at com.offbytwo.jenkins.JenkinsServer.createJob(JenkinsServer.java:167)
at jenkins.automation.SettingsHelperTest.testRubickConfig(SettingsHelperTest.java:136)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Hey.
I got the runtime exception with could not generate dh keypair.
Our jenkins is running with an self signed ssl certificate.
With simply initializing JenkinsServer with the Jenkins URL and doing any request such getJobs the plugin throws that exception.
I'm using 0.3.1-SNAPSHOT which was compiled from latest master of this repository.
Any ideas?
javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1904)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1862)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1845)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1366)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:535)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:403)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
at org.apache.http.impl.conn.ManagedClientConnectionImpl.open(ManagedClientConnectionImpl.java:304)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
at com.offbytwo.jenkins.client.JenkinsHttpClient.get(JenkinsHttpClient.java:123)
at com.offbytwo.jenkins.JenkinsServer.getJob(JenkinsServer.java:133)
at de.test.stash.RefBuildProvider.getMetadata(RefBuildProvider.java:50)
at com.atlassian.stash.internal.repository.PluginRefMetadataMapProvider$2.call(PluginRefMetadataMapProvider.java:109)
at com.atlassian.stash.internal.repository.PluginRefMetadataMapProvider$2.call(PluginRefMetadataMapProvider.java:105)
at com.atlassian.stash.internal.concurrent.StateTransferringExecutorService$StateTransferringCallable.call(StateTransferringExecutorService.java:147)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at sun.security.ssl.DHCrypt.<init>(DHCrypt.java:136)
at sun.security.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:688)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:261)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:913)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:849)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1023)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
... 24 more
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DHKeyPairGenerator.java:120)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:675)
at sun.security.ssl.DHCrypt.<init>(DHCrypt.java:127)
... 31 more
Hi,
Can add a new parameter depth=X in requests.
Now I cant retrieve the Executors:
/jenkins/computer/(master)/api/json?pretty=true
/jenkins/computer/(master)/api/json?pretty=true&depth=2 (more information)
When posting Jenkins configuration (when updating or creating jobs for example), the POST request need to have "crumb" header.
Those headers can be generated by requesting "crumbIssuer/api/json" and adding crumbRequestField
value with crumb
value to the header.
Upon investigation, it seems that the jackson-mapper-asl is not compatible with spring 3.2. You would need to use fastxml jackson pom dependencies. Please see the url below for the changes http://wiki.fasterxml.com/JacksonUpgradeFrom19To20
Stacktrace:
java.lang.NoSuchMethodError: org.codehaus.jackson.map.DeserializationConfig.without([Lorg/codehaus/jackson/map/DeserializationConfig$Feature;)Lorg/codehaus/jackson/map/DeserializationConfig;
at com.offbytwo.jenkins.client.JenkinsHttpClient.getDefaultMapper(JenkinsHttpClient.java:232)
at com.offbytwo.jenkins.client.JenkinsHttpClient.(JenkinsHttpClient.java:53)
at com.offbytwo.jenkins.client.JenkinsHttpClient.(JenkinsHttpClient.java:65)
at com.offbytwo.jenkins.JenkinsServer.(JenkinsServer.java:46)
Is it possible to get this fixed ASAP?
Update dependency to 4.3.6
Sorry to post here, if there is a forum to discuss it, I am happy to move this topic to :-)
The lase release: 0.3.0 has been released half a year, do you have any plan when to release 0.3.1? Thank you very much! :-)
public String Stop() throws HttpResponseException, IOException{
try {
return client.get(url + "stop");
}
catch (IOException ex){
if(((HttpResponseException)ex).getStatusCode() == 405)
{
stopPost();
return "";
}
}
return "";
}
java.lang.ClassCastException: org.apache.http.client.ClientProtocolException cannot be cast to org.apache.http.client.HttpResponseException
When a job is being built and you get the Build details of it the value is null. It should be the enum value BUILD.BUILDING.
The basic instance created by the client is susceptible to the following exception when used in a concurrent environment such as a web server:
java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated.
This is solved by passing a more advanced client connection manager such as PoolingClientConnectionManager to the DefaultHttpClient when it is constructed. Since there are lots of ways to configure this connection manager and other HTTP settings such as timeouts, it is recommended to allow an advanced user of jenkins-client to pass their own instance of DefaultHttpClient when constructing.
Do you have any ETA?
Request for causes method to be added to BuildWithDetails, including the information from 'causes' in the api
"causes" : [
{
"shortDescription" : "Started by upstream project <foo> build number X",
"upstreamBuild" : X,
"upstreamProject" : "<foo>",
"upstreamUrl" : "job/foo/"
}
]
Hi,
I have created REST service to fetch the job details from Jenkins server.It works fine with already build in jobs.(FAILURE,SUCCESS,ABORTED those status are working fine).I have executed job in Jenkins server and trying to get currently running job status but when i call created rest service it throws an Null point exception when getting jobDetails.getResult().Please refer following link to see my sample code.
http://stackoverflow.com/questions/33686892/how-to-get-jenkins-list-of-job-details-using-jenkins-client-in-java
Please let me know that how can i get job details including current execution jobs status as well.
Thanks.
Hi,
i just want to know if you plan to create a new release and distribute it to maven central?
Do you like to continue development ? Cause i'm interested in continuing...
Kind regards
Karl HEinz Marbaise
Currently the loadStatistics is not loaded.
post() and post_xml() method in JenkinsHttpClient.java has a bug where we always get IOException when CrumbIssuer is not set up in a Jenkins server.
Specifically, the following code always throws IOException before doing POST.
Crumb crumb = get("/crumbIssuer", Crumb.class);
#26 resolved the Crumb issue for users who set up CrumbIssuer, but it is not always the case.
To support the other users who have not used the CrumbIssuer, we should modify this.
The JenkinsHttpClient implementation does not consume the response entity in all cases.
cause:
In "JenkinsHttpClient::public T get(String path, Class cls)" the method is exited with an exception.
solution:
allways consume the entity / make try finally around complete method eg :
try {
response = client.execute(new HttpGet(api(path)), localContext);
int status = response.getStatusLine().getStatusCode();
if (status < 200 || status >= 300) {
throw new HttpResponseException(status, response.getStatusLine().getReasonPhrase());
}
return objectFromResponse(cls, response);
} finally {
if(response!=null){
EntityUtils.consume(response.getEntity());
}
}
@khmarbaise
Test below code:
String jobName = "Test";
String xml = jenkins.getJobXml(jobName);
JobConfiguration jobConf = new JobConfiguration(xml);
jobConf.addStringParam("tt", "Test parameter", "1");
I found it failed with below exception:
java.lang.NoClassDefFoundError: org/jaxen/NamespaceContext
at org.dom4j.DocumentFactory.createXPath(DocumentFactory.java:230)
at org.dom4j.tree.AbstractNode.createXPath(AbstractNode.java:207)
at org.dom4j.tree.AbstractNode.selectNodes(AbstractNode.java:164)
...
... 29 more
I found the cause is that no jaxen dependency in pom.xml.
I guess you guys did not meet it because jenkins-test-harness has an indirect dependency to jaxen. But jenkins-test-harness only be depended in test scope.
The header must contain a ".crumb" in the header. When that's missing, the server returns Error 403. I changed the code in JenkinsHttpClient.java, post_xml() like this:
String crumb = get("crumbIssuer/api/json").replace("{"crumb":"", "").replace("","crumbRequestField":".crumb"}", "");
HttpPost request = new HttpPost(api(path));
if (xml_data != null) {
request.addHeader(".crumb", crumb);
request.setEntity(new StringEntity(xml_data, ContentType.APPLICATION_XML));
}
There may be a better way doing this, but it works :)
Move the execution of maven-failsafe-plugin into a profile which makes releasing simpler.
I can't call build.details() if the build status is NOT_BUILT:
Causing: org.quartz.JobExecutionException: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.offbytwo.jenkins.model.BuildResult from String value 'NOT_BUILT': value not one of declared Enum instance names
! at [Source: org.apache.http.conn.EofSensorInputStream@27205751; line: 1, column: 3427] (through reference chain: com.offbytwo.jenkins.model.BuildWithDetails["result"])
Hi,
I'd like to use your library in order to delete jobs in Jenkins but this is not included in the last release (0.2.0).
When do you plan to get a new release?
Thanks!
Angela.
Jenkins does have at /queue an api for the build queue, this is currently missing.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.