Mirroring pub.dev packages to a custom package repository - flutter

As of Dart 2.15, you can create your own package repository.
https://dart.dev/tools/pub/custom-package-repositories#publishing-to-a-custom-package-repository
We need to mirror the subset of pub.dev packages (for corporative security reasons).
But there's no information, how to do a package mirroring.
Should I fork a GitHub source and publish every allowed package versions manually? It looks exremely annoying and time-consuming. And what about transitive dependencies? Should I upload all of them too?
I also found this article: https://medium.com/dartlang/hosting-a-private-dart-package-repository-774c3c51dff9 , it describes the pub.dev mirroring scenario too, but doesn't explains how to do it.

I don't know if this is the answer you are looking for, but I believe that with some experimentation this could be scripted using the APIs described in the dart package repository specification:
https://github.com/dart-lang/pub/blob/master/doc/repository-spec-v2.md
For example, you can query all versions of a package like so:
curl https://pub.dev/api/packages/test
{
"version": "1.23.1",
"pubspec": {
"name": "test",
"version": "1.23.1",
...
"dependencies": {
"analyzer": ">=2.0.0 <6.0.0",
...
"test_core": "0.4.24"
},
"dev_dependencies": {
...
}
},
"archive_url": "https://pub.dartlang.org/packages/test/versions/1.23.1.tar.gz",
...
}
....
}
You can then use the archive_url for the version(s) you want to download the package, potentially iterating over the dependencies and downloading them as well.
You would then need to upload each package version you downloaded to your private repo. This can be done by first doing a GET on the new package submission URL:
curl https://my-private-repo.tld/api/packages/versions/new
{
"url": "https://my-private-repo.tld/api/packages/versions/newUpload",
"fields": {}
}
And then POST the form described by fields plus the archive you previously downloaded to the url provided in the response. Note that when I test this against unpub, the fields map is empty, but depending on your private repo implementation that may be different.
One could imagine a script that starts with a list of packages to mirror, downloads them, potentially also downloads their dependencies, and then uploads them all to the private server.
For transitive dependencies it probably depends on your security requirements. If you use PUB_HOSTED_URL=https://my-private-repo.tld then running flutter pub get will download any dependencies it can find from your private repo, and any other dependencies from pub.dev. If that is not acceptable, then you'll probably need to upload them all.

Related

Using NuGet restore with lock files gives "NU1004: The packages lock file is inconsistent with the project dependencies" error

I am getting this error when I use the -LockMode switch with the nuget restore command.
NU1004: The packages lock file is inconsistent with the project
dependencies so restore can't be run in locked mode. Disable the
RestoreLockedMode MSBuild property or pass an explicit
--force-evaluate option to run restore to update the lock file.
What I am trying to achieve is to automatically upgrade my nuget references by using wildcards but use specific versions when I want to re-build my project from known sources. this blog posts describes how this can be achieved Enable repeatable package restores using a lock file.
When I use -UseLockFile & -LockMode on a simple solution with just one project it works as expected, the issue arises when I start adding another project to the solution.
Here're the steps:
I have published my package to an Azure DevOps feed and I have the following versions listed:
1.0.1-ci.1
1.0.1-ci.2
I have created a .Net 3.1 console app that references my package using wild cards, i.e. <PackageReference Include="My.Package" Version="1.0.*-ci.*" />
Running the command nuget restore -UseLockFile -ForceEvaluate creates the packages.lock.json with the right reference (I am using -ForceEvaluate in order to ensure it always resolves to the latest version available on the feed), the contents of the lock file of my console project are:
{
"version": 1,
"dependencies": {
".NETCoreApp,Version=v3.1": {
"My.Package": {
"type": "Direct",
"requested": "[1.0.*-ci.*, )",
"resolved": "1.0.0-ci.2",
"contentHash": "4HQuN7LNoZT9Z+MOL/Yig79FehhXBZmi26j3VtWR9Cgz8k5irWspSQ8aasVbNkYp7AgA2XaDQdr/cnwJnPilpQ=="
}
}
}
}
I then publish a new version of My.Package (1.0.1-ci.3) and run the command nuget restore -LockedMode, and the version resolved is still 1.0.1-ci.2, and if I then run nuget restore -ForceEvaluate it will resolve as expected to 1.0.1-ci.3, so far so good!
The issue arises when I add a class library to my solution which uses the same package reference, i.e. <PackageReference Include="My.Package" Version="1.0.*-ci.*" />, when I run restore -UseLockFile -ForceEvaluate my packages.lock.json file is updated to include the project dependency:
{
"version": 1,
"dependencies": {
".NETCoreApp,Version=v3.1": {
"My.Package": {
"type": "Direct",
"requested": "[1.0.*-ci.*, )",
"resolved": "1.0.0-ci.3",
"contentHash": "4HQuN7LNoZT9Z+MOL/Yig79FehhXBZmi26j3VtWR9Cgz8k5irWspSQ8aasVbNkYp7AgA2XaDQdr/cnwJnPilpQ=="
},
"classlibrary1": {
"type": "Project",
"dependencies": {
"My.Package": "1.0.0-ci.0"
}
}
}
}
}
While the contents of the lock file of the Class Library project are:
{
"version": 1,
"dependencies": {
".NETCoreApp,Version=v3.1": {
"My.Package": {
"type": "Direct",
"requested": "[1.0.*-ci.*, )",
"resolved": "1.0.0-ci.3",
"contentHash": "4HQuN7LNoZT9Z+MOL/Yig79FehhXBZmi26j3VtWR9Cgz8k5irWspSQ8aasVbNkYp7AgA2XaDQdr/cnwJnPilpQ=="
}
}
}
}
After this when I try running restore -LockMode I get the NU1004 error mentioned earlier.
Doing what the error message suggests and use -ForceEvaluate would clearly break what I wanted to achieve, yet I can't imagine that this relatively simple scenario is not covered by NuGet, so I would guess I am doing something wrong, does anyone have any ideas of what I could try to make this work?
It sounds like you're adding a new dependency then running nuget restore -LockedMode without first running nuget restore -ForceEvaluate.
It's not obvious what NuGet should do in that case - you're telling it you only want to use the dependencies in your lock file but you've also added new dependencies too.
It sounds like this would typically fail the restore:
If locked mode is set, restore will either get the exact packages as listed in the lock file or fail if it cannot. For example, if you updated the defined package dependencies for the project after lock file was created
https://devblogs.microsoft.com/nuget/enable-repeatable-package-restores-using-a-lock-file/#why-use-a-lock-file
You might have hit a corner case if the only transitive dependency of your new dependency is one that's already in the lock file but at a different version.
In general though, whenever you add new dependencies you're going to need to update your lock file, then after that you should be set to carry on running nuget restore -LockedMode.

Local swift package with local dependency

I have a project that I plan on developing in modules, the final application will be any number of the modules built together based on a configuration. I have a swift package that has all of my common code it it, we can call that the platform package. I then went to create my first feature, this went just fine however when I created the wrapper application to pull in each feature, I got this error from SPM in xcode11:
package 'Platform' is required using a revision-based requirement and it depends on local package
'Feature1', which is not supported.
Looking at the code base for SPM here (line 72)
https://github.com/apple/swift-package-manager/blob/master/Sources/PackageGraph/DependencyResolver.swift
It looks like this is something that is just not supported, the mixing of local and remote dependencies? Is this a limitation of SPM / should I be trying to use another tool for this type of app architecture?
In my case, I was trying to add a package, which I was developing, and its Package.swift contained dependencies of the form:
dependencies: [
.package(path: "../PackageName"),
// etc
Changing the references to specific repos solved the problem:
dependencies: [
.package(path: "http://github.com/..."),
// etc

Unable to find nuget folder

I'm unable to find some nuget packages (VS 2019, asp.net core 2.2). I found that System.ComponentModels.Annotations can't be found in my .nuget folder and in VS, there is no "expand" arrow next to it like all the other packages:
In my .nuget folder:
I've tried clearing out my packages folder and re-building to get all the packages. I've tried update-package -reinstall. I've tried Installing system.componentmodel.annotations directly (rather than having it install as a dependency). My solution builds fine, but I can't find this package anywhere on my harddrive. I've also noticed that Microsoft.AspNetCore.Razor.Design is exhibiting the exact same behavior.
When NuGet restores a project that uses PackageReference for packages (all SDK-style projects, and opt-in for traditional projects), it writes the obj\project.assets.json file, which is what MSBuild uses to complete the rest of the build.
Looking at the packageFolders section of my test project, I see this:
"packageFolders": {
"c:\\git\\test\\globalPackages\\": {},
"C:\\Program Files\\dotnet\\sdk\\NuGetFallbackFolder": {}
},
note that I have a nuget.config that redirects my global packages folder away from my user profile global packages folder, so temporary/fake packages I create don't pollute my real dev environment. FYI in case you're wondering why you don't see c:\users\zivkan\.nuget\packages.
But notice that there are two package folders.
Looking for System.ComonentModel.Annotations in the libraries section of project.assets.json, I see:
"System.ComponentModel.Annotations/4.5.0": {
"sha512": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg==",
"type": "package",
"path": "system.componentmodel.annotations/4.5.0",
"files": [
// list of every file in package
]
},
see the path says system.componentmodel.annotations/4.5.0, which means it could be in either or both of c:\git\test\globalPackages\system.componentmodel.annotations\4.5.0 and/or C:\Program Files\dotnet\sdk\NuGetFallbackFolder\system.componentmodel.annotations\4.5.0.
For your use-case of trying to load it in Powershell, you can try to load one of the assemblies in the lib\* directory. Pick a TFM you think is compatible with your version of Powershell.
As for the reason that Solution Explorer doesn't have a twisty to expand the package, go find the package in the targets section of the project.assets.json and you'll see this:
"System.ComponentModel.Annotations/4.5.0": {
"type": "package",
"compile": {
"ref/netcoreapp2.0/_._": {}
},
"runtime": {
"lib/netcoreapp2.0/_._": {}
}
},
In other words, the package is not bringing in any assets or additional NuGet dependencies. Therefore nothing to expand in Solution Explorer.
In this specific case it's because netcoreapp2.0 has the assembly built-in to the runtime, and the Microsoft.NETCore.App package has the compile-time metadata for it. This is why I asked why you are looking for the package. If you use project.assets.json to find the exact System.ComponentModel.Annotations.dll that the build uses during compile, you'll find a metadata-only reference assembly that can't be loaded. But I gave insturations above on how to find the package directory and you can look for a loadable dll in one of the lib\* directories to try to load in Powershell.

project.json specify exact version of NuGet dependency

When using a packages.configfile to specify NuGet dependencies I'm able to provide the allowedVersions attribute to specify a SemVer string defining the range of versions I want to be able to update to. By using [] I'm currently able to effectively pin my package to a single version. Eg:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Common.Logging" version="3.3.0" allowedVersions="[3.3.0, 3.3.0]" />
</packages>
Now that in .net core projects we have project.json to specify NuGet dependencies (however short lived it may be), how can I pin a NuGet dependency to a version such that dotnet restore doesn't update my application to a new version of one is available from my package source?
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"Newtonsoft.Json": "9.0.1" //how can i pin to 9.0.1 ??
},
}
Figure #2 in this nuget documentation stronly implies this is possible, but doesn't provide the syntax to do it.
-- UPDATE --
I tested this with two .net core class libraries and my local file system as a package repository. I created a class library called UpdateMeDependencyLib and packaged it as v1.0.0, and I consumed it from a second project via nuget. Below is the project.json from the 2nd class library consuming UpdateMeDependencyLib
{
"version": "1.0.0-*",
"dependencies": {
"NETStandard.Library": "1.6.0",
"UpdateMeDependencyLib": "1.0.0"
},
"frameworks": {
"netstandard1.6": {
"imports": "dnxcore50"
}
}
}
I then updated UpdateMeDependencyLib to version 1.1.0 and repackaged, so there is now a v1.0.0 and a v1.1.0 nuget package on my local system. After creating v1.1.0 of UpdateMeDependencyLib I now get the following experience
Compiling the project in Visual Studio (with no changes to consumer project.json) that consumes UpdateMeDependencyLib outputs v1.1.0 to its bin directory
If I force a package restore on the consumer library I now get a Nuget warning "NU1007 Dependency specified was UpdateMeDependencyLib >= 1.0.0 but ended up with UpdateMeDependencyLib 1.1.0"
So it would appear simply using "1.0.0" in my consuming library doesn't pin it and it will automatically get updated when a new version appears in my NuGet source.
You need to use the following notation for your ref
"UpdateMeDependencyLib": {
"version": "1.0.0",
"target": "package"
}
As the two projects are in the same solution, the system doesn't use your local package repo to resolve the dependency. It directly uses the project as reference. Because the reference 1.0.0 no longer exists in the solution, (and because "UpdateMeDeepencyLib": "1.0.0" means >= 1.0.0), it use the Nuget rule "Lowest applicable version" and resolve the dependency by referencing the 1.1.0 project. Note the icon of the UpdateMeDependencyLib in the dependency tree is not the nuget one.
What I can't figure out is, how we can stricly set the dependency to 1.0.0 and, in this case, break the build.
To lock in a specific version, place the version number inside square brackets.
"UpdateMeDependencyLib": {
"version": "[1.0.0]",
"target": "package"
}
You will need to do a restore packages after updating.

Git hook update package json version

In our project we often forget to update version numbers in Package.json file. Ours is a AngularJS project. In our package JSON file we are specifying the below two version information
"version": "1.0.7",
"devVersion": "1.0.4"
Before Merging a branch to develop I want a automated script to update these above two version numbers. I am thinking Git Hooks will help me.
Where can i find the hooks, I am able to see the hooks in my local repo under .git folder. I am confused which hook to use. Searching on Google suggests I have to create hooks on server.
Where can i find them and can i update the above both keys (version and devVersion) ?
Pls suggest the location and hook to use, this will solve a lot of problem.
I am using husky and git-branch-is:
"scripts": {
...
"postmerge": "(git-branch-is master && npm version minor ||
(git-branch-is dev && npm --no-git-tag-version version patch)",
...
},
Read more about npm version
Webpack or Vue.js
If you are using webpack or Vue.js, you can display this in the UI using Auto inject version - Webpack plugin
NUXT
In nuxt.config.js:
var WebpackAutoInject = require('webpack-auto-inject-version');
module.exports = {
build: {
plugins: [
new WebpackAutoInject({
// options
// example:
components: {
InjectAsComment: false
},
}),
]
},
}
Inside your template for example in the footer:
<p> All rights reserved © 2018 [v[AIV]{version}[/AIV]]</p>
You have two kinds of hooks (both present in any .git/hooks folder): server and client hooks.
They are listed in "Customizing Git - Git Hooks"
A merge is a local operation, so if you wanted to automate any process during a merge, you would need a client hook, like a post-commit hook (meaning executed just after creating a merge commit).
If you need to update that file before a merge, you can try a pre-commit hook, and check if a merge is in progress (if not, your pre-commit hook would do nothing since you want to update the versions only before a merge).
You can see in this answer an example of a post-commit hook which generates a version.json file.
If is written in node, but you can write a hook ni any scripting language you want.
With Husky, it's extremely simple:
{
"name": "demo-project",
"version": "0.0.3",
"husky": {
"hooks": {
"pre-commit": "npm --no-git-tag-version version patch && git add ."
}
}
}
Note: I put git add . in the end because after we update package version, we need to stage it