Local dependency cannot be resolved - move-lang

I know there is a similiar question right below this one but the answer does not solve my issue.
I have a published package and would like to refer to it from another one.
The dependency is defined locally (not git), however the build command returns 'Failed to build Move modules: "Unable to resolve packages for package 'Parent'".' thus I'm doing something wrong with the linking.
the project structure looks like this:
Parent Move.toml
[package]
name = "Parent"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
Child = { local = "child" }
[addresses]
parent = "0x0"
child = "0x08f5f5f4101e9c4b2d2b3f212b6e909b48acd02c"
Child Move.toml
[package]
name = "Child"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
[addresses]
child = "0x0"
foo.Move
module child::foo {
use sui::tx_context::{TxContext};
fun init(_: &mut TxContext) {}
public fun test(): u8 {
10
}
}
bar.Move
module parent::bar {
use sui::tx_context::{TxContext};
use child::foo::{Self};
fun init(_: &mut TxContext) {
let value_from_child = foo::test();
}
}
I am on Windows.

The issue is that module child is bound to address 0x0 in package Child, but bound to your published address in package Parent. Currently, there are a couple of ways you could get things building.
1. Assign child the same address (its published address) in both packages:
(Recommended if Child is intended to be published in one place and then reused by everyone there)
./Move.toml
[package]
name = "Parent"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
Child = { local = "child" }
[addresses]
parent = "0x0"
child = "0x08f5f5f4101e9c4b2d2b3f212b6e909b48acd02c"
./child/Move.toml
[package]
name = "Child"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
[addresses]
child = "0x08f5f5f4101e9c4b2d2b3f212b6e909b48acd02c"
2. Assign child a placeholder address in Child and substitute it in Parent.
(Recommended if Child is a library that you expect to re-publish along with the packages that use it)
./Move.toml
[package]
name = "Parent"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
Child = { local = "child", addr_subst = { "child" = "0x08f5f5f4101e9c4b2d2b3f212b6e909b48acd02c" } }
[addresses]
parent = "0x0"
./child/Move.toml
[package]
name = "Child"
version = "0.0.1"
[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework", rev = "devnet-0.10.0" }
[addresses]
child = "_"

Related

how to deploy escloud extension in terraform

I deploy escloud with terraform.
I want to add an existing extension, analysis-icu, how can I configure it?
resource "ec_deployment_extension" "icu" {
name = "analysis-icu"
version = "*"
extension_type = "bundle"
download_url = "https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-nori/analysis-nori-8.6.1.zip"
}
module "escloud_default" {
source = "./escloud"
name = "${var.environment}-test"
...
elasticsearch_config = {
topologies = [
{
id = "hot_content"
size = var.environment == "prod" ? "2g" : "1g"
size_resource = "memory"
zone_count = var.environment == "prod" ? 2 : 1
autoscaling = {
min_size = ""
min_size_resource = ""
max_size = "116g"
max_size_resource = "memory"
}
},
]
extensions = [
{
name = ec_deployment_extension.nori.name
type = "bundle"
version = "*"
url = ec_deployment_extension.nori.url
}
]
}
...
This code does not apply existing icu plugin, just create custom bundle.
i solved it. There is config.plugins arguments.
https://registry.terraform.io/providers/elastic/ec/latest/docs/resources/ec_deployment#plugins

KMM Signing Pod Dependency for Xcode 14

I've recently updated to Xcode 14 for my KMM project and I now run into this build error when syncing gradle.
shared/build/cocoapods/synthetic/IOS/Pods/Pods.xcodeproj: error: Signing for "gRPC-C++-gRPCCertificates-Cpp" requires a development team. Select a development team in the Signing & Capabilities editor. (in target 'gRPC-C++-gRPCCertificates-Cpp' from project 'Pods')
I'm using Firebase and am including the pods as dependencies in my shared build.gradle file.
kotlin {
...
cocoapods {
...
ios.deploymentTarget = "15.0"
podfile = project.file("../iosApp/Podfile")
framework {
baseName = "shared"
}
xcodeConfigurationToNativeBuildType
val firebaseVersion = "9.6.0"
pod("FirebaseCore") { version = firebaseVersion }
pod("FirebaseAuth") { version = firebaseVersion }
pod("FirebaseFirestore") { version = firebaseVersion }
pod("FirebaseCrashlytics") { version = firebaseVersion }
pod("FirebaseAnalytics") { version = firebaseVersion }
}
...
}
I have a team setup and if I open Xcode and go to the Pods project, select gRPC-C++-gRPCCertificates-Cpp, then add my team to it, the project builds fine from Xcode.
However, this doesn't fix the gradle issue as it seems to use its own temporary project file when syncing (in shared/build/cocoapods/synthetic/IOS/Pods/Pods.xcodepro)
Is there any way to add my team to the gradle sync build?
As a temporary work around, I've switched back to Xcode 13.4.1 which doesn't have this problem.
This will be fixed in Kotlin 1.8.0 but in the meantime here is a workaround (from https://youtrack.jetbrains.com/issue/KT-54161)
First create the directories buildSrc/src/main/kotlin in the root of your project. In buildSrc create the file build.gradle.kts and add the following contents.
plugins {
`kotlin-dsl`
}
repositories {
mavenCentral()
google()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
implementation("com.android.tools.build:gradle:7.3.1")
}
Then create the file PatchedPodGenTask.kt in buildSrc/src/main/kotlin. Add the following to it.
import org.gradle.api.Project
import org.gradle.api.logging.Logger
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.*
import java.io.File
import java.io.IOException
import org.jetbrains.kotlin.konan.target.*
import org.jetbrains.kotlin.gradle.targets.native.tasks.PodGenTask
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.SpecRepos
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.CocoapodsDependency.PodLocation.*
import org.jetbrains.kotlin.gradle.plugin.cocoapods.CocoapodsExtension.CocoapodsDependency.PodLocation
import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
import kotlin.concurrent.thread
import kotlin.reflect.KClass
//import org.jetbrains.kotlin.gradle.plugin.cocoapods.cocoapodsBuildDirs
private val Family.platformLiteral: String
get() = when (this) {
Family.OSX -> "macos"
Family.IOS -> "ios"
Family.TVOS -> "tvos"
Family.WATCHOS -> "watchos"
else -> throw IllegalArgumentException("Bad family ${this.name}")
}
internal val Project.cocoapodsBuildDirs: CocoapodsBuildDirs
get() = CocoapodsBuildDirs(this)
internal class CocoapodsBuildDirs(val project: Project) {
val root: File
get() = project.buildDir.resolve("cocoapods")
val framework: File
get() = root.resolve("framework")
val defs: File
get() = root.resolve("defs")
val buildSettings: File
get() = root.resolve("buildSettings")
val synthetic: File
get() = root.resolve("synthetic")
fun synthetic(family: Family) = synthetic.resolve(family.name)
val externalSources: File
get() = root.resolve("externalSources")
val publish: File = root.resolve("publish")
fun externalSources(fileName: String) = externalSources.resolve(fileName)
fun fatFramework(buildType: NativeBuildType) =
root.resolve("fat-frameworks/${buildType.getName()}")
}
/**
* The task generates a synthetic project with all cocoapods dependencies
*/
open class PatchedPodGenTask : PodGenTask() {
private val PODFILE_SUFFIX = """
post_install do |installer|
installer.pods_project.build_configurations.each do |config|
config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
end
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
installer.generated_projects.each do |project|
project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings["DEVELOPMENT_TEAM"] = "..."
end
end
end
end
""".trimIndent()
#TaskAction
fun patchedGenerate() {
val syntheticDir = project.cocoapodsBuildDirs.synthetic(family).apply { mkdirs() }
val specRepos: Collection<String> = specReposAccessor.get().getAllAccessor()
val projResource = "/cocoapods/project.pbxproj"
val projDestination = syntheticDir.resolve("synthetic.xcodeproj").resolve("project.pbxproj")
projDestination.parentFile.mkdirs()
projDestination.outputStream().use { file ->
javaClass.getResourceAsStream(projResource).use { resource ->
resource.copyTo(file)
}
}
val podfile = syntheticDir.resolve("Podfile")
podfile.createNewFile()
val podfileContent = getPodfileContent(specRepos, family.platformLiteral) + PODFILE_SUFFIX
podfile.writeText(podfileContent)
val podInstallCommand = listOf("pod", "install")
runCommand(
podInstallCommand,
project.logger,
exceptionHandler = { e: IOException ->
CocoapodsErrorHandlingUtil.handle(e, podInstallCommand)
},
errorHandler = { retCode, output, _ ->
CocoapodsErrorHandlingUtil.handlePodInstallSyntheticError(
podInstallCommand.joinToString(" "),
retCode,
output,
family,
podNameAccessor.get()
)
},
processConfiguration = {
directory(syntheticDir)
})
val podsXcprojFile = podsXcodeProjDirAccessor.get()
check(podsXcprojFile.exists() && podsXcprojFile.isDirectory) {
"Synthetic project '${podsXcprojFile.path}' was not created."
}
}
private fun getPodfileContent(specRepos: Collection<String>, xcodeTarget: String) =
buildString {
specRepos.forEach {
appendLine("source '$it'")
}
appendLine("target '$xcodeTarget' do")
//if (useLibraries.get().not()) {
appendLine("\tuse_frameworks!")
//}
pods.get().mapNotNull {
buildString {
append("pod '${it.name}'")
val pathType = when (it.source) {
is Path -> "path"
is Url -> "path"
is Git -> "git"
else -> null
}
val path = it.source?.getLocalPathAccessor(project, it.name)
if (path != null && pathType != null) {
append(", :$pathType => '$path'")
}
}
}.forEach { appendLine("\t$it") }
appendLine("end\n")
}
}
fun <T : Any, R> KClass<T>.invokeDynamic(methodStart: String, instance: Any?, vararg params: Any?): R {
val method = this.java.methods.firstOrNull { it.name.startsWith(methodStart) } ?: error("Can't find accessor for $methodStart")
return method.invoke(instance, *params) as R
}
val PodGenTask.podsXcodeProjDirAccessor: Provider<File> get() = this::class.invokeDynamic("getPodsXcodeProjDir", this)
val PodGenTask.specReposAccessor: Provider<SpecRepos> get() = this::class.invokeDynamic("getSpecRepos", this)
val PodGenTask.podNameAccessor: Provider<String> get() = this::class.invokeDynamic("getPodName", this)
fun SpecRepos.getAllAccessor(): Collection<String> = this::class.invokeDynamic("getAll", this)
fun PodLocation.getLocalPathAccessor(project: Project, podName: String): String? = this::class.invokeDynamic("getLocalPath", this, project, podName)
private fun runCommand(
command: List<String>,
logger: Logger,
errorHandler: ((retCode: Int, output: String, process: Process) -> String?)? = null,
exceptionHandler: ((ex: IOException) -> Unit)? = null,
processConfiguration: ProcessBuilder.() -> Unit = { }
): String {
var process: Process? = null
try {
process = ProcessBuilder(command)
.apply {
this.processConfiguration()
}.start()
} catch (e: IOException) {
if (exceptionHandler != null) exceptionHandler(e) else throw e
}
if (process == null) {
throw IllegalStateException("Failed to run command ${command.joinToString(" ")}")
}
var inputText = ""
var errorText = ""
val inputThread = thread {
inputText = process.inputStream.use {
it.reader().readText()
}
}
val errorThread = thread {
errorText = process.errorStream.use {
it.reader().readText()
}
}
inputThread.join()
errorThread.join()
val retCode = process.waitFor()
logger.info(
"""
|Information about "${command.joinToString(" ")}" call:
|
|${inputText}
""".trimMargin()
)
check(retCode == 0) {
errorHandler?.invoke(retCode, inputText.ifBlank { errorText }, process)
?: """
|Executing of '${command.joinToString(" ")}' failed with code $retCode and message:
|
|$inputText
|
|$errorText
|
""".trimMargin()
}
return inputText
}
private object CocoapodsErrorHandlingUtil {
fun handle(e: IOException, command: List<String>) {
if (e.message?.contains("No such file or directory") == true) {
val message = """
|'${command.take(2).joinToString(" ")}' command failed with an exception:
| ${e.message}
|
| Full command: ${command.joinToString(" ")}
|
| Possible reason: CocoaPods is not installed
| Please check that CocoaPods v1.10 or above is installed.
|
| To check CocoaPods version type 'pod --version' in the terminal
|
| To install CocoaPods execute 'sudo gem install cocoapods'
|
""".trimMargin()
throw IllegalStateException(message)
} else {
throw e
}
}
fun handlePodInstallSyntheticError(command: String, retCode: Int, error: String, family: Family, podName: String): String? {
var message = """
|'pod install' command on the synthetic project failed with return code: $retCode
|
| Full command: $command
|
| Error: ${error.lines().filter { it.contains("[!]") }.joinToString("\n")}
|
""".trimMargin()
if (
error.contains("deployment target") ||
error.contains("no platform was specified") ||
error.contains(Regex("The platform of the target .+ is not compatible with `$podName"))
) {
message += """
|
| Possible reason: ${family.name.toLowerCase()} deployment target is not configured
| Configure deployment_target for ALL targets as follows:
| cocoapods {
| ...
| ${family.name.toLowerCase()}.deploymentTarget = "..."
| ...
| }
|
""".trimMargin()
return message
} else if (
error.contains("Unable to add a source with url") ||
error.contains("Couldn't determine repo name for URL") ||
error.contains("Unable to find a specification")
) {
message += """
|
| Possible reason: spec repos are not configured correctly.
| Ensure that spec repos are correctly configured for all private pod dependencies:
| cocoapods {
| specRepos {
| url("<private spec repo url>")
| }
| }
|
""".trimMargin()
return message
}
return null
}
}
Find the line that says config.build_settings["DEVELOPMENT_TEAM"] = "..." and replace ... with your actual dev team ID.
Finally, in the build.gradle.kts file of the module you want to apply it (mine was the shared module) add the following
// #TODO: This is a hack, and we should remove it once PodGenTask is fixed or supports adding suffixes in the official Kotlin plugin
tasks.replace("podGenIOS", PatchedPodGenTask::class.java)
Clean your project and re-sync Gradle. The patch should be applied and work with Xcode 14

create azure vm from custom image using terraform error

I need to provision a VMs in Azure from a Custom Image using Terraform, and everything works fine with image from the market place but when I try to specify a my custom image an error returns. I have been banging my head all day on this issue.
Here my tf script:
resource "azurerm_windows_virtual_machine" "tftest" {
name = "myazurevm"
location = "eastus"
resource_group_name = "myresource-rg"
network_interface_ids = [azurerm_network_interface.azvm1nic.id]
size = "Standard_B1s"
storage_image_reference {
id = "/subscriptions/xxxxxxxxxxxxxxxxxxxxxxxxxxxxx/resourceGroups/xxxxx/providers/Microsoft.Compute/images/mytemplate"
}
storage_os_disk {
name = "my-os-disk"
create_option = "FromImage"
managed_disk_type = "Premium_LRS"
}
storage_data_disk {
name = "my-data-disk"
managed_disk_type = "Premium_LRS"
disk_size_gb = 75
create_option = "FromImage"
lun = 0
}
os_profile {
computer_name = "myvmazure"
admin_username = "admin"
admin_password = "test123"
}
os_profile_windows_config {
provision_vm_agent = true
}
}
Here the error returned during plan phase:
2020-07-17T20:02:26.9367986Z ==============================================================================
2020-07-17T20:02:26.9368212Z Task : Terraform
2020-07-17T20:02:26.9368456Z Description : Execute terraform commands to manage resources on AzureRM, Amazon Web Services(AWS) and Google Cloud Platform(GCP)
2020-07-17T20:02:26.9368678Z Version : 0.0.142
2020-07-17T20:02:26.9368852Z Author : Microsoft Corporation
2020-07-17T20:02:26.9369049Z Help : [Learn more about this task](https://aka.ms/AA5j5pf)
2020-07-17T20:02:26.9369262Z ==============================================================================
2020-07-17T20:02:27.2826725Z [command]D:\agent\_work\_tool\terraform\0.12.3\x64\terraform.exe providers
2020-07-17T20:02:27.5303002Z .
2020-07-17T20:02:27.5304176Z └── provider.azurerm
2020-07-17T20:02:27.5304628Z
2020-07-17T20:02:27.5363313Z [command]D:\agent\_work\_tool\terraform\0.12.3\x64\terraform.exe plan
2020-07-17T20:02:29.7685150Z [31m
2020-07-17T20:02:29.7788471Z [1m[31mError: [0m[0m[1mInsufficient os_disk blocks[0m
2020-07-17T20:02:29.7792789Z
2020-07-17T20:02:29.7793007Z [0m on line 0:
2020-07-17T20:02:29.7793199Z (source code not available)
2020-07-17T20:02:29.7793305Z
2020-07-17T20:02:29.7793472Z At least 1 "os_disk" blocks are required.
2020-07-17T20:02:29.7793660Z [0m[0m
2020-07-17T20:02:29.7793800Z [31m
2020-07-17T20:02:29.7793975Z [1m[31mError: [0m[0m[1mMissing required argument[0m
Do you have any suggestions to locate the issue?
I have finally figured out the issue. I was using the wrong terraform resource:
wrong --> azurerm_windows_virtual_machine
correct --> azurerm_virtual_machine
azurerm_windows_virtual_machine doesn't support arguments like (storage_os_disk, storage_data_disk) and is not the right one for custom images unless the image is publish in Shared Image Gallery.
See documentation for options supported from each provider:
https://www.terraform.io/docs/providers/azurerm/r/virtual_machine.html
https://www.terraform.io/docs/providers/azurerm/r/windows_virtual_machine.html
first do it
https://learn.microsoft.com/pt-br/azure/virtual-machines/windows/upload-generalized-managed?toc=%2Fazure%2Fvirtual-machines%2Fwindows%2Ftoc.json
than my all cod
resource "azurerm_resource_group" "example" {
name = "example-resources1"
location = "West Europe"
}
resource "azurerm_virtual_network" "example" {
name = "example-network1"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_subnet" "example" {
name = "internal1"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.0.2.0/24"]
}
resource "azurerm_network_interface" "example" {
name = "example-nic1"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
ip_configuration {
name = "internal1"
subnet_id = azurerm_subnet.example.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_virtual_machine" "example" {
name = "example-machine1"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
vm_size = "Standard_B1s"
network_interface_ids = [
azurerm_network_interface.example.id,
]
storage_image_reference {
id = "/subscriptions/XXXXXXXXXXXXX/resourceGroups/ORIGEM/providers/Microsoft.Compute/images/myImage"
//just copi id from your image that you created
}
storage_os_disk {
name = "my-os-disk"
create_option = "FromImage"
managed_disk_type = "Premium_LRS"
}
os_profile {
computer_name = "myvmazure"
admin_username = "adminusername"
admin_password = "testenovo#123"
}
os_profile_windows_config {
provision_vm_agent = true
}
}
//bellow the cod to call powershell o work extension,
resource "azurerm_virtual_machine_extension" "software" {
name = "install-software"
//resource_group_name = azurerm_resource_group.example.name
virtual_machine_id = azurerm_virtual_machine.example.id
publisher = "Microsoft.Compute"
type = "CustomScriptExtension"
type_handler_version = "1.9"
protected_settings = <<SETTINGS
{
"commandToExecute": "powershell -encodedCommand ${textencodebase64(file("install.ps1"), "UTF-16LE")}"
}
SETTINGS
}
You can use a custom image with "azurerm_windows_virtual_machine" module setting "source_image_id" parameter. Documentation note that "One of either source_image_id or source_image_reference must be set." One you can use for marketplace/gallery imagens and the other for managed images.

JenkinsFile default workspace name is too long

I am currently setting up jenkins with bitbucket.
I have create a new jenkins project as multibranch project.
The JenkinsFile is hosted inside the git repository.
How can I force jenkins to generate a shorter branch name than the default one.
E:\jenkins\workspace\reposName-BrancheName-ZKIZ7BNGL6RTDKLQAQ7QR4FKZMOB3DDAVZ564BLWT2BY5ZV652VA
How can I get ride of ZKIZ7BNGL6RTDKLQAQ7QR4FKZMOB3DDAVZ564BLWT2BY5ZV652VA
This is my jenkinsFile
#!/usr/bin/env groovy
env.PATH = env.PATH + ";c:\\Windows\\System32"
def call(String label = null, Closure body) {
node(label) {
String path = pwd()
String branchName = env.BRANCH_NAME
if (branchName) {
path = path.split(Pattern.quote(File.separator))
def workspaceRoot = path[0..<-1].join(File.separator)
def currentWs = path[-1]
String newWorkspace = env.JOB_NAME.replace('/', '-')
newWorkspace = newWorkspace.replace(File.separator, '-')
newWorkspace = newWorkspace.replace('%2f', '-')
newWorkspace = newWorkspace.replace('%2F', '-')
if (currentWs =~ '#') {
newWorkspace = "${newWorkspace}#${currentWs.split('#')[-1]}"
}
path = "${workspaceRoot}${File.separator}${newWorkspace}"
}
ws(path) {
body()
}
}
}
pipeline
{
} // pipeline
Is there a way to force Jenkins to generate a shorter name?
You can change value of jenkins.branch.WorkspaceLocatorImpl.PATH_MAX=20 in jenkins's script console.
Changes will be lost if you restart jenkins server. To make the changes permanent, add this java property -Djenkins.branch.WorkspaceLocatorImpl.PATH_MAX=20
This is not the best way to fix it, but it is working :)
First create a method to get the current workspace and rework the final path like this:
def GetWorkspace()
{
node
{
String path = pwd()
String branchName = env.BRANCH_NAME
if(branchName)
{
path = path.split(Pattern.quote(File.separator))
def workspaceRoot = path[0..<-1].join(File.separator)
def currentWs = path[-1]
// Here is where we make branch names safe for directories -
// the most common bad character is '/' in 'feature/add_widget'
// which gets replaced with '%2f', so JOB_NAME will be
// ${PR}}OJECT_NAME}%2f${BRANCH_NAME}
String newWorkspace = env.JOB_NAME.replace('/', '-')
newWorkspace = newWorkspace.replace(File.separator, '-')
newWorkspace = newWorkspace.replace('%2f', '-')
newWorkspace = newWorkspace.replace('%2F', '-')
// Add on the '#n' suffix if it was there
if (currentWs =~ '#')
{
newWorkspace = "${newWorkspace}#${currentWs.split('#')[-1]}"
}
path = "E:\\Jenkins\\workspace\\${File.separator}${newWorkspace}"
}
return path
}
}
Then you have to set it up to our agent like this
pipeline {
environment {
//Your Env Setup
}
agent { //Global Agent.
node {
label 'AgentName'
customWorkspace GetWorkspace()
}
}

Unlist a package from Nuget with all it's history versions

I'm looking for a simple solution, on how to Unlist (delete) a package from Nuget library with all of it's versions.
I'm asking this, because manually I can do this 1 version at a time for 1 package. And I have lots of packages with ~20+ versions each ..
Please help.
I know this is old, but the nuget "delete" command is still not implemented, so I needed a solution. Perhaps someone can still benefit from this. I created a Command-line program and added the Nuget package Headless. Then, the code is:
class Program
{
static void Main(string[] args)
{
List<PostEntry> parameters = new List<PostEntry>();
using (var browser = new Browser())
{
var loginPage = browser.GoTo<LoginPage>();
parameters.Clear();
parameters.Add(new PostEntry("SignIn.UserNameOrEmail", "yournugetusername"));
parameters.Add(new PostEntry("SignIn.Password", "yournugetpassword"));
parameters.Add(new PostEntry("ReturnUrl", "/"));
parameters.Add(new PostEntry("LinkingAccount", "false"));
parameters.Add(new PostEntry("__RequestVerificationToken", loginPage.Find<HtmlElement>().ById("signIn").Find<HtmlInput>().ByName("__RequestVerificationToken").Value));
browser.PostTo(parameters, new Uri("https://www.nuget.org/users/account/SignIn"));
Console.WriteLine("logged in");
var cont = true;
while (cont)
{
var packagesPage = browser.GoTo<PackagesPage>();
Console.WriteLine("at packages page");
var links = packagesPage.Find<HtmlElement>()
.ById("published")
.Find<HtmlLink>()
.AllByPredicate(o => o.GetAttribute("title") == "Delete"
&& (o.Href.Contains("/IdOfPackageIWantToDelete/")
|| o.Href.Contains("/IdOfAnotherPackageIWantToDelete/")));
cont = links.Count() >= 1;
if (links.Any())
{
var htmlLink = links.First();
var linkPage = htmlLink.Href;
Console.WriteLine(linkPage);
var deletePackagePage = htmlLink.Click();
parameters.Clear();
parameters.Add(new PostEntry("Listed", "false"));
parameters.Add(new PostEntry("__RequestVerificationToken", deletePackagePage.Find<HtmlElement>().ById("body").Find<HtmlInput>().ByName("__RequestVerificationToken").Value));
browser.PostTo(parameters, new Uri("https://www.nuget.org" + linkPage));
Console.WriteLine("delete submitted");
}
}
}
Console.WriteLine("Hit any key to quit");
Console.ReadKey();
}
public class LoginPage : HtmlPage
{
public override Uri TargetLocation
{
get { return new Uri("https://www.nuget.org/users/account/LogOn?returnUrl=%2F"); }
}
}
public class PackagesPage : HtmlPage
{
public override Uri TargetLocation
{
get { return new Uri("https://www.nuget.org/account/Packages"); }
}
}
}
It will take a little while to run, but it does the trick.
You could write a batch script to call nuget delete, iterating over all your packages - see http://docs.nuget.org/docs/reference/command-line-reference#Delete_Command
e.g.
nuget delete MyPackage 1.1 -NoPrompt
nuget delete MyPackage 1.2 -NoPrompt
etc. Pretty straightforward with grep or a search/replace in a text editor.
You can do this with PowerShell, here is a function:
function Remove-AllNuGetPackageVersions($PackageId, $ApiKey)
{
$lower = $PackageId.ToLowerInvariant();
$json = Invoke-WebRequest -Uri "https://api.nuget.org/v3-flatcontainer/$lower/index.json" | ConvertFrom-Json
foreach($version in $json.versions)
{
Write-Host "Unlisting $PackageId, Ver $version"
Invoke-Expression "nuget delete $PackageId $version $ApiKey -source https://api.nuget.org/v3/index.json -NonInteractive"
}
}
If you are hosting your own nuget gallery, you could execute the following SQL query against the nuget database:
select 'nuget delete ' + pr.Id + ' ' + p.Version + ' {ApiKey} -source {Source} -noninteractive' from Packages p
join PackageRegistrations pr
on p.PackageRegistrationKey = pr.[Key]
where pr.Id = '{PackageId}' AND
p.Listed = 1
Replace {ApiKey}, {Source} and {PackageId} with your own values, I then placed the results in a batch file adjacent to nuget.exe and executed.
You can use a combination of tools by creating a simple console application.
Create a new Console application and install the package "Nuget.Core".
Add the following method to get a list of all package versions:
private static IEnumerable<IPackage> GetListedPackages(string packageID)
{
var repo = PackageRepositoryFactory.Default.CreateRepository("https://packages.nuget.org/api/v2");
var packages = from package in repo.FindPackagesById(packageID)
where package.IsListed()
select package;
return packages;
}
Then copy nuget.exe from the ".nuget" folder in one of your projects into the console application project (add it in the solution explorer and make sure that it's copied to the output directory)
Next create a new method which uses nuget.exe to unlist the package version:
private static string UnlistPackage(IPackage package, string apiKey)
{
var arguments = $"delete {package.Id} {package.Version} -ApiKey {apiKey} -NonInteractive";
var psi = new ProcessStartInfo("nuget.exe", arguments)
{
RedirectStandardOutput = true,
WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory,
UseShellExecute = false
};
var process = Process.Start(psi);
process.WaitForExit();
return process.StandardOutput.ReadToEnd();
}
Finally change Main method so it gets a list and removes all versions:
private static void Main(string[] args)
{
var packageID = "yourPackageName";
var apiKey = "yourKeyFromNugetOrg";
var packages = GetListedPackages(packageID);
foreach (var package in packages)
{
Console.WriteLine("Unlisting package " + package);
var output = UnlistPackage(package, apiKey);
Console.WriteLine(output);
}
Console.Write("Completed. Press ENTER to quit.");
Console.ReadLine();
}
source: http://blog.gauffin.org/2016/09/how-to-remove-a-package-from-nuget-org/

Resources