contraband / autopilot Goto Github PK
View Code? Open in Web Editor NEWcf plugin for hands-off, zero downtime application deploys
License: Apache License 2.0
cf plugin for hands-off, zero downtime application deploys
License: Apache License 2.0
Hello,
I'm having some trouble installing the plugin
matt@Matt-BZC001 ~/Downloads> cf install-plugin autopilot-darwin
Attention: Plugins are binaries written by potentially untrusted authors. Install and use plugins at your own risk.
Do you want to install the plugin autopilot-darwin? (y or n)> y
Installing plugin ./autopilot-darwin...
FAILED
fork/exec ./autopilot-darwin: permission denied
This was fixed by running: chmod +x autopilot-darwin
Attempting to use the new vars-file flag to interpolate cf manifest files with a command similar to the following:
cf zero-downtime-push app-name -f app-manifest.yml -p app.jar -vars-file app-manifest-vars.yml
I made a similar report back to the cf-resource which leverages the autopilot plugin: cloudfoundry-community/cf-resource#56 (comment)
No one has responded so I am not completely sure if its something that I am doing or something with the plugin. Wasn't really sure how to turn on additional debugging to tease out more details.
In a similar vein to #12 - the renamed (venerable) app is not being deleted for me. The initial deploy does not appear to be successful, but instead simply hangs without an error. Below is what I see in the console, hanging at the last line with no resolution.
$ cf zero-downtime-push "MyApp" -f ./manifest.yml
Renaming app MyApp to MyApp-venerable in org MyOrg / space MySpace as MyEmailAddress...
OK
Using manifest file ./manifest.yml
Creating app MyApp in org MyOrg / space MySpace as MyEmailAddress...
OK
Using route MyApp.mybluemix.net
Binding MyApp.mybluemix.net to MyApp...
OK
Uploading MyApp...
Uploading app files from: /MyProjectPath
Uploading 40.2K, 23 files
Done uploading
OK
Starting app MyApp in org MyOrg / space MySpace as MyEmailAddress...
Downloading swift_buildpack_v2_0_2-20161118-1326...
Downloading go_buildpack...
Downloading binary_buildpack...
Downloading python_buildpack...
Downloading liberty-for-java_v3_5-20161114-1152...
Downloaded binary_buildpack
Downloading sdk-for-nodejs_v3_8-20161006-1211...
Downloaded python_buildpack
Downloaded go_buildpack
Downloaded swift_buildpack_v2_0_2-20161118-1326
Downloading java_buildpack...
Downloaded liberty-for-java_v3_5-20161114-1152
Downloading liberty-for-java...
Downloaded liberty-for-java_v3_4_1-20161030-2241
Downloading sdk-for-nodejs...
Downloaded dotnet-core_v1_0_1-20161005-1225
Downloaded java_buildpack
Downloading swift_buildpack...
Downloaded sdk-for-nodejs_v3_8-20161006-1211
Downloading noop-buildpack...
Downloaded liberty-for-java
Downloading php_buildpack...
Downloaded sdk-for-nodejs
Downloading xpages_buildpack...
Downloaded dotnet-core
Downloading ruby_buildpack...
Downloaded swift_buildpack
Downloading staticfile_buildpack...
Downloaded php_buildpack
Downloading xpages_buildpack_v1_2_1-20160913-103...
Downloaded noop-buildpack
Downloading nodejs_buildpack...
Downloaded xpages_buildpack
Downloaded ruby_buildpack
Downloaded nodejs_buildpack
Downloaded xpages_buildpack_v1_2_1-20160913-103
Downloaded staticfile_buildpack
Creating container
Downloading liberty-for-java_v3_4_1-20161030-2241...
Successfully created container
Downloading app package...
Downloaded app package (26.7K)
Staging...
-----> IBM SDK for Node.js Buildpack v3.9-20161128-1327
Based on Cloud Foundry Node.js Buildpack v1.5.20
-----> Creating runtime environment
NPM_CONFIG_PRODUCTION=true
NODE_ENV=production
NODE_MODULES_CACHE=true
-----> Installing binaries
engines.node (package.json): 6.2.1
engines.npm (package.json): 3.9.3
Downloading and installing node 6.2.1...
npm 3.9.3 already installed with node
Skipping cache restore (new runtime signature)
-----> Building dependencies
Installing node modules (package.json)
> [email protected] install /tmp/app/node_modules/dtrace-provider
> node scripts/install.js
> [email protected] install /tmp/app/node_modules/bunyan/node_modules/dtrace-provider
> node scripts/install.js
├─┬ [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ ├─┬ [email protected]
│ │ │ │ │ └── [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ │ │ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├─┬ [email protected]
│ │ │ │ │ └─┬ [email protected]
│ │ │ │ │ ├── [email protected]
│ │ │ │ │ ├── [email protected]
│ │ │ │ │ ├── [email protected]
│ │ │ │ │ └── [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├─┬ [email protected]
│ │ │ │ │ └── [email protected]
│ │ │ │ └── [email protected]
│ │ │ ├─┬ [email protected]
│ │ │ │ ├── [email protected]
│ │ │ │ └── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ ├─┬ [email protected]
│ │ │ └── [email protected]
│ │ └─┬ [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ └─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ └── [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ │ └── [email protected]
│ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
├─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├─┬ [email protected]
│ │ │ ├── [email protected]
│ │ │ └─┬ [email protected]
│ │ │ └── [email protected]
│ │ └── [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ ├─┬ [email protected]
│ │ ├── [email protected]
│ │ └── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
├── [email protected]
└── [email protected]
-----> Installing App Management
WARN: App Management cannot be installed because the start script cannot be found.
To install App Management utilities, specify your 'node' start script in 'package.json' or 'Procfile'.
-----> Caching build
Clearing previous node cache
Saving 2 cacheDirectories (default):
- node_modules
│ ├── [email protected]
│ ├─┬ [email protected]
│ │ └── [email protected]
│ ├── [email protected]
- bower_components (nothing to cache)
-----> Build succeeded!
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]
Exit status 0
Staging complete
Uploading droplet, build artifacts cache...
Uploading build artifacts cache...
Uploading droplet...
Uploaded build artifacts cache (4.6M)
Uploaded droplet (17.2M)
Uploading complete
Destroying container
Successfully destroyed container
At this point both apps, new and venerable, still visible in my Bluemix console. Not sure on how to debug further. Suggestions?
Hi,
I have noticed that if you have multiple routes mapped to your app that only the primary route gets re-mapped. This could lead to downtime for anyone accessing the app on any routes other than the primary route. This is a particular issue if you have a secondary route to your app mapped as "www".
There is also an orphaned route left after running cf zero-downtime-push.
Regards,
S
Autopilot seems to assume that your app already exists. If you try to run it with an app that does not already exist, the following error occurs:
$ cf zero-downtime-push new-app -f manifest.yml -p .
FAILED
App new-app not found
error: Error executing cli core command
Unsure if this is actually intended behavior (considering not having the app exist might be considered a fringe case) or a bug.
Autopilot renames application-to-replace
but pushes all applications in the specified manifest. So if my manifest includes app-a
and app-b
, running cf zero-downtime-deploy app-a -f manifest.yml
will deploy app-a
without downtime, but app-b
with downtime. Users can work around this by keeping each application in its own manifest, but it should be simple enough to support this use case in autopilot by passing the application name to cf push
.
I'd love to use this plugin with Travis, but I can't seem to get Travis to reliably install the plugin and use it through their deploy process. Do you have instructions for using it with Travis?
Thanks!
It's helpful tor tracking whether I have the latest version of the plugin or not.
First off, I love this plugin and have been using it for some time. Thank you for all the awesomeness thus far. Just had a small question: The final step in autopilot is to list all applications, is there a reason for this feature? Could we possibly make that an option, based on some flag in the arguments? It seems to make the logs a bit cumbersome if you have a lot of applications. I would be happy to take a stab at this if you are open to the idea. Thanks!
It would be great if ENV vars could be copied from one generation of the app to the next upon deploy. As is we have to use user provided services to hold our env vars, which isn't very nice for environments that aren't on cloud foundry (e.g. development). Hopefully this could be as simple as just fetching the ENV vars and iterating through them.
cc: @mikfreedman
With a customer using the plugin, and when CF_TRACE
was set to true
after the 200 OK from the initial push, there was an "unexpected end of JSON" error. Was only fleeting and I'm supposed to be pairing with the chap now, so will investigate more later if I get time.
$ cf zero-downtime-push -f manifest-staging.yml
error: a manifest is required to push this application
Ideally, autopilot should check the manifest to see if the app name is specified there, just as cf push
does.
At the very least, the error should be fixed to explain the real problem.
If you run cf zero-downtime-push appname
without passing in a manifest.yml, it first renames the old app to training-venerable, and then checks to see that you forgot to pass in a manifest and dies. At that point, re-running the same command but with -f manifest.yml
appended doesn't work, and confusion reigns.
Thank you!
Hi,
I was trying to deploy app to Cloud Foundry using Buildpack URI
cf push -f manifest.yml -b https://github.com/cloudfoundry/java-buildpack.git
Then i tried to achieve similar result using autopilot plugin. But it seems there is no way to give options used by cf push.
Is this something you will consider in the future? or it is not possible to achieve via this plugin?
Please see the attached issue: cloudfoundry-community/cf-resource#28
I think this may be possibly addressed in autopilot, although I think it may be asking the tool to do too much and it should instead be left to an upstream task. But then again, autopilot is already effectively just an orchestrator for other primitive CF commands. Thoughts?
Can be nice is this plugin can support scaling over time.
Let's say zero-dowtime with application with 100 instances.
Can be nice if we can merge this plugin with the scaleover one.
missing usage
$ cf h zero-downtime-push
NAME:
zero-downtime-push - Perform a zero-downtime push of an application over the top of an old one
USAGE:
$
It might be nice to mention that go is a dependency of this lib. It took me a few minutes to realize that. :)
Getting the below error when trying to cf install autopilot on a tfs agent.
Plugin autopilot N/A is already installed. Uninstalling existing plugin...
accept tcp 127.0.0.1:55925: use of closed network connection
panic: runtime error: slice bounds out of range
goroutine 1 [running]:
main.AutopilotPlugin.parseArgs(0xc0820263e0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/Users/cb/workspace/go/src/github.com/concourse/autopilot/autopilot.go:65 +0x2c7
main.AutopilotPlugin.Run(0x193620, 0xc082004f30, 0xc0820263e0, 0x1, 0x1)
/Users/cb/workspace/go/src/github.com/concourse/autopilot/autopilot.go:27 +0xd2
main.(*AutopilotPlugin).Run(0x9730c8, 0x193620, 0xc082004f30, 0xc0820263e0, 0x1, 0x1)
:1 +0xd0
github.com/cloudfoundry/cli/plugin.Start(0x192500, 0x9730c8)
/Users/cb/workspace/go/src/github.com/cloudfoundry/cli/plugin/plugin_shim.go:18 +0x251
main.main()
/Users/cb/workspace/go/src/github.com/concourse/autopilot/autopilot.go:20 +0x66
exit status 2
[31;1mFAILED
The version on the CF-Community(https://plugins.cloudfoundry.org/) is two versions behind the latest release (0.0.1 vs. 0.0.3). Is that due to that?
We were playing around with this plugin and noticed that for our apps with multiple routes only one route is preserved when we re-push our app with cf zero-downtime-push
. Could you please add the ability to handle multiple routes? Thanks!
autopilot should delete the renamed app after successful completion of the hot deployment.
I see this when I cf zero-downtime-push uas -f manifest.yml`
FAILED
Server error, status code: 400, error code: 100002, message: The app name is taken: uas-venerable
error: Error executing cli core command
Happens because autopilot still keeps the old renamed app. Is there a flag to force it not to keep the renamed app?
I think it would be useful to have the option to just stop the venerable application instead of deleting it.
My rationale is that after the new version of the application is deployed it would be good to have the option to switch back to the old version for a while just in case something goes wrong may it be related to test cases, credentials, external services or something else.
What do you think?
Best Regards
Michael
Hey! Pleased to have come across this project. I had written something similar, which I had been planning to port over to a CLI plugin.
Wanted to raise an idea: while I totally understand the reasoning for (and simplicity of) requiring the user to have a complete manifest to deploy with, my guess is that in reality, there are lots of applications that don't (mine included). For cf-blue-green
, I was starting to play around with having the local manifest merged with the remote one (basically local -> inherit: -> remote
); in other words, any local manifest changes will be included in the new deploy, but any configuration not reflected in the manifest would be included as well.
Not sure how well I explained it... Thoughts? Also, sorry if there's a better forum for feature ideas.
Because a few items in our manifest file are deprecated, we switched over to the new format. However, when trying to use the new manifests we get an error stating that the new fields cannot be used with 'legacy push'.
Are there any plans to update autopilot to work with the latest cf-cli and the new manifests?
Feature Request:
It would be nice to have a short plugin name(alias) like "cf zdp".
with the normal cf push I also pass the --health-check-type none
parameter on my worker applications that contain no routes. This option does not seem to exist in autopilot yet. The result is that any pushed applications will fail to start due to failing the default health check
Hi,
I ran into an odd situation today, where app-name
was deleted not app-name-venerable
anyone else seen this?
Creating an app manifest from current settings of app tariff-frontend-dev in org trade-tariff / space development as ..
OK
Manifest file created successfully at ./tariff-frontend-dev_manifest.yml
Renaming app tariff-frontend-dev to tariff-frontend-dev-venerable in org trade-tariff / space development as ...
OK
Using manifest file tariff-frontend-dev_manifest.yml
Using stack cflinuxfs2...
OK
Creating app tariff-frontend-dev in org trade-tariff / space development as ...
OK
Using route tariff-frontend-dev...
Binding tariff-frontend-dev... to tariff-frontend-dev...
Deleting app tariff-frontend-dev in org trade-tariff / space development as ...
OK
error: Oh no. Something's gone wrong. I've tried to roll back but you should check to see if everything is OK.: App tariff-frontend-dev-venerable not found
Exited with code 1
Can we get a new version published? It's been almost a year since 0.0.2 was released, and there are a few updates merged in since then that would help my team.
Thanks and great work on this!
Feature Request:
If no manifest option is set (-f path/to/manifest) automatically use the manifest.yml in the current directory.
This feature is also pre built-in to the general cf cli.
When a deploy dies, the venerable app persists in CF. When you deploy again, the deploy fails with this error:
+ cf zero-downtime-push APPNAME -f manifest.yml -p $WORKSPACE
Renaming app APPNAME to APPNAME-venerable in org ORG / space acceptance as ********...
FAILED
Server error, status code: 400, error code: 100002, message: The app name is taken: APPNAME-venerable
In this scenario, we go into CF and delete the venerable instance manually. Maybe the plugin could do this for us (this wouldn't be a zero downtime deploy but neither is our current solution). Alternately, the app could push to the non-venerable instance, change the route, and then delete the venerable instance.
If I fail to specify the -f
or -p
options, the plugin plugin starts by renaming the app, but then erring that it requires the manifest and path:
$ cf zero-downtime-push mcowger-python
Renaming app mcowger-python to mcowger-python-venerable in org EMC Dev Ops Class / space development as [email protected]...
OK
error: a manifest is required to push this application
The plugin should check for the required command line options before beginning and renaming apps.
After looking into this issue, it appears that the plugin is actually not complied statically!
$ ldd autopilot-linux
linux-vdso.so.1 => (0x00007ffdb6394000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f8b0a778000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8b0a398000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8b0a997000)
So it fails during the cf install-plugin step in your docker file because alpine Linux does not have those libraries. The CF CLI tries to run the plugin it's installing during the install-plugin phase to get metadata about said plugin and a segfault occurs, thus causing the error you see in front of you.
There are two solutions:
Compile the autopilot plugin yourself with the following build command:
$ CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -a -tags netgo -installsuffix netgo -ldflags "-w -s -extldflags "-static"" -o autopilot-linux
submit an issue against autopilot
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.