badgerati / fudge Goto Github PK
View Code? Open in Web Editor NEWFudge is a PowerShell tool to help manage software packages via Chocolatey for specific development projects. Think NPM and Bower, but for Chocolatey
License: MIT License
Fudge is a PowerShell tool to help manage software packages via Chocolatey for specific development projects. Think NPM and Bower, but for Chocolatey
License: MIT License
Choco packages can list dependencies in the nuspec included in the nupkg.
The choco stdout also contain a list of dependencies as they are being processed ; if the choco stdout is being read as a stream, this could allow 'real-time' UI for showing the dependencies.
The choco logs also contain the dependency info.
There is also the ability for choco packages to install multiple packages, and optionally skip some based on custom logic in the nupkg. It should be relatively easy to snapshot/monitor the windows installed software list to see what was installed during each Fudge entry.
It would be wonderful if the dependency info was stored in a "Fudgefile.snapshot" (arbitrary suffix to try to describe what it would be). While it is very unlikely the snapshot file would initially be re-usable on any different computer, and therefore isnt a .lock
, it would be great to be able to use it when rebuilding on an identical system, such as a CI VM, so Fudge can report when there are changes to the dependencies. In the coala repos, we would have at least two different snapshot files, one for AppVeyor and one for Travis Windows CI.
For ordinary users, likely the snapshot from one user omits some packages which were installed previously, and another user would find they are missing and commit the improved snapshot file.
I expect long term, if anyone is interested, the snapshot file could become a lock file, by adding constraints to each entry to indicate when that dependency is active. The most obvious constraint in lock files (e.g. by gems, pip, npm) is OS, and that would likely apply here, but more likely as Windows OS versions.
It would be nice if this worked
PS> Install-Module Fudge
Otherwise it is a bit difficult on Linux. e.g.
> Get-PSRepository
Name InstallationPolicy SourceLocation
---- ------------------ --------------
PSGallery Untrusted https://www.powershellgallery.com/api/v2
PS> nuget
nuget : The term 'nuget' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ nuget
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (nuget:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS> Install-PackageProvider Nuget
Install-PackageProvider : No match was found for the specified search criteria for the provider 'Nuget'. The package provider requires 'PackageManagement' and 'Provider' tags. Please check if the specified package has the tags.
At line:1 char:1
+ Install-PackageProvider Nuget
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (Microsoft.PowerShel\u2026tallPackageProvider:InstallPackageProvider) [Install-PackageProvider], Exception
+ FullyQualifiedErrorId : NoMatchFoundForProvider,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackageProvider
^D
$ sudo zypper install mono-nuget
Loading repository data...
Reading installed packages...
Resolving package dependencies...
The following 2 NEW packages are going to be installed:
mono-devel mono-nuget
2 new packages to install.
Overall download size: 12.5 MiB. Already cached: 0 B. After the operation, additional 77.7 MiB will be used.
Continue? [y/n/v/...? shows all options] (y): y
Retrieving package mono-devel-5.20.1-2.3.x86_64 (1/2), 12.2 MiB ( 76.3 MiB unpacked)
Retrieving: mono-devel-5.20.1-2.3.x86_64.rpm .........................................................................................................[done (613.3 KiB/s)]
Retrieving package mono-nuget-2.8.7-1.9.noarch (2/2), 347.0 KiB ( 1.5 MiB unpacked)
Retrieving: mono-nuget-2.8.7-1.9.noarch.rpm ...........................................................................................................[done (31.0 KiB/s)]
Checking for file conflicts: .......................................................................................................................................[done]
(1/2) Installing: mono-devel-5.20.1-2.3.x86_64 .....................................................................................................................[done]
(2/2) Installing: mono-nuget-2.8.7-1.9.noarch ......................................................................................................................[done]
$ pwsh
PS> Install-PackageProvider Nuget
Install-PackageProvider : No match was found for the specified search criteria for the provider 'Nuget'. The package provider requires 'PackageManagement' and 'Provider' tags. Please check if the specified package has the tags.
At line:1 char:1
+ Install-PackageProvider Nuget
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (Microsoft.PowerShel\u2026tallPackageProvider:InstallPackageProvider) [Install-PackageProvider], Exception
+ FullyQualifiedErrorId : NoMatchFoundForProvider,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackageProvider
^D
$ nuget install Fudge
If 'nuget' is not a typo you can use command-not-found to lookup the package that contains it, like this:
cnf nuget
$ rpm -ql mono-nuget
/usr/lib/mono/nuget
/usr/lib/mono/nuget/Microsoft.Web.XmlTransform.dll
/usr/lib/mono/nuget/NuGet.Core.dll
/usr/lib/mono/nuget/NuGet.exe
$ NuGet install Fudge
If 'NuGet' is not a typo you can use command-not-found to lookup the package that contains it, like this:
cnf NuGet
$ NuGet.exe install Fudge
If 'NuGet.exe' is not a typo you can use command-not-found to lookup the package that contains it, like this:
cnf NuGet.exe
$ /usr/lib/mono/nuget/NuGet.exe install Fudge
bash: /usr/lib/mono/nuget/NuGet.exe: cannot execute binary file: Exec format error
$ mono /usr/lib/mono/nuget/NuGet.exe install Fudge
Installing 'fudge 1.3.0'.
Successfully installed 'fudge 1.3.0'.
jayvdb@linux-lwww:~/projects/coala/coala-bears> pwsh
$ pwsh
PS> fudge
fudge : The term 'fudge' is not recognized as the name of a cmdlet, function, script file, or operable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ fudge
+ ~~~~~
+ CategoryInfo : ObjectNotFound: (fudge:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS> . ./fudge.1.3.0/tools/Fudge.ps1 search choco
Fudge v1.3.0
Error checking user administrator priviledges
Windows Principal functionality is not supported on this platform.
Must be running with administrator priviledges for Fudge to fully function
Duration: 00:00:00.2168319
i.e. I dont know why Install-PackageProvider Nuget
doesnt 'just work' - it does on Windows. The openSUSE mono-dotnet doesnt install the provider into OneGet , and it doesnt do the voodoo needed to make .exe an executable format.
Sure I can work all of this out, and do it manually, and I will, but all of this can be bypassed because PSGallery is the only provider pre-installed with pwsh
.
Continuing from #59
.psd1 support would have lots of advantages. It doesnt need to replace the Fudgefile[.json] support. It should be additional, for people who have needs which make simple json undesirable. This also avoids backwards compatibility issues.
Re the "trailing comma" problem mentioned in issue #59, I see them used a lot, e.g.
https://github.com/PowerShell/PSScriptAnalyzer/blob/master/Engine/Settings/CodeFormattingOTBS.psd1
I hope it isnt a standard linting rule that they should be added.
Also another possible negative is that lint rules for PS typically require alignment of '=', which means adding a new property with a longer length means that other lines need to be adjusted to insert more whitespace. Whitespace additions are not nearly as bad, as git includes options to ignore whitespace changes, even when tracing through the blame history.
The reason why linting rules are relevant is the standard linter doesnt have good ability to ignore some files. PowerShell/PSScriptAnalyzer#1230
While cleaning up my own code, I accidentally ran PSScriptAnalyzer on Fudge. Here are the results.
Perhaps adding CI for PSScriptAnalyzer would be helpful, with a custom set of ignores for things you believe are not appropriate to solve.
RuleName Severity ScriptName Line Message
-------- -------- ---------- ---- -------
PSPossibleIncorrectComparisonWithNu Warning Fudge.ps1 278 $null should be on the left side of equality comparisons.
ll
PSPossibleIncorrectComparisonWithNu Warning Fudge.ps1 296 $null should be on the left side of equality comparisons.
ll
PSUseShouldProcessForStateChangingF Warning FudgeTools 468 Function 'Remove-Fudgefile' has verb that could change
unctions .psm1 system state. Therefore, the function has to support
'ShouldProcess'.
PSUseShouldProcessForStateChangingF Warning FudgeTools 623 Function 'New-Fudgefile' has verb that could change system
unctions .psm1 state. Therefore, the function has to support
'ShouldProcess'.
PSUseShouldProcessForStateChangingF Warning FudgeTools 932 Function 'Start-ActionPackages' has verb that could change
unctions .psm1 system state. Therefore, the function has to support
'ShouldProcess'.
PSUseShouldProcessForStateChangingF Warning FudgeTools 996 Function 'Start-ActionPack' has verb that could change
unctions .psm1 system state. Therefore, the function has to support
'ShouldProcess'.
PSUseSingularNouns Warning FudgeTools 33 The cmdlet 'Write-Details' uses a plural noun. A singular
.psm1 noun should be used instead.
PSUseSingularNouns Warning FudgeTools 85 The cmdlet 'Compare-Versions' uses a plural noun. A
.psm1 singular noun should be used instead.
PSUseSingularNouns Warning FudgeTools 932 The cmdlet 'Start-ActionPackages' uses a plural noun. A
.psm1 singular noun should be used instead.
PSUseSingularNouns Warning FudgeTools 1119 The cmdlet 'Add-CoreChocoPackages' uses a plural noun. A
.psm1 singular noun should be used instead.
PSUseSingularNouns Warning FudgeTools 1413 The cmdlet 'Format-ChocolateyParams' uses a plural noun. A
.psm1 singular noun should be used instead.
PSUseSingularNouns Warning FudgeTools 1636 The cmdlet 'Invoke-FudgeLocalDetails' uses a plural noun. A
.psm1 singular noun should be used instead.
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 371 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 371 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 775 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 787 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 832 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 1077 $null should be on the left side of equality comparisons.
ll .psm1
PSPossibleIncorrectComparisonWithNu Warning FudgeTools 1750 $null should be on the left side of equality comparisons.
ll .psm1
PSAvoidUsingInvokeExpression Warning FudgeTools 865 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 887 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 927 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 1761 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 1767 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 1773 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 1779 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
PSAvoidUsingInvokeExpression Warning FudgeTools 1791 Invoke-Expression is used. Please remove Invoke-Expression
.psm1 from script and find other options instead.
It would be lovely if Fudge could be a bridge between choco and other sources.
https://github.com/akamac/load-dependencies/blob/master/load-dependencies.ps1 includes support for 'nuget', 'powershellget', and 'gitlab'.
i.e. All of those could be supported by moving up the stack, and being a OneGet wrapper, which has a lot of providers https://github.com/OneGet/oneget/wiki/Provider-Requests.
Which no doubt makes you think about https://github.com/Badgerati/Picassio and https://github.com/Badgerati/Picassio2
fudge new
only imports the name
(id) and version
from a nuspec file.
https://chocolatey.org/docs/commandsinstall#packagesconfig is the choco format , and includes many additional fields.
The example listed is
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="apackage" />
<package id="anotherPackage" version="1.1" />
<package id="chocolateytestpackage" version="0.1" source="somelocation" />
<package id="alloptions" version="0.1.1"
source="https://somewhere/api/v2/" installArguments=""
packageParameters="" forceX86="false" allowMultipleVersions="false"
ignoreDependencies="false"
/>
</packages>
When running new
, allow the passing of local
(as well as nuspec paths), so that a Fudgefile is created with references to all of the packages currently installed locally:
fudge new local
Which will run choco list -lo
, and create a Fudgefile with packages installed locally.
Invoke-Chocolatey
calls Update-FudgeEnvironmentVariables
which doesnt exist.
I guess it should be calling Update-EnvironmentVariables
It would be helpful if Fudge detected nuget/choco failed due to transient network problems, and retried the operation.
i.e. workaround upstream issues chocolatey/choco#1853 and NuGet/Home#2269
The current package
section don't easily allow for expansion, such as passing unique sources, parameters and other arguments to installing packages. (otherwise we'd have a section for params, a section for arguments, etc. and it'd all look very ugly).
This change will make packages
into an array of package objects; each will contain the mandatory "name"
, followed by the optional "version"
, "source"
, "params"
, and "args"
.
The current "source"
value will remain, as it will act as a global value to all packages (if they come from the same source). Though if the package specifies it's own source that will take precedence.
example:
{
"source": "",
"packages": [
{
"name": "curl"
},
{
"name": "python3",
"params": "some parameters to pass",
"args": "--x86"
}
],
"devPackages": [
{
"name": "7zip.install",
"version": "16.4.0.20170506"
}
]
}
When fudge install
is called without naming packages, the switch -args
is silently ignored.
There are args which are suitable to be used for all packages, such as --forcex86
for creating a x86 setup when that isnt normally wanted and shouldnt be put into the Fudgefile.
i.e. I want my CI to have a --forcex86 job, but not force that onto the devs by putting it into the Fudgefile
.
Add a new action of "prune" to Fudge, so that when run it will uninstall all packages (via choco) that are no in the passed Fudgefile:
fudge prune
ie: if you have git, 7zip, cake
installed but the Fudgefile only has git, cake
then 7zip
will be uninstalled
Fudge should have a new command of delete
which will delete the default or a custom Fudgefile.
There should also be a new flag of -Uninstall
(Alias: -u
) which will first uninstall the packages within the file before deleting it. The -Dev
and -DevOnly
flags should also apply here too.
Examples:
fudge delete
fudge delete -fp './CustomFile'
fudge delete -u
fudge delete -u -d
The last one will uninstall all packages, including dev ones, then remove the Fudgefile
Seems like there is a few problems preventing the basics from working. (Note I dont have choco installed yet, so that should be the first error I see)
$ pwsh -c ". assets/fudge/Fudge.ps1 list"
Fudge v$version$
Error checking user administrator priviledges
Windows Principal functionality is not supported on this platform.
Must be running with administrator priviledges for Fudge to fully function
Duration: 00:00:00.4940592
$ pwsh -c ". assets/fudge/Fudge.ps1 pack -fudgefile .ci/Fudgefile.appveyor"
Fudge v$version$
Error checking user administrator priviledges
Windows Principal functionality is not supported on this platform.
Must be running with administrator priviledges for Fudge to fully function
Duration: 00:00:00.2603162
Leave out a comma and the error is Invalid JSON primitive: .
. It would be nice if there was an indication which line the error was on, or just say "Invalid JSON: <filename>
" or something like that.
One minor complication I found as a newcomer was that I couldnt do fudge
on the cmd.exe
command line. That requires fudge.ps1 to be in PATH and for .ps1 to be in PATHEXT. Choco can help with those.
It would be helpful to have a verbose mode, especially to show what was hidden during Format-ChocolateyList
, and this should be default if there was an error during a chocolatey action.
I am guessing I can do something like
fudge install;
cat C:\ProgramData\chocolatey\logs\chocolatey.log;
But that is a bit clumsy.
When I have a Fudgefile with Git
and some other tools like
{
"name": "visualstudio2017buildtools",
"version": null,
"args":null,
"params": null
},
it also installs chocolatey-visualstudio.extension
But when, for example, I remove Git from the Fudgefile and run fudge prune
it tries to remove packages not mentioned in the Fudgefile, like chocolatey-visualstudio.extension
.
choco list -local
returns 32 packages (including dependencies)
fudge list -local
returns 13 packages (without dependencies)
Is there some way to counteract this behavior?
Fudge should support StrictMode. e.g. #67 was one problem.
Possibly #58 (comment) is also caused by this.
This can be a gradual thing, as it will likely require several changes.
After the installation is done for an unspecified version, fudge should show which version was installed.
Ability to list packages in the Fudgefile and show information about which ones are installed, not installed, and have a different version installed then specified in the file.
fudge list
You should also be able to run fudge list <package_id>
and it will list the information for that package only. If that package ID cannot be found, Fudge will list the closest named packages instead.
The call structure for this will be something like:
fudge renew
fudge renew nuspec
fudge renew local
renew
: remove all packages/devPackages from the Fudgefile.renew nuspec
: remove all packages, then re-add from the nuspecs in the pack
sectionrenew local
: remove all packages, then re-add based on locally installed packagesAs a simplified version of #57 , perhaps an easier approach atm is to snapshot the choco package list at the beginning of a non-adhoc install, and at the end report any extra packages which were installed.
At the moment my CI includes choco list --local-only
afterwards so I know what was actually installed. This would be unnecessary if Fudge could emit the list of unexpected additions. It really doesnt matter why they were installed; the most important information is the final list, so it can be compared with previous CI build logs whenever a build breaks.
choco packages have some rather strange versions at times. Most people dont want to put patch numbers into a package.json
or similar. They expect those to be handled in a lock file.
And often one wants updates, but only to the same minor release, but not the next major, so ideally something like ~1.2
is supported.
When I tried to specify just 3.1
for a package without a 3.1*, I get
Installing R.project (3.1) > failed
Chocolatey v0.10.11 Installing the following packages: R.project By installing you accept licenses for the packages. R.project not installed. The package was not found with the source(s) listed. Source(s): 'https://chocolatey.org/api/v2/' NOTE: When you specify explicit sources, it overrides default sources. If the package version is a prerelease and you didn't specify `--pre`, the package may not be found. Version was specified as '3.1'. It is possible that version does not exist for 'R.project' at the source specified. Please see https://chocolatey.org/docs/troubleshooting for more assistance. Chocolatey installed 0/1 packages. 1 packages failed. See the log for details (C:\ProgramData\chocolatey\logs\chocolatey.log). Failures - R.project - R.project not installed. The package was not found with the source(s) listed. Source(s): 'https://chocolatey.org/api/v2/' NOTE: When you specify explicit sources, it overrides default sources. If the package version is a prerelease and you didn't specify `--pre`, the package may not be found. Version was specified as '3.1'. It is possible that version does not exist for 'R.project' at the source specified. Please see https://chocolatey.org/docs/troubleshooting for more assistance.
When I tried to specify just 7.3
for php, I got an error about it being less than the installed 7.3.6
Using ^
:
Chocolatey v0.10.11 Installing the following packages: php By installing you accept licenses for the packages. '^7.3' is not a valid version string. Parameter name: version
When using develop branch, I am seeing a problem with the code added in #55
The variable '$latest' cannot be retrieved because it has not been set.
See https://ci.appveyor.com/project/jayvdb/mobans/builds/25484849/job/fgbips38471hguug
And latest https://gitlab.com/coala/mobans/merge_requests/130
It would be helpful to see how long each package took to install, and a ticker / progress bar to look at while it is installing each package
priviledges -> privileges
The Fudgefile could do with having a source
property which allows for the installation of packages from custom/local sources. If not supplied, will just default to the main chocolatey source.
Spawned from #42 (comment)
The pnpmfile.js approach is very powerful. At each layer of the package tree, the data structure is given to the hook which can modify it, and pnpm uses the modified structure. For context, in pnpm this is critical as npm authors often forget to declare a direct dependency because it is installed by another declared dependency. In a flat node_modules it doesnt matter, but it breaks pnpm. However I see the same underlying problem in choco -- the packages are often poorly maintained, and either we create our own packages for everything or fix them at runtime. The latter approach has a lower ongoing maintenance cost, and it isolates the problems and the fixes needed, so it is easy to then report bugs with solutions upstream.
At the moment, Fudge only has two levels of nesting - the top level, and then each entry in the Fudgefile. I expect that will change to three levels when dependency tracking is added. nuspec format already describes dependencies so that could be added quite easily. For real choco dependencies, it gets a bit more tricky #57 .
The which command relies on the program being findable using PATH, like where.exe
.
This means it does not work after fudge install
in a cmd.exe
, until the $env:PATH
has been refreshed from the registry, e.g. using https://github.com/chocolatey-archive/chocolatey/blob/master/src/redirects/RefreshEnv.cmd from cmd or https://github.com/chocolatey/choco/blob/stable/src/chocolatey.resources/helpers/functions/Update-SessionEnvironment.ps1 in powershell.
It would be helpful if it also searched for the program using the PATH live in the registry keys, or invoked Update-SessionEnvironment
before looking for programs.
Cue debate ...
Similar to when deleting Fudgefiles, there should be a tag when creating new ones to install the packages after creating the file.
-Install
[alias: -i
]Examples:
fudge new -i
fudge new -i -d
Add the ability for fudge to create new empty Fudgefiles by typing:
fudge new
This will create basic template. If the -fp
argument is passed, an empty template will be create there.
Typing:
fudge new ./path/to/tool.nuspec
will create a basic Fudgefile, but will auto-populate the packages
with the dependencies from the nuspec; and will add the nuspec to the packs
section of the new Fudgefile.
Of course, if a file already exists at the location then error - do not overwrite
Composer needs to know where php is located, so it would look something like this:
{
"name": "php",
"version": "7.3.6",
"params": "/InstallDir:C:\\tools\\php"
},
{
"name": "composer",
"args": "/PHP=C:\\tools\\php\\php.exe"
},
But it would be much nicer if there were not hard-coded directories could be something like
{
"name": "php",
"version": "7.3.6",
},
{
"name": "composer",
"args": "/PHP=$(fudge which php)"
},
or perhaps
{
"name": "composer",
"dynamic-args": "name-of-script-returning-args-as-string"
},
There is already a dependency between the composer and php packages, so the dynamic scriptlet only needs to be run just before composer is ready to be installed.
Have a -DevOnly
flag to only action upon the devPackages if there are any present in the Fudgefile.
Ie, this should only install, upgrade, uninstall, reinstall, and list the devPackages
only.
Exit code of 3010 (Reboot) from Chocolatey causes Fudge to fail
If output contains "exit code 3010
", or LASTEXITCODE
is 3010, don't fail. Make sure to output that you may need to reboot machine afterwards.
I am copying Fudge into our mobans repository - it is only two files, and this means we can pin our version to a development version - and it is distributed from there to all of the coala repositories.
Three tweaks that would help.
git rebase
to emit confusing messages, even when the rebase is not touching the files which have trailing whitespace.Modules
subdirectory containing only a single file.Fudge v$version$
, likely because it couldnt find the correct version to report. The quick fix is to not report a version when there is no real version for the code being executed.Add a new action of "clean" to Fudge, so that when run it will uninstall all packages (via choco) that are currently installed - regardless of Fudgefiles:
fudge clean
ie: if you have git, 7zip, cake
installed then git, 7zip, cake
will all be uninstalled
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.