kusionstack / kusion Goto Github PK
View Code? Open in Web Editor NEWDeclarative Intent Driven Platform Orchestrator for Internal Developer Platform (IDP).
Home Page: https://kusionstack.io
License: Apache License 2.0
Declarative Intent Driven Platform Orchestrator for Internal Developer Platform (IDP).
Home Page: https://kusionstack.io
License: Apache License 2.0
Please answer these questions before submitting your issue. Thanks!
apply
, Kusion will recognize this resoruce as Unchanged
and will Skip
this resource.Resource A is saved in kusion_state.json file
Resource A isn't saved in kusion_state.json file
v0.5.0
Let me introduces 2 scenes here:
Since Konfig is a public repository, it is obviously inappropriate to store the sensitive information in the above scenarios in a large repository. Therefore, this issue explores solutions for maintaining sensitive information in a large repository.
Comb dependency in go.mod replaces some large dependencies, such as:
github.com/pulumi/pulumi/sdk/v3 v3.24.0
Only some util funcs of pulumi/sdk
are used in the kusion, so there is no need to import the whole package.
Please answer these questions before submitting your issue. Thanks!
按教程,kusionup
kusion init --online
进入code-city/dev
执行:kusion apply
no error
✘ Compiling in stack dev...
❌ KCL Compile Error[E2F04] : Cannot find the module
Cannot find the kcl file, please check whether the file path /base/pkg/kusion_models/kube/metadata/metadata.k
releaseVersion: v0.6.1-rc.0
gitInfo:
latestTag: v0.6.1-rc.0
commit: e496ce1
treeState: clean
buildInfo:
goVersion: go1.17.13
GOOS: linux
GOARCH: amd64
numCPU: 2
compiler: gc
buildTime: "2022-09-07 06:30:06"
dependency:
kclvmgoVersion: v0.4.3-alpha.4
kclPluginVersion: v0.4.1-alpha2
Please answer these questions before submitting your issue. Thanks!
Apply resources to some cluster of DryRun feature-gate is off.
According to k8s doc, feature gate DryRun
has been GA since v1.19.
Apply success!
dry run not support
releaseVersion: v0.4.3
gitInfo:
latestTag: v0.4.3
commit: 874a13dd38516908d7db6cbd309c31f3f40368ab
treeState: clean
buildInfo:
goVersion: go1.17.11
GOOS: linux
GOARCH: amd64
numCPU: 2
compiler: gc
buildTime: "2022-06-09 12:44:43"
dependency:
kclvmgoVersion: v0.4.2-alpha4
kclPluginVersion: v0.4.1-alpha2
Only UTs can't guarantee the whole working flow is ready to use. We need an end to end test framework to test our codes like a real user.
The initial requirement of kusion watch
comes from the fact that after the user successfully creates, modifies or deletes the resource using the kusion apply
, which can monitor the real-time update of the resource, so as to ensure that Spec and Live are ultimately consistent on the Runtime side. Therefore, the operation object of the Watch subcommand is not a single resource, but a single Stack under a certain Project.
Kusion has been connected to Kubernetes and Terraform. For k8s resources, client-go provides Watch interface, resource changes that can be obtained in real time; and for the Terraform ecosystem, there is no so-called Live Manifest, and the Terraform side just saves The resource list after the operation is successfully executed, which is equivalent to a cache.
As an alpha feature, the primary purpose is to define the watch workflow. So TF runtime is not include in this time. And there are a few preconditions:
The complete workflow can be simplified as 4 stages:
sequenceDiagram
autonumber
actor User
participant KusionCLI
participant KCLVM
participant IaC Engine
participant Runtime
User ->> KusionCLI: kusion apply --watch
KusionCLI->>KCLVM: compile
activate KCLVM
KCLVM-->>KusionCLI: kcl resoults
deactivate KCLVM
KusionCLI ->> IaC Engine: watch resources
activate IaC Engine
loop Every Resource
IaC Engine ->> Runtime: watch one
activate Runtime
Runtime -->> IaC Engine: event
deactivate Runtime
IaC Engine ->> IaC Engine: render table row
end
IaC Engine -->> KusionCLI: render table
deactivate IaC Engine
KusionCLI --> User: flush table
For k8s, the --w
flag in the kubectl get command provides the implementation of related capabilities. The Watch behavior of k8s for resources is unterminated, and the object of Watch can only be one resource or one certain type of resource. And formatted output for each resource, defined here pkg/printers/internalversion/printers.go
. The key implementation of kubectl get -w
is as follows:
// staging/src/k8s.io/kubectl/pkg/cmd/get/get.go:636
func (o *GetOptions) watch(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
// ...
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
intr := interrupt.New(nil, cancel)
intr.Run(func() error {
_, err := watchtools.UntilWithoutRetry(ctx, w, func(e watch.Event) (bool, error) {
objToPrint := e.Object
if o.OutputWatchEvents {
objToPrint = &metav1.WatchEvent{Type: string(e.Type), Object: runtime.RawExtension{Object: objToPrint}}
}
if err := printer.PrintObj(objToPrint, writer); err != nil {
return false, err
}
writer.Flush()
// after processing at least one event, start outputting objects
*outputObjects = true
return false, nil
})
return err
})
// ....
}
The objToPrint
variable in the above code listing is the result of conversion from the API Server according to the specified format, not the YAML output according to the definition of the resource type. k8s defines parsing strategies for different resource types; the following is the table output format of the selected Pod:
// pkg/printers/internalversion/printers.go:87
func AddHandlers(h printers.PrintHandler) {
podColumnDefinitions := []metav1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
{Name: "Ready", Type: "string", Description: "The aggregate readiness state of this pod for accepting traffic."},
{Name: "Status", Type: "string", Description: "The aggregate status of the containers in this pod."},
{Name: "Restarts", Type: "string", Description: "The number of times the containers in this pod have been restarted and when the last container in this pod has restarted."},
{Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
{Name: "IP", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["podIP"]},
{Name: "Node", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["nodeName"]},
{Name: "Nominated Node", Type: "string", Priority: 1, Description: apiv1.PodStatus{}.SwaggerDoc()["nominatedNodeName"]},
{Name: "Readiness Gates", Type: "string", Priority: 1, Description: apiv1.PodSpec{}.SwaggerDoc()["readinessGates"]},
}
h.TableHandler(podColumnDefinitions, printPodList)
h.TableHandler(podColumnDefinitions, printPod)
// ...
}
k8s officially provides 46 resources parsing strategies.
kubespy is a tool developed by pulumi two years ago to monitor Kubernetes resources in real time. The trace
command currently only supports the monitoring of two resources, Deployment and Service. The whole business process is roughly divided into the following 3 steps:
func traceDeployment(namespace, name string) {
//...
for {
select {
case e := <-deploymentEvents:
if e.Type == k8sWatch.Deleted {
o := e.Object.(*unstructured.Unstructured)
delete(o.Object, "spec")
delete(o.Object, "status")
}
table[deployment] = []k8sWatch.Event{e}
case e := <-replicaSetEvents:
o := e.Object.(*unstructured.Unstructured)
if e.Type == k8sWatch.Deleted {
delete(repSets, o.GetName())
} else {
repSets[o.GetName()] = e
}
table[v1ReplicaSet] = []k8sWatch.Event{}
for _, rsEvent := range repSets {
table[v1ReplicaSet] = append(table[v1ReplicaSet], rsEvent)
}
case e := <-podEvents:
o := e.Object.(*unstructured.Unstructured)
if e.Type == k8sWatch.Deleted {
delete(pods, o.GetName())
} else {
pods[o.GetName()] = e
}
table[v1Pod] = []k8sWatch.Event{}
for _, podEvent := range pods {
table[v1Pod] = append(table[v1Pod], podEvent)
}
}
print.DeploymentWatchTable(writer, table)
}
}
DeploymentWatchTable()
uses the uilive framework, which can dynamically refresh the table instead of incrementally; the formatted output of the subsequent kusion watch can be referred it.
support KCL source code dependency analysis, for example, list affected stacks/projects by changed file paths and list all the file paths that some specific files depends on.
This feature can then be used to filter KCL test cases and accelerate the local build/test and CI test.
we need version upgrade tips for user , for example, when run kusion version
cmd
kusion version
warning: A new version of Kusion is available. To upgrade from version 'a.b.c' to 'x.y.z', run
$ kusionup reinstall [email protected]
or visit https://github.com/KusionStack/kusion/releases/ for manual instructions and release notes.
...
Please answer these questions before submitting your issue. Thanks!
make build-local-darwin-all
go version -m _build/bundles/kusion-darwin/kclvm/bin/kcl-go
...
dep kusionstack.io/kclvm-go v0.4.2-alpha4
...
...
path gitlab.alipay-inc.com/ant-cas/KCLVM/kclvm-go/cmds/kcl-go
mod gitlab.alipay-inc.com/ant-cas/KCLVM (devel)
...
I executed kusion apply
twice continuously without making any changes, but the preview results show that the deployment has changed:
The preview logic, use ClientSideDryRun
to preview what the apply action will do. Because the manifest doesn't contains these 3 fields from the picture above, but the deployment controller will write the default value, so there is no changes actually.
If we want to hide these changes, we must set:
// When present, indicates that modifications should not be
// persisted. An invalid or unrecognized dryRun directive will
// result in an error response and no further processing of the
// request. Valid values are:
// - All: all dry run stages will be processed
// +optional
DryRun []string `json:"dryRun,omitempty" protobuf:"bytes,1,rep,name=dryRun"`
and this feature is ServerSideApply
, more details: https://kubernetes.io/docs/reference/using-api/server-side-apply/
it's GA from kubernetes v1.22.
kusion init
is a helpful tool to create a new project of KCL. Consider that we have two different roles, one is template developer, who is responsible for design and develop template, as well as a set of default values; another is to use template. For quick start of template rendering, developer provides a YAML file, named kusion.yaml, which contains type and default value of all params that is used by go template engine.
However, if I want to override template default value, there is only one solution: type new default when each Prompt asks, which is strongly Inefficient.
Add a new flag(CustomParams) to override template defaults. Kusion must to provide a struct with filed name and type. User can prepare a new set of defaults in advance, based on file kusion.yaml.
Although we encourage all to use primitive type for template params:
But we must admit there is always an exception, aka complicated data type, For example:
and mixed complicated with primitives. So we need to explain every field type in kusion.yaml.
kusion.yaml provide a struct as below:
projectName: my-app
description: A minimal kusion project of single stack
quickstart: kusion compile main.k -Y ci-test/settings.yaml
common:
# base/base.k
- name: ServiceName
description: service name
type: string
default: frontend-svc
- name: NodePort
description: node port
type: int
default: 30000
# project.yaml
- name: ProjectName
description: project name
type: string
default: my-app
stacks:
- name: dev
fields:
# stack/ci-test/settings.yaml
- name: Stack
description: stack env. One of dev,test,stable,pre,sim,gray,prod.
type: string
default: dev
# stack/main.k
- name: Image
description: The Image Address. Default to 'gcr.io/google-samples/gb-frontend:v4'
type: string
default: gcr.io/google-samples/gb-frontend:v4
# stack/stack.yaml
- name: ClusterName
description: The Cluster Name. Default to 'kubernetes-dev'
type: string
default: kubernetes-dev
Implicit struct of CustomParams flag:
{
"projectConfig": {
"ServiceName": "frontend-svc",
"NodePort": 30000,
"ProjectName": "my-app"
},
"stacksConfig": {
"dev": {
"Stack": "dev",
"Image": "gcr.io/google-samples/gb-frontend:v4",
"ClusterName": "kubernetes-dev"
}
}
}
Please answer these questions before submitting your issue. Thanks!
macbook-m1:compile chai$ go env GOOS GOARCH
darwin
arm64
macbook-m1:compile chai$ go list
kusionstack.io/kusion/pkg/compile
macbook-m1:compile chai$ go test
# bou.ke/monkey
/Users/chai/go/pkg/mod/bou.ke/[email protected]/replace.go:24:14: undefined: jmpToFunctionValue
FAIL kusionstack.io/kusion/pkg/compile [build failed]
Go test build successe
# bou.ke/monkey
/Users/chai/go/pkg/mod/bou.ke/[email protected]/replace.go:24:14: undefined: jmpToFunctionValue
FAIL kusionstack.io/kusion/pkg/compile [build failed]
latest 2e9b750
Is your feature request related to a problem? Please describe:
No
Describe the feature you'd like:
Users can sepcify different different backend storage type to save state files like file system, S3, OSS...
Teachability, Documentation, Adoption, Migration Strategy:
Users provides config data of specified storage in some config files and kusion will pasres these configs to connect to this storage and save States to this storage
Kusion is Open Source project, LEGAL.md is not needed
Please answer these questions before submitting your issue. Thanks!
https://github.com/KusionStack/kusion/blob/main/third_party/README.md
File content is deprecated, Grumpy is not used in any code
Optimize the console ui of kusion
kusion apply use pterm.DefaultProgressbar
to format output progress detail message, initialized detail:
var (
// DefaultProgressbar is the default ProgressbarPrinter.
DefaultProgressbar = ProgressbarPrinter{
Total: 100,
BarCharacter: "█",
LastCharacter: "█",
ElapsedTimeRoundingFactor: time.Second,
BarStyle: &ThemeDefault.ProgressbarBarStyle,
TitleStyle: &ThemeDefault.ProgressbarTitleStyle,
ShowTitle: true,
ShowCount: true,
ShowPercentage: true,
ShowElapsedTime: true,
BarFiller: " ",
MaxWidth: 80,
}
)
Default set width to 100, when length of ProgressbarPrinter.Title
is over 100, will cause a displayed issue.
Pterm offer func WithMaxWidth()
, says:
// If the terminal is smaller than the given width, the terminal width will be used instead.
// If the width is set to zero, or below, the terminal width will be used.
so we can manually set width to 0, so pterm will keep to use terminal size.
K8s resources are alway be Updated since we directly compare Spec.Resource and resource's live state. We need a 3-way(Spec, State, Live) diff strategy to fix this issue.
Adjust github action configuration for kusion repo.
Purpose:
TODO
See our roadmap documents:
When you create a new CustomResourceDefinition (CRD), the Kubernetes API Server creates a new RESTful resource path for each version you specify. After the CustomResourceDefinition object has been created, you can create custom objects.
As we all know, preview the actual difference come the first in the workflow of kusion apply
, so when we apply CRD and CR at the same time, CRD is ok to preview, but CRs can not find in the kubernetes API Server, will return a NoMatchErr
.
We can ignore such error supposing the Action
of this resource is Create
. In addition, user must config CR DependOn
field, so the DAG of workflow from Kusion Engine can guarantee CR
createdOrUpdate after CRD
installed.
use kusion apply
to delete a resource
Resource action is Delete
.
Resource action is Unchange
.
v0.5.2
Please answer these questions before submitting your issue. Thanks!
kusion compile a.k -D a='["x","y","z"]' -D b='{"foo": "bar"}'
a = option("a")
b = option("b")
a:
- x
- y
- z
b:
foo: bar
❌ invalid argument "a=[\"x\",\"y\",\"z\"]" for "-D, --argument" flag: parse error on line 1, column 4: bare " in non-quoted-field
See 'kusion compile --help' for usage.
releaseVersion: v0.5.2
Add a labels field to the project or stack for custom label attachment to the project or stack.
// ProjectConfiguration is the project configuration
type ProjectConfiguration struct {
// Name of the project, unique in tenant scope
Name string `json:"name" yaml:"name"`
// Description of the project from manual writing and for human reading
Description string `json:"description,omitempty" yaml:"description,omitempty"`
// Customized Tags adhere to the project
Labels map[string]interface{} `json:"labels,omitempty" yaml:"labels,omitempty"`
}
// StackConfiguration is the stack configuration
type StackConfiguration struct {
// Name of the Stack, unique in project scope
Name string `json:"name" yaml:"name"`
// Description of the stack from manual writing and for human reading
Description string `json:"description,omitempty" yaml:"description,omitempty"`
// Customized Tags adhere to the project
Labels map[string]interface{} `json:"labels,omitempty" yaml:"labels,omitempty"`
}
Is your feature request related to a problem? Please describe:
No
Describe the feature you'd like:
Currently, Kusion can only watch & healthcheck some k8s native resources, we need to extend the scope of supported resources to K8s CR.
Users can write the CR healthcheck scripts in Konfig with KCL and Kusion will check this kind of resource's health after they are applied with customized CR healthcheck scripts.
Describe alternatives you've considered:
KCL healthcheck scripts is recommended, maybe we can support other scripts like Python or Lua
Teachability, Documentation, Adoption, Migration Strategy:
Ref: https://argo-cd.readthedocs.io/en/stable/operator-manual/health/
Please answer these questions before submitting your issue. Thanks!
create 3 resources successfully
releaseVersion: v0.4.2-alpha.1
gitInfo:
latestTag: v0.4.2-alpha.1
commit: 28b4f93
treeState: clean
buildInfo:
goVersion: go1.17.10
GOOS: linux
GOARCH: amd64
numCPU: 2
compiler: gc
buildTime: "2022-05-26 08:37:19"
dependency:
kclvmgoVersion: v0.4.2-alpha4
kclPluginVersion: v0.4.1-alpha2
Is your feature request related to a problem? Please describe:
CRD doesn't have KCL model now, we need figure out a solution to support this feature
Describe the feature you'd like:
CRDs can be save in one independent folder and in native k8s YAML formt. KCL will merge these YAML into the compile result
Teachability, Documentation, Adoption, Migration Strategy:
This is a common feature needed for all K8s users
How to set the root path of kclvm can be referred to:
https://pkg.go.dev/kusionstack.io/kclvm-go#InitKclvmPath
When the number of focus files increases to a huge scale, passing them through the --focus
option is not (--focus 参数)capable and will produce an "Argument list too long" error since the length of the bash scripts and environment variables has a limited capacity. So it's necessary to support passing the focus paths through an input file.
kusion deps --focus-conf <input_file_path>
Please answer these questions before submitting your issue. Thanks!
appops/guestbook-frontend
of konfig, delete project.yaml
prod
stack, execute kusion compile
error: project is not provided
nothing printed, compile success
releaseVersion: v0.6.1
gitInfo:
latestTag: v0.6.1
commit: c5eea56957d986ce8914187868dd6901ef0cfd26
treeState: clean
buildInfo:
goVersion: go1.17.13
GOOS: linux
GOARCH: amd64
numCPU: 2
compiler: gc
buildTime: "2022-09-05 02:45:23"
dependency:
kclvmgoVersion: v0.4.3-alpha.3
kclPluginVersion: v0.4.1-alpha2
Now kusion only watch changes some resource itself, not including dependent resources, for example:
Above resources are owner and dependent relation(OwnerReferences
), also can list by labels and selector(LabelSelector
).
Service and Endpoints are special, they have same name in same namespace, but Service is owner of EndpointSlice, and CANNOT list by labels.
Kusion should support to watch resources on some relationship chain, maybe ownerRef or labels
run-e2e.sh
installs ginkgo first, but use kusion module:
# Install ginkgo
GO111MODULE=on go install github.com/onsi/ginkgo/v2/ginkgo
However, kusion only depends on github.com/onsi/ginkgo/v2
, which not include ginkgo's dependencies.
So any contributor run go mod tidy
will remove unused entry from go.sum, then pipeline failed:
# Run e2e test
hack/run-e2e.sh
go: downloading github.com/onsi/ginkgo/v2 v2.0.0
go: downloading github.com/onsi/ginkgo v1.16.5
Error: ../../../go/pkg/mod/github.com/onsi/ginkgo/[email protected]/ginkgo/generators/bootstrap_command.go:9:2: missing go.sum entry for module providing package github.com/go-task/slim-sprig (imported by github.com/onsi/ginkgo/v2/ginkgo/generators); to add:
go get github.com/onsi/ginkgo/v2/ginkgo/[email protected]
Error: ../../../go/pkg/mod/github.com/onsi/ginkgo/[email protected]/ginkgo/internal/profiles_and_reports.go:12:2: missing go.sum entry for module providing package github.com/google/pprof/profile (imported by github.com/onsi/ginkgo/v2/ginkgo/internal); to add:
go get github.com/onsi/ginkgo/v2/ginkgo/[email protected]
Error: ../../../go/pkg/mod/github.com/onsi/ginkgo/[email protected]/ginkgo/labels/labels_command.go:15:2: missing go.sum entry for module providing package golang.org/x/tools/go/ast/inspector (imported by github.com/onsi/ginkgo/v2/ginkgo/labels); to add:
go get github.com/onsi/ginkgo/v2/ginkgo/[email protected]
make: *** [Makefile:35[7](https://github.com/KusionStack/kusion/actions/runs/3410235948/jobs/5672947142#step:7:8): e2e-test] Error 1
Error: Process completed with exit code 2.
The true usage as follows:
$ go install github.com/onsi/ginkgo/v2/ginkgo@latest
go: downloading github.com/onsi/ginkgo/v2 v2.4.0
go: downloading golang.org/x/tools v0.2.0
Now, kusion only support CRUD on k8s resources, we need to expand its capabilities to any schema
In some scenarios (for example, the dependency analyze step in Konfig CI) there's no need to actually compile with KCLVM, an image with rare kusion binary is enough and also more lightweight. It seems necessary to produce one in kusion's release pipeline.
kcl compile result is different with kusion compile
use any project just run kusion compile
and kcl compile
none
print compiled result base on kcl schema definition
for func apply/preview, logs are printed to standard output, desire for customized log's writing, and in a streaming way.
Calculate APPLY actions:
1
means not nil, 0
means nil
prior | plan | live | action | remark |
---|---|---|---|---|
1 | 1 | 1 | update | kusion apply |
1 | 1 | 0 | update | use kusion apply first, then resources are deleted without kusion. |
1 | 0 | 1 | delete | kusion apply or kusion destroy |
1 | 0 | 0 | delete | resources are create or updated with kusion, then deleted beforehand without kusion, now perform kusion destory |
0 | 1 | 1 | update | resources are create without kusion beforehand, now perform kusion apply |
0 | 1 | 0 | create | kusion apply |
0 | 0 | 1 | delete | resources are created beforehand without kusion, now perform kusion destory |
0 | 0 | 0 | --- | never reach |
Please answer these questions before submitting your issue. Thanks!
After concurrent execute kusion compile
for a period of time.
Normal compilation without error
releaseVersion: v0.4.2-alpha.1
gitInfo:
latestTag: v0.4.2-alpha.1
commit: 28b4f935cdd2813f5e7c09de855f6e584ed4af3c
treeState: clean
buildInfo:
goVersion: go1.17.10
GOOS: linux
GOARCH: amd64
numCPU: 2
compiler: gc
buildTime: "2022-05-26 08:37:19"
dependency:
kclvmgoVersion: v0.4.2-alpha4
kclPluginVersion: v0.4.1-alpha2
Currently, the mock package used by kusion is bou.ke/monkey
, but it has been archived.
Consider other go mock package. Reference:
As the title, kusion init
now cannot skip some stack and render each stack with all StackConfigs defined in kusion.yaml
We currently have supported watching and health-checking for some k8s native resources when we use command kusion apply --watch
. It is a very useful feature for users to understand what is happening and whether resources are ready to use when they are operating k8s resources.
More k8s native resources are required to be supported by Kusion. This issue is used to track resources in networking.k8s.io/v1
More details can be found in #23
github.dev is a web-based editor and its business version support running dev containers within the online workspace.
The codespace can start a container that is defined and configured by a custom devcontainers.json
file within the code repo.
The devcontainers.json
file usually consists of configurations such as a base image, some add-on features, and some commands that will be run after the container creates/starts.
We need to contribute a kusion feature to the dev container features. And the kusion feature needs to support kusion and KCL usage within the container:
The available dev container features are listed here. For example, there is Kubernetes-Minikube-in-docker feature. And kusion can be an add-on feature to collaborate with that to provide a local quick-start experience. Also, kusion can be adopted independently to provide experience to the remote cloud.
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.