From c7337160cf2969e65fd85f9c41929311b8b220db Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 21:40:51 +0000 Subject: [PATCH 1/6] chore: update golang.org/x/sys to v0.38.0 --- go.mod | 2 +- go.sum | 2 + vendor/golang.org/x/sys/unix/mkerrors.sh | 2 + vendor/golang.org/x/sys/unix/syscall_linux.go | 6 + vendor/golang.org/x/sys/unix/zerrors_linux.go | 359 ++++++++++++++++++ .../golang.org/x/sys/unix/zsyscall_linux.go | 10 + vendor/golang.org/x/sys/unix/ztypes_linux.go | 31 ++ .../x/sys/windows/syscall_windows.go | 15 + .../golang.org/x/sys/windows/types_windows.go | 76 ++++ .../x/sys/windows/zsyscall_windows.go | 37 ++ vendor/modules.txt | 2 +- 11 files changed, 540 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 0b984aff..0e5dbbfb 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/zalando/go-keyring v0.2.6 go.uber.org/mock v0.6.0 go.uber.org/zap v1.27.0 - golang.org/x/sys v0.37.0 + golang.org/x/sys v0.38.0 golang.org/x/term v0.36.0 golang.org/x/text v0.30.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 3ec9fda4..a15d79d1 100644 --- a/go.sum +++ b/go.sum @@ -163,6 +163,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh index d1c8b264..42517077 100644 --- a/vendor/golang.org/x/sys/unix/mkerrors.sh +++ b/vendor/golang.org/x/sys/unix/mkerrors.sh @@ -226,6 +226,7 @@ struct ltchars { #include #include #include +#include #include #include #include @@ -529,6 +530,7 @@ ccflags="$@" $2 ~ /^O[CNPFPL][A-Z]+[^_][A-Z]+$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)DLY$/ || $2 ~ /^(NL|CR|TAB|BS|VT|FF)[0-9]$/ || + $2 ~ /^(DT|EI|ELF|EV|NN|NT|PF|SHF|SHN|SHT|STB|STT|VER)_/ || $2 ~ /^O?XTABS$/ || $2 ~ /^TC[IO](ON|OFF)$/ || $2 ~ /^IN_/ || diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 9439af96..06c0eea6 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -2643,3 +2643,9 @@ func SchedGetAttr(pid int, flags uint) (*SchedAttr, error) { //sys Cachestat(fd uint, crange *CachestatRange, cstat *Cachestat_t, flags uint) (err error) //sys Mseal(b []byte, flags uint) (err error) + +//sys setMemPolicy(mode int, mask *CPUSet, size int) (err error) = SYS_SET_MEMPOLICY + +func SetMemPolicy(mode int, mask *CPUSet) error { + return setMemPolicy(mode, mask, _CPU_SETSIZE) +} diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux.go b/vendor/golang.org/x/sys/unix/zerrors_linux.go index b6db27d9..d0a75da5 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux.go @@ -853,20 +853,86 @@ const ( DM_VERSION_MAJOR = 0x4 DM_VERSION_MINOR = 0x32 DM_VERSION_PATCHLEVEL = 0x0 + DT_ADDRRNGHI = 0x6ffffeff + DT_ADDRRNGLO = 0x6ffffe00 DT_BLK = 0x6 DT_CHR = 0x2 + DT_DEBUG = 0x15 DT_DIR = 0x4 + DT_ENCODING = 0x20 DT_FIFO = 0x1 + DT_FINI = 0xd + DT_FLAGS_1 = 0x6ffffffb + DT_GNU_HASH = 0x6ffffef5 + DT_HASH = 0x4 + DT_HIOS = 0x6ffff000 + DT_HIPROC = 0x7fffffff + DT_INIT = 0xc + DT_JMPREL = 0x17 DT_LNK = 0xa + DT_LOOS = 0x6000000d + DT_LOPROC = 0x70000000 + DT_NEEDED = 0x1 + DT_NULL = 0x0 + DT_PLTGOT = 0x3 + DT_PLTREL = 0x14 + DT_PLTRELSZ = 0x2 DT_REG = 0x8 + DT_REL = 0x11 + DT_RELA = 0x7 + DT_RELACOUNT = 0x6ffffff9 + DT_RELAENT = 0x9 + DT_RELASZ = 0x8 + DT_RELCOUNT = 0x6ffffffa + DT_RELENT = 0x13 + DT_RELSZ = 0x12 + DT_RPATH = 0xf DT_SOCK = 0xc + DT_SONAME = 0xe + DT_STRSZ = 0xa + DT_STRTAB = 0x5 + DT_SYMBOLIC = 0x10 + DT_SYMENT = 0xb + DT_SYMTAB = 0x6 + DT_TEXTREL = 0x16 DT_UNKNOWN = 0x0 + DT_VALRNGHI = 0x6ffffdff + DT_VALRNGLO = 0x6ffffd00 + DT_VERDEF = 0x6ffffffc + DT_VERDEFNUM = 0x6ffffffd + DT_VERNEED = 0x6ffffffe + DT_VERNEEDNUM = 0x6fffffff + DT_VERSYM = 0x6ffffff0 DT_WHT = 0xe ECHO = 0x8 ECRYPTFS_SUPER_MAGIC = 0xf15f EFD_SEMAPHORE = 0x1 EFIVARFS_MAGIC = 0xde5e81e4 EFS_SUPER_MAGIC = 0x414a53 + EI_CLASS = 0x4 + EI_DATA = 0x5 + EI_MAG0 = 0x0 + EI_MAG1 = 0x1 + EI_MAG2 = 0x2 + EI_MAG3 = 0x3 + EI_NIDENT = 0x10 + EI_OSABI = 0x7 + EI_PAD = 0x8 + EI_VERSION = 0x6 + ELFCLASS32 = 0x1 + ELFCLASS64 = 0x2 + ELFCLASSNONE = 0x0 + ELFCLASSNUM = 0x3 + ELFDATA2LSB = 0x1 + ELFDATA2MSB = 0x2 + ELFDATANONE = 0x0 + ELFMAG = "\177ELF" + ELFMAG0 = 0x7f + ELFMAG1 = 'E' + ELFMAG2 = 'L' + ELFMAG3 = 'F' + ELFOSABI_LINUX = 0x3 + ELFOSABI_NONE = 0x0 EM_386 = 0x3 EM_486 = 0x6 EM_68K = 0x4 @@ -1152,14 +1218,24 @@ const ( ETH_P_WCCP = 0x883e ETH_P_X25 = 0x805 ETH_P_XDSA = 0xf8 + ET_CORE = 0x4 + ET_DYN = 0x3 + ET_EXEC = 0x2 + ET_HIPROC = 0xffff + ET_LOPROC = 0xff00 + ET_NONE = 0x0 + ET_REL = 0x1 EV_ABS = 0x3 EV_CNT = 0x20 + EV_CURRENT = 0x1 EV_FF = 0x15 EV_FF_STATUS = 0x17 EV_KEY = 0x1 EV_LED = 0x11 EV_MAX = 0x1f EV_MSC = 0x4 + EV_NONE = 0x0 + EV_NUM = 0x2 EV_PWR = 0x16 EV_REL = 0x2 EV_REP = 0x14 @@ -2276,7 +2352,167 @@ const ( NLM_F_REPLACE = 0x100 NLM_F_REQUEST = 0x1 NLM_F_ROOT = 0x100 + NN_386_IOPERM = "LINUX" + NN_386_TLS = "LINUX" + NN_ARC_V2 = "LINUX" + NN_ARM_FPMR = "LINUX" + NN_ARM_GCS = "LINUX" + NN_ARM_HW_BREAK = "LINUX" + NN_ARM_HW_WATCH = "LINUX" + NN_ARM_PACA_KEYS = "LINUX" + NN_ARM_PACG_KEYS = "LINUX" + NN_ARM_PAC_ENABLED_KEYS = "LINUX" + NN_ARM_PAC_MASK = "LINUX" + NN_ARM_POE = "LINUX" + NN_ARM_SSVE = "LINUX" + NN_ARM_SVE = "LINUX" + NN_ARM_SYSTEM_CALL = "LINUX" + NN_ARM_TAGGED_ADDR_CTRL = "LINUX" + NN_ARM_TLS = "LINUX" + NN_ARM_VFP = "LINUX" + NN_ARM_ZA = "LINUX" + NN_ARM_ZT = "LINUX" + NN_AUXV = "CORE" + NN_FILE = "CORE" + NN_GNU_PROPERTY_TYPE_0 = "GNU" + NN_LOONGARCH_CPUCFG = "LINUX" + NN_LOONGARCH_CSR = "LINUX" + NN_LOONGARCH_HW_BREAK = "LINUX" + NN_LOONGARCH_HW_WATCH = "LINUX" + NN_LOONGARCH_LASX = "LINUX" + NN_LOONGARCH_LBT = "LINUX" + NN_LOONGARCH_LSX = "LINUX" + NN_MIPS_DSP = "LINUX" + NN_MIPS_FP_MODE = "LINUX" + NN_MIPS_MSA = "LINUX" + NN_PPC_DEXCR = "LINUX" + NN_PPC_DSCR = "LINUX" + NN_PPC_EBB = "LINUX" + NN_PPC_HASHKEYR = "LINUX" + NN_PPC_PKEY = "LINUX" + NN_PPC_PMU = "LINUX" + NN_PPC_PPR = "LINUX" + NN_PPC_SPE = "LINUX" + NN_PPC_TAR = "LINUX" + NN_PPC_TM_CDSCR = "LINUX" + NN_PPC_TM_CFPR = "LINUX" + NN_PPC_TM_CGPR = "LINUX" + NN_PPC_TM_CPPR = "LINUX" + NN_PPC_TM_CTAR = "LINUX" + NN_PPC_TM_CVMX = "LINUX" + NN_PPC_TM_CVSX = "LINUX" + NN_PPC_TM_SPR = "LINUX" + NN_PPC_VMX = "LINUX" + NN_PPC_VSX = "LINUX" + NN_PRFPREG = "CORE" + NN_PRPSINFO = "CORE" + NN_PRSTATUS = "CORE" + NN_PRXFPREG = "LINUX" + NN_RISCV_CSR = "LINUX" + NN_RISCV_TAGGED_ADDR_CTRL = "LINUX" + NN_RISCV_VECTOR = "LINUX" + NN_S390_CTRS = "LINUX" + NN_S390_GS_BC = "LINUX" + NN_S390_GS_CB = "LINUX" + NN_S390_HIGH_GPRS = "LINUX" + NN_S390_LAST_BREAK = "LINUX" + NN_S390_PREFIX = "LINUX" + NN_S390_PV_CPU_DATA = "LINUX" + NN_S390_RI_CB = "LINUX" + NN_S390_SYSTEM_CALL = "LINUX" + NN_S390_TDB = "LINUX" + NN_S390_TIMER = "LINUX" + NN_S390_TODCMP = "LINUX" + NN_S390_TODPREG = "LINUX" + NN_S390_VXRS_HIGH = "LINUX" + NN_S390_VXRS_LOW = "LINUX" + NN_SIGINFO = "CORE" + NN_TASKSTRUCT = "CORE" + NN_VMCOREDD = "LINUX" + NN_X86_SHSTK = "LINUX" + NN_X86_XSAVE_LAYOUT = "LINUX" + NN_X86_XSTATE = "LINUX" NSFS_MAGIC = 0x6e736673 + NT_386_IOPERM = 0x201 + NT_386_TLS = 0x200 + NT_ARC_V2 = 0x600 + NT_ARM_FPMR = 0x40e + NT_ARM_GCS = 0x410 + NT_ARM_HW_BREAK = 0x402 + NT_ARM_HW_WATCH = 0x403 + NT_ARM_PACA_KEYS = 0x407 + NT_ARM_PACG_KEYS = 0x408 + NT_ARM_PAC_ENABLED_KEYS = 0x40a + NT_ARM_PAC_MASK = 0x406 + NT_ARM_POE = 0x40f + NT_ARM_SSVE = 0x40b + NT_ARM_SVE = 0x405 + NT_ARM_SYSTEM_CALL = 0x404 + NT_ARM_TAGGED_ADDR_CTRL = 0x409 + NT_ARM_TLS = 0x401 + NT_ARM_VFP = 0x400 + NT_ARM_ZA = 0x40c + NT_ARM_ZT = 0x40d + NT_AUXV = 0x6 + NT_FILE = 0x46494c45 + NT_GNU_PROPERTY_TYPE_0 = 0x5 + NT_LOONGARCH_CPUCFG = 0xa00 + NT_LOONGARCH_CSR = 0xa01 + NT_LOONGARCH_HW_BREAK = 0xa05 + NT_LOONGARCH_HW_WATCH = 0xa06 + NT_LOONGARCH_LASX = 0xa03 + NT_LOONGARCH_LBT = 0xa04 + NT_LOONGARCH_LSX = 0xa02 + NT_MIPS_DSP = 0x800 + NT_MIPS_FP_MODE = 0x801 + NT_MIPS_MSA = 0x802 + NT_PPC_DEXCR = 0x111 + NT_PPC_DSCR = 0x105 + NT_PPC_EBB = 0x106 + NT_PPC_HASHKEYR = 0x112 + NT_PPC_PKEY = 0x110 + NT_PPC_PMU = 0x107 + NT_PPC_PPR = 0x104 + NT_PPC_SPE = 0x101 + NT_PPC_TAR = 0x103 + NT_PPC_TM_CDSCR = 0x10f + NT_PPC_TM_CFPR = 0x109 + NT_PPC_TM_CGPR = 0x108 + NT_PPC_TM_CPPR = 0x10e + NT_PPC_TM_CTAR = 0x10d + NT_PPC_TM_CVMX = 0x10a + NT_PPC_TM_CVSX = 0x10b + NT_PPC_TM_SPR = 0x10c + NT_PPC_VMX = 0x100 + NT_PPC_VSX = 0x102 + NT_PRFPREG = 0x2 + NT_PRPSINFO = 0x3 + NT_PRSTATUS = 0x1 + NT_PRXFPREG = 0x46e62b7f + NT_RISCV_CSR = 0x900 + NT_RISCV_TAGGED_ADDR_CTRL = 0x902 + NT_RISCV_VECTOR = 0x901 + NT_S390_CTRS = 0x304 + NT_S390_GS_BC = 0x30c + NT_S390_GS_CB = 0x30b + NT_S390_HIGH_GPRS = 0x300 + NT_S390_LAST_BREAK = 0x306 + NT_S390_PREFIX = 0x305 + NT_S390_PV_CPU_DATA = 0x30e + NT_S390_RI_CB = 0x30d + NT_S390_SYSTEM_CALL = 0x307 + NT_S390_TDB = 0x308 + NT_S390_TIMER = 0x301 + NT_S390_TODCMP = 0x302 + NT_S390_TODPREG = 0x303 + NT_S390_VXRS_HIGH = 0x30a + NT_S390_VXRS_LOW = 0x309 + NT_SIGINFO = 0x53494749 + NT_TASKSTRUCT = 0x4 + NT_VMCOREDD = 0x700 + NT_X86_SHSTK = 0x204 + NT_X86_XSAVE_LAYOUT = 0x205 + NT_X86_XSTATE = 0x202 OCFS2_SUPER_MAGIC = 0x7461636f OCRNL = 0x8 OFDEL = 0x80 @@ -2463,6 +2699,59 @@ const ( PERF_RECORD_MISC_USER = 0x2 PERF_SAMPLE_BRANCH_PLM_ALL = 0x7 PERF_SAMPLE_WEIGHT_TYPE = 0x1004000 + PF_ALG = 0x26 + PF_APPLETALK = 0x5 + PF_ASH = 0x12 + PF_ATMPVC = 0x8 + PF_ATMSVC = 0x14 + PF_AX25 = 0x3 + PF_BLUETOOTH = 0x1f + PF_BRIDGE = 0x7 + PF_CAIF = 0x25 + PF_CAN = 0x1d + PF_DECnet = 0xc + PF_ECONET = 0x13 + PF_FILE = 0x1 + PF_IB = 0x1b + PF_IEEE802154 = 0x24 + PF_INET = 0x2 + PF_INET6 = 0xa + PF_IPX = 0x4 + PF_IRDA = 0x17 + PF_ISDN = 0x22 + PF_IUCV = 0x20 + PF_KCM = 0x29 + PF_KEY = 0xf + PF_LLC = 0x1a + PF_LOCAL = 0x1 + PF_MAX = 0x2e + PF_MCTP = 0x2d + PF_MPLS = 0x1c + PF_NETBEUI = 0xd + PF_NETLINK = 0x10 + PF_NETROM = 0x6 + PF_NFC = 0x27 + PF_PACKET = 0x11 + PF_PHONET = 0x23 + PF_PPPOX = 0x18 + PF_QIPCRTR = 0x2a + PF_R = 0x4 + PF_RDS = 0x15 + PF_ROSE = 0xb + PF_ROUTE = 0x10 + PF_RXRPC = 0x21 + PF_SECURITY = 0xe + PF_SMC = 0x2b + PF_SNA = 0x16 + PF_TIPC = 0x1e + PF_UNIX = 0x1 + PF_UNSPEC = 0x0 + PF_VSOCK = 0x28 + PF_W = 0x2 + PF_WANPIPE = 0x19 + PF_X = 0x1 + PF_X25 = 0x9 + PF_XDP = 0x2c PID_FS_MAGIC = 0x50494446 PIPEFS_MAGIC = 0x50495045 PPPIOCGNPMODE = 0xc008744c @@ -2758,6 +3047,23 @@ const ( PTRACE_SYSCALL_INFO_NONE = 0x0 PTRACE_SYSCALL_INFO_SECCOMP = 0x3 PTRACE_TRACEME = 0x0 + PT_AARCH64_MEMTAG_MTE = 0x70000002 + PT_DYNAMIC = 0x2 + PT_GNU_EH_FRAME = 0x6474e550 + PT_GNU_PROPERTY = 0x6474e553 + PT_GNU_RELRO = 0x6474e552 + PT_GNU_STACK = 0x6474e551 + PT_HIOS = 0x6fffffff + PT_HIPROC = 0x7fffffff + PT_INTERP = 0x3 + PT_LOAD = 0x1 + PT_LOOS = 0x60000000 + PT_LOPROC = 0x70000000 + PT_NOTE = 0x4 + PT_NULL = 0x0 + PT_PHDR = 0x6 + PT_SHLIB = 0x5 + PT_TLS = 0x7 P_ALL = 0x0 P_PGID = 0x2 P_PID = 0x1 @@ -3091,6 +3397,47 @@ const ( SEEK_MAX = 0x4 SEEK_SET = 0x0 SELINUX_MAGIC = 0xf97cff8c + SHF_ALLOC = 0x2 + SHF_EXCLUDE = 0x8000000 + SHF_EXECINSTR = 0x4 + SHF_GROUP = 0x200 + SHF_INFO_LINK = 0x40 + SHF_LINK_ORDER = 0x80 + SHF_MASKOS = 0xff00000 + SHF_MASKPROC = 0xf0000000 + SHF_MERGE = 0x10 + SHF_ORDERED = 0x4000000 + SHF_OS_NONCONFORMING = 0x100 + SHF_RELA_LIVEPATCH = 0x100000 + SHF_RO_AFTER_INIT = 0x200000 + SHF_STRINGS = 0x20 + SHF_TLS = 0x400 + SHF_WRITE = 0x1 + SHN_ABS = 0xfff1 + SHN_COMMON = 0xfff2 + SHN_HIPROC = 0xff1f + SHN_HIRESERVE = 0xffff + SHN_LIVEPATCH = 0xff20 + SHN_LOPROC = 0xff00 + SHN_LORESERVE = 0xff00 + SHN_UNDEF = 0x0 + SHT_DYNAMIC = 0x6 + SHT_DYNSYM = 0xb + SHT_HASH = 0x5 + SHT_HIPROC = 0x7fffffff + SHT_HIUSER = 0xffffffff + SHT_LOPROC = 0x70000000 + SHT_LOUSER = 0x80000000 + SHT_NOBITS = 0x8 + SHT_NOTE = 0x7 + SHT_NULL = 0x0 + SHT_NUM = 0xc + SHT_PROGBITS = 0x1 + SHT_REL = 0x9 + SHT_RELA = 0x4 + SHT_SHLIB = 0xa + SHT_STRTAB = 0x3 + SHT_SYMTAB = 0x2 SHUT_RD = 0x0 SHUT_RDWR = 0x2 SHUT_WR = 0x1 @@ -3317,6 +3664,16 @@ const ( STATX_UID = 0x8 STATX_WRITE_ATOMIC = 0x10000 STATX__RESERVED = 0x80000000 + STB_GLOBAL = 0x1 + STB_LOCAL = 0x0 + STB_WEAK = 0x2 + STT_COMMON = 0x5 + STT_FILE = 0x4 + STT_FUNC = 0x2 + STT_NOTYPE = 0x0 + STT_OBJECT = 0x1 + STT_SECTION = 0x3 + STT_TLS = 0x6 SYNC_FILE_RANGE_WAIT_AFTER = 0x4 SYNC_FILE_RANGE_WAIT_BEFORE = 0x1 SYNC_FILE_RANGE_WRITE = 0x2 @@ -3553,6 +3910,8 @@ const ( UTIME_OMIT = 0x3ffffffe V9FS_MAGIC = 0x1021997 VERASE = 0x2 + VER_FLG_BASE = 0x1 + VER_FLG_WEAK = 0x2 VINTR = 0x0 VKILL = 0x3 VLNEXT = 0xf diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/vendor/golang.org/x/sys/unix/zsyscall_linux.go index 5cc1e8eb..8935d10a 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux.go @@ -2238,3 +2238,13 @@ func Mseal(b []byte, flags uint) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func setMemPolicy(mode int, mask *CPUSet, size int) (err error) { + _, _, e1 := Syscall(SYS_SET_MEMPOLICY, uintptr(mode), uintptr(unsafe.Pointer(mask)), uintptr(size)) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go index 944e75a1..c1a46701 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go @@ -3590,6 +3590,8 @@ type Nhmsg struct { Flags uint32 } +const SizeofNhmsg = 0x8 + type NexthopGrp struct { Id uint32 Weight uint8 @@ -3597,6 +3599,8 @@ type NexthopGrp struct { Resvd2 uint16 } +const SizeofNexthopGrp = 0x8 + const ( NHA_UNSPEC = 0x0 NHA_ID = 0x1 @@ -6332,3 +6336,30 @@ type SockDiagReq struct { } const RTM_NEWNVLAN = 0x70 + +const ( + MPOL_BIND = 0x2 + MPOL_DEFAULT = 0x0 + MPOL_F_ADDR = 0x2 + MPOL_F_MEMS_ALLOWED = 0x4 + MPOL_F_MOF = 0x8 + MPOL_F_MORON = 0x10 + MPOL_F_NODE = 0x1 + MPOL_F_NUMA_BALANCING = 0x2000 + MPOL_F_RELATIVE_NODES = 0x4000 + MPOL_F_SHARED = 0x1 + MPOL_F_STATIC_NODES = 0x8000 + MPOL_INTERLEAVE = 0x3 + MPOL_LOCAL = 0x4 + MPOL_MAX = 0x7 + MPOL_MF_INTERNAL = 0x10 + MPOL_MF_LAZY = 0x8 + MPOL_MF_MOVE_ALL = 0x4 + MPOL_MF_MOVE = 0x2 + MPOL_MF_STRICT = 0x1 + MPOL_MF_VALID = 0x7 + MPOL_MODE_FLAGS = 0xe000 + MPOL_PREFERRED = 0x1 + MPOL_PREFERRED_MANY = 0x5 + MPOL_WEIGHTED_INTERLEAVE = 0x6 +) diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go index bd513373..69439df2 100644 --- a/vendor/golang.org/x/sys/windows/syscall_windows.go +++ b/vendor/golang.org/x/sys/windows/syscall_windows.go @@ -892,8 +892,12 @@ const socket_error = uintptr(^uint32(0)) //sys MultiByteToWideChar(codePage uint32, dwFlags uint32, str *byte, nstr int32, wchar *uint16, nwchar int32) (nwrite int32, err error) = kernel32.MultiByteToWideChar //sys getBestInterfaceEx(sockaddr unsafe.Pointer, pdwBestIfIndex *uint32) (errcode error) = iphlpapi.GetBestInterfaceEx //sys GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) = iphlpapi.GetIfEntry2Ex +//sys GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) = iphlpapi.GetIpForwardEntry2 +//sys GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) = iphlpapi.GetIpForwardTable2 //sys GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) = iphlpapi.GetUnicastIpAddressEntry +//sys FreeMibTable(memory unsafe.Pointer) = iphlpapi.FreeMibTable //sys NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyIpInterfaceChange +//sys NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyRouteChange2 //sys NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) = iphlpapi.NotifyUnicastIpAddressChange //sys CancelMibChangeNotify2(notificationHandle Handle) (errcode error) = iphlpapi.CancelMibChangeNotify2 @@ -916,6 +920,17 @@ type RawSockaddrInet6 struct { Scope_id uint32 } +// RawSockaddrInet is a union that contains an IPv4, an IPv6 address, or an address family. See +// https://learn.microsoft.com/en-us/windows/win32/api/ws2ipdef/ns-ws2ipdef-sockaddr_inet. +// +// A [*RawSockaddrInet] may be converted to a [*RawSockaddrInet4] or [*RawSockaddrInet6] using +// unsafe, depending on the address family. +type RawSockaddrInet struct { + Family uint16 + Port uint16 + Data [6]uint32 +} + type RawSockaddr struct { Family uint16 Data [14]int8 diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go index 358be3c7..6e4f50eb 100644 --- a/vendor/golang.org/x/sys/windows/types_windows.go +++ b/vendor/golang.org/x/sys/windows/types_windows.go @@ -2320,6 +2320,82 @@ type MibIfRow2 struct { OutQLen uint64 } +// IP_ADDRESS_PREFIX stores an IP address prefix. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-ip_address_prefix. +type IpAddressPrefix struct { + Prefix RawSockaddrInet + PrefixLength uint8 +} + +// NL_ROUTE_ORIGIN enumeration from nldef.h or +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_origin. +const ( + NlroManual = 0 + NlroWellKnown = 1 + NlroDHCP = 2 + NlroRouterAdvertisement = 3 + Nlro6to4 = 4 +) + +// NL_ROUTE_ORIGIN enumeration from nldef.h or +// https://learn.microsoft.com/en-us/windows/win32/api/nldef/ne-nldef-nl_route_protocol. +const ( + MIB_IPPROTO_OTHER = 1 + MIB_IPPROTO_LOCAL = 2 + MIB_IPPROTO_NETMGMT = 3 + MIB_IPPROTO_ICMP = 4 + MIB_IPPROTO_EGP = 5 + MIB_IPPROTO_GGP = 6 + MIB_IPPROTO_HELLO = 7 + MIB_IPPROTO_RIP = 8 + MIB_IPPROTO_IS_IS = 9 + MIB_IPPROTO_ES_IS = 10 + MIB_IPPROTO_CISCO = 11 + MIB_IPPROTO_BBN = 12 + MIB_IPPROTO_OSPF = 13 + MIB_IPPROTO_BGP = 14 + MIB_IPPROTO_IDPR = 15 + MIB_IPPROTO_EIGRP = 16 + MIB_IPPROTO_DVMRP = 17 + MIB_IPPROTO_RPL = 18 + MIB_IPPROTO_DHCP = 19 + MIB_IPPROTO_NT_AUTOSTATIC = 10002 + MIB_IPPROTO_NT_STATIC = 10006 + MIB_IPPROTO_NT_STATIC_NON_DOD = 10007 +) + +// MIB_IPFORWARD_ROW2 stores information about an IP route entry. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_row2. +type MibIpForwardRow2 struct { + InterfaceLuid uint64 + InterfaceIndex uint32 + DestinationPrefix IpAddressPrefix + NextHop RawSockaddrInet + SitePrefixLength uint8 + ValidLifetime uint32 + PreferredLifetime uint32 + Metric uint32 + Protocol uint32 + Loopback uint8 + AutoconfigureAddress uint8 + Publish uint8 + Immortal uint8 + Age uint32 + Origin uint32 +} + +// MIB_IPFORWARD_TABLE2 contains a table of IP route entries. See +// https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_ipforward_table2. +type MibIpForwardTable2 struct { + NumEntries uint32 + Table [1]MibIpForwardRow2 +} + +// Rows returns the IP route entries in the table. +func (t *MibIpForwardTable2) Rows() []MibIpForwardRow2 { + return unsafe.Slice(&t.Table[0], t.NumEntries) +} + // MIB_UNICASTIPADDRESS_ROW stores information about a unicast IP address. See // https://learn.microsoft.com/en-us/windows/win32/api/netioapi/ns-netioapi-mib_unicastipaddress_row. type MibUnicastIpAddressRow struct { diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 426151a0..f25b7308 100644 --- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -182,13 +182,17 @@ var ( procDwmGetWindowAttribute = moddwmapi.NewProc("DwmGetWindowAttribute") procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute") procCancelMibChangeNotify2 = modiphlpapi.NewProc("CancelMibChangeNotify2") + procFreeMibTable = modiphlpapi.NewProc("FreeMibTable") procGetAdaptersAddresses = modiphlpapi.NewProc("GetAdaptersAddresses") procGetAdaptersInfo = modiphlpapi.NewProc("GetAdaptersInfo") procGetBestInterfaceEx = modiphlpapi.NewProc("GetBestInterfaceEx") procGetIfEntry = modiphlpapi.NewProc("GetIfEntry") procGetIfEntry2Ex = modiphlpapi.NewProc("GetIfEntry2Ex") + procGetIpForwardEntry2 = modiphlpapi.NewProc("GetIpForwardEntry2") + procGetIpForwardTable2 = modiphlpapi.NewProc("GetIpForwardTable2") procGetUnicastIpAddressEntry = modiphlpapi.NewProc("GetUnicastIpAddressEntry") procNotifyIpInterfaceChange = modiphlpapi.NewProc("NotifyIpInterfaceChange") + procNotifyRouteChange2 = modiphlpapi.NewProc("NotifyRouteChange2") procNotifyUnicastIpAddressChange = modiphlpapi.NewProc("NotifyUnicastIpAddressChange") procAddDllDirectory = modkernel32.NewProc("AddDllDirectory") procAssignProcessToJobObject = modkernel32.NewProc("AssignProcessToJobObject") @@ -1624,6 +1628,11 @@ func CancelMibChangeNotify2(notificationHandle Handle) (errcode error) { return } +func FreeMibTable(memory unsafe.Pointer) { + syscall.SyscallN(procFreeMibTable.Addr(), uintptr(memory)) + return +} + func GetAdaptersAddresses(family uint32, flags uint32, reserved uintptr, adapterAddresses *IpAdapterAddresses, sizePointer *uint32) (errcode error) { r0, _, _ := syscall.SyscallN(procGetAdaptersAddresses.Addr(), uintptr(family), uintptr(flags), uintptr(reserved), uintptr(unsafe.Pointer(adapterAddresses)), uintptr(unsafe.Pointer(sizePointer))) if r0 != 0 { @@ -1664,6 +1673,22 @@ func GetIfEntry2Ex(level uint32, row *MibIfRow2) (errcode error) { return } +func GetIpForwardEntry2(row *MibIpForwardRow2) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetIpForwardEntry2.Addr(), uintptr(unsafe.Pointer(row))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + +func GetIpForwardTable2(family uint16, table **MibIpForwardTable2) (errcode error) { + r0, _, _ := syscall.SyscallN(procGetIpForwardTable2.Addr(), uintptr(family), uintptr(unsafe.Pointer(table))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func GetUnicastIpAddressEntry(row *MibUnicastIpAddressRow) (errcode error) { r0, _, _ := syscall.SyscallN(procGetUnicastIpAddressEntry.Addr(), uintptr(unsafe.Pointer(row))) if r0 != 0 { @@ -1684,6 +1709,18 @@ func NotifyIpInterfaceChange(family uint16, callback uintptr, callerContext unsa return } +func NotifyRouteChange2(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { + var _p0 uint32 + if initialNotification { + _p0 = 1 + } + r0, _, _ := syscall.SyscallN(procNotifyRouteChange2.Addr(), uintptr(family), uintptr(callback), uintptr(callerContext), uintptr(_p0), uintptr(unsafe.Pointer(notificationHandle))) + if r0 != 0 { + errcode = syscall.Errno(r0) + } + return +} + func NotifyUnicastIpAddressChange(family uint16, callback uintptr, callerContext unsafe.Pointer, initialNotification bool, notificationHandle *Handle) (errcode error) { var _p0 uint32 if initialNotification { diff --git a/vendor/modules.txt b/vendor/modules.txt index 3e20ace3..52e8d9a0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -236,7 +236,7 @@ go.uber.org/zap/zapcore golang.org/x/net/html golang.org/x/net/html/atom golang.org/x/net/idna -# golang.org/x/sys v0.37.0 +# golang.org/x/sys v0.38.0 ## explicit; go 1.24.0 golang.org/x/sys/plan9 golang.org/x/sys/unix From 1f2691e737520163211c6f88e634a803d6dbb070 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 22:09:36 +0000 Subject: [PATCH 2/6] feat: add classification path helpers Add NormalizeClassificationPath and BuildClassificationPath utilities for normalizing and preparing classification node paths used by Azure DevOps endpoints. --- internal/cmd/boards/shared/path.go | 107 ++++++++++++++++++++++++ internal/cmd/boards/shared/path_test.go | 92 ++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 internal/cmd/boards/shared/path.go create mode 100644 internal/cmd/boards/shared/path_test.go diff --git a/internal/cmd/boards/shared/path.go b/internal/cmd/boards/shared/path.go new file mode 100644 index 00000000..b3bf403e --- /dev/null +++ b/internal/cmd/boards/shared/path.go @@ -0,0 +1,107 @@ +package shared + +import ( + "net/url" + "regexp" + "strings" +) + +// collapseMultipleSlashes replaces consecutive slashes with a single slash. +var multipleSlashes = regexp.MustCompile(`/+`) + +// NormalizeClassificationPath normalizes classification node paths. +// +// Behavior: +// - If raw is empty or only whitespace/slashes, returns an empty string. +// - Converts backslashes to forward slashes. +// - Trims surrounding whitespace. +// - Collapses consecutive slashes (e.g. "a//b" -> "a/b"). +// - Removes any leading and trailing slashes. +// Examples: +// +// NormalizeClassificationPath(" \\Project\\Area\\Foo\\ ") -> "Project/Area/Foo" +// NormalizeClassificationPath("/a//b/") -> "a/b" +func NormalizeClassificationPath(raw string) string { + raw = strings.TrimSpace(raw) + if raw == "" { + return "" + } + + // Normalize separators + s := strings.ReplaceAll(raw, "\\", "/") + + // Collapse repeated slashes + s = multipleSlashes.ReplaceAllString(s, "/") + + // Trim leading/trailing slashes and surrounding whitespace + s = strings.Trim(s, "/") + s = strings.TrimSpace(s) + + return s +} + +// BuildClassificationPath prepares the path segment for Azure DevOps REST endpoints. +// +// Rules and validations: +// - Accepts user input with either forward or backward slashes. +// - Uses the same normalization rules as NormalizeClassificationPath. +// - If the trimmed input is empty, returns ("", nil) to indicate "no path" (keeps existing callers behavior). +// - Removes a leading project segment (case-insensitive) if present. +// - If includesScope is true, removes a leading scopeName segment (case-insensitive) if present after project removal. +// - Rejects input that would produce empty segments (e.g., "a//b" after normalization should not happen because we collapse slashes). +// - Trims whitespace around each segment. +// - URL-escapes each segment with url.PathEscape and joins with forward slashes. +func BuildClassificationPath(project string, includesScope bool, scopeName string, raw string) (string, error) { + trimmed := strings.TrimSpace(raw) + if trimmed == "" { + // No path provided; caller semantics: return empty path without error. + return "", nil + } + + normalized := NormalizeClassificationPath(trimmed) + if normalized == "" { + // Input had only slashes/whitespace. + return "", nil + } + + segments := strings.Split(normalized, "/") + + // Remove leading project segment if present (case-insensitive) + if len(segments) > 0 && project != "" && strings.EqualFold(segments[0], project) { + segments = segments[1:] + } + + // Remove leading scope segment if requested + if includesScope && len(segments) > 0 && scopeName != "" && strings.EqualFold(segments[0], scopeName) { + segments = segments[1:] + } + + if len(segments) == 0 { + // After removing project/scope there is no path left → treat as no path + return "", nil + } + + // Filter out and skip empty (space-only) segments that may appear between separators, + // e.g. "SP4DB/Area/ / /WKB" -> ["SP4DB","Area","","","WKB"] -> skip empties -> ["SP4DB","Area","WKB"] + filtered := make([]string, 0, len(segments)) + for _, seg := range segments { + seg = strings.TrimSpace(seg) + if seg == "" { + // Skip segments that are only whitespace. + continue + } + filtered = append(filtered, seg) + } + + if len(filtered) == 0 { + // Nothing meaningful left after filtering + return "", nil + } + + escaped := make([]string, 0, len(filtered)) + for _, seg := range filtered { + escaped = append(escaped, url.PathEscape(seg)) + } + + return strings.Join(escaped, "/"), nil +} diff --git a/internal/cmd/boards/shared/path_test.go b/internal/cmd/boards/shared/path_test.go new file mode 100644 index 00000000..d63d89a3 --- /dev/null +++ b/internal/cmd/boards/shared/path_test.go @@ -0,0 +1,92 @@ +package shared + +import ( + "testing" +) + +func TestNormalizeClassificationPath(t *testing.T) { + tests := []struct { + name string + in string + out string + }{ + {"empty", "", ""}, + {"spaces only", " ", ""}, + {"backslashes", `\Project\Area\Foo\`, "Project/Area/Foo"}, + {"leading/trailing slashes", "/a/b/c/", "a/b/c"}, + {"consecutive slashes", "a//b///c", "a/b/c"}, + {"mixed separators and spaces", ` \A//B\C/ `, "A/B/C"}, + {"only slashes", "///\\\\///", ""}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := NormalizeClassificationPath(tt.in) + if got != tt.out { + t.Fatalf("NormalizeClassificationPath(%q) = %q, want %q", tt.in, got, tt.out) + } + }) + } +} + +func TestBuildClassificationPath(t *testing.T) { + type args struct { + project string + includesScope bool + scopeName string + raw string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + "empty returns empty", args{ + "proj", false, "", "", + }, "", false, + }, + {"only slashes returns empty", args{ + "proj", false, "", "////", + }, "", false}, + {"simple path", args{ + "proj", false, "", "area/sub", + }, "area/sub", false}, + {"backslashes and spaces", args{ + "proj", false, "", `\Area \Sub `, + }, "Area/Sub", false}, + {"collapse slashes", args{ + "proj", false, "", "a//b///c", + }, "a/b/c", false}, + {"leading project removed", args{ + "MyProj", false, "", "MyProj/Area/Child", + }, "Area/Child", false}, + {"leading project removed case-insensitive", args{ + "myproj", false, "", "MYPROJ/Area", + }, "Area", false}, + {"remove scope when requested", args{ + "proj", true, "Area", "proj/Area/Sub", + }, "Sub", false}, + {"remove scope case-insensitive", args{ + "proj", true, "Area", "proj/area/Sub", + }, "Sub", false}, + {"segment with reserved chars escaped", args{ + "proj", false, "", "a/b c/d?e", + }, "a/b%20c/d%3Fe", false}, + // New test: handle space-only segments by skipping them. + {"skip space-only segments and return last meaningful segment", args{ + "SP4DB", true, "Area", "SP4DB/Area/ / /WKB", + }, "WKB", false}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := BuildClassificationPath(tt.args.project, tt.args.includesScope, tt.args.scopeName, tt.args.raw) + if (err != nil) != tt.wantErr { + t.Fatalf("BuildClassificationPath() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Fatalf("BuildClassificationPath() = %q, want %q (err=%v)", got, tt.want, err) + } + }) + } +} From 868f1681e84a314e52594cf6b2e357a9028f9028 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 22:11:02 +0000 Subject: [PATCH 3/6] feat(boards): add boards area project list command Add a new CLI command to list Azure Boards area paths for a project. The command supports organization/project scoping, optional path restriction, depth control for child nodes, and JSON export.This enables users to conveniently list and inspect area paths from the CLI for various automation and inspection workflows. --- internal/cmd/boards/area/area.go | 27 ++ internal/cmd/boards/area/project/list/list.go | 278 ++++++++++++++++++ internal/cmd/boards/area/project/project.go | 28 ++ internal/cmd/boards/boards.go | 28 ++ internal/cmd/root/root.go | 2 + 5 files changed, 363 insertions(+) create mode 100644 internal/cmd/boards/area/area.go create mode 100644 internal/cmd/boards/area/project/list/list.go create mode 100644 internal/cmd/boards/area/project/project.go create mode 100644 internal/cmd/boards/boards.go diff --git a/internal/cmd/boards/area/area.go b/internal/cmd/boards/area/area.go new file mode 100644 index 00000000..d1633b99 --- /dev/null +++ b/internal/cmd/boards/area/area.go @@ -0,0 +1,27 @@ +package area + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" + projectcmd "github.com/tmeckel/azdo-cli/internal/cmd/boards/area/project" + "github.com/tmeckel/azdo-cli/internal/cmd/util" +) + +// NewCmd wires subcommands for managing area paths. +func NewCmd(ctx util.CmdContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "area ", + Short: "Manage area paths used by Azure Boards.", + Example: heredoc.Doc(` + # List the area paths for a project + azdo boards area project list Fabrikam + `), + Aliases: []string{ + "a", + }, + } + + cmd.AddCommand(projectcmd.NewCmd(ctx)) + + return cmd +} diff --git a/internal/cmd/boards/area/project/list/list.go b/internal/cmd/boards/area/project/list/list.go new file mode 100644 index 00000000..6942cd94 --- /dev/null +++ b/internal/cmd/boards/area/project/list/list.go @@ -0,0 +1,278 @@ +package list + +import ( + "fmt" + "net/http" + "net/url" + "sort" + "strconv" + "strings" + + "github.com/MakeNowJust/heredoc" + "github.com/microsoft/azure-devops-go-api/azuredevops/v7" + "github.com/spf13/cobra" + "go.uber.org/zap" + + "github.com/tmeckel/azdo-cli/internal/cmd/boards/shared" + "github.com/tmeckel/azdo-cli/internal/cmd/util" + "github.com/tmeckel/azdo-cli/internal/types" +) + +type listOptions struct { + scopeArg string + path string + depth int + exporter util.Exporter +} + +type workItemClassificationNode struct { + ID *int `json:"id,omitempty"` + Identifier *string `json:"identifier,omitempty"` + Name *string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` + Structure *string `json:"structureType,omitempty"` + HasChildren *bool `json:"hasChildren,omitempty"` + Children []workItemClassificationNode `json:"children,omitempty"` + Attributes map[string]any `json:"attributes,omitempty"` +} + +type areaNode struct { + ID int `json:"id"` + Identifier string `json:"identifier,omitempty"` + Name string `json:"name"` + Path string `json:"path"` + HasChildren bool `json:"hasChildren"` + ParentPath string `json:"parentPath,omitempty"` +} + +func NewCmd(ctx util.CmdContext) *cobra.Command { + opts := &listOptions{ + depth: 1, + } + + cmd := &cobra.Command{ + Use: "list [ORGANIZATION/]PROJECT", + Short: "List area paths defined for a project.", + Long: heredoc.Doc(` + List Azure Boards area paths for a project. The project argument accepts the form + [ORGANIZATION/]PROJECT. When the organization segment is omitted, the default + organization from configuration is used. + `), + Example: heredoc.Doc(` + # List the top-level area paths for Fabrikam using the default organization + azdo boards area project list Fabrikam + + # List the full area tree for a project in a specific organization + azdo boards area project list myorg/Fabrikam --depth 5 + + # List the sub-tree under a specific area path (relative paths are resolved under /Area) + azdo boards area project list myorg/Fabrikam --path Payments --depth 3 + `), + Aliases: []string{"ls", "l"}, + Args: util.ExactArgs(1, "project argument required"), + RunE: func(cmd *cobra.Command, args []string) error { + opts.scopeArg = args[0] + return runList(ctx, opts) + }, + } + + cmd.Flags().StringVar(&opts.path, "path", "", "Restrict results to a specific area path (relative paths like \"Payments\" or \"Payments/Sub\" are resolved under /Area).") + cmd.Flags().IntVar(&opts.depth, "depth", 1, "Depth of child nodes to include (use 0 to omit child nodes).") + util.AddJSONFlags(cmd, &opts.exporter, []string{"id", "identifier", "name", "path", "hasChildren", "parentPath"}) + + return cmd +} + +func runList(ctx util.CmdContext, opts *listOptions) error { + ios, err := ctx.IOStreams() + if err != nil { + return err + } + + if opts.depth < 0 { + return util.FlagErrorf("--depth must be greater than or equal to 0") + } + + ios.StartProgressIndicator() + progressStopped := false + defer func() { + if !progressStopped { + ios.StopProgressIndicator() + } + }() + + org, project, err := resolveProjectScope(ctx, opts.scopeArg) + if err != nil { + return err + } + + cfg, err := ctx.Config() + if err != nil { + return fmt.Errorf("failed to load configuration: %w", err) + } + + orgURL, err := cfg.Authentication().GetURL(org) + if err != nil { + return fmt.Errorf("failed to resolve organization URL: %w", err) + } + + conn, err := ctx.ConnectionFactory().Connection(org) + if err != nil { + return fmt.Errorf("failed to create connection: %w", err) + } + + endpoint, err := buildAreaEndpoint(strings.TrimRight(orgURL, "/"), project, opts.path) + if err != nil { + return err + } + + reqURL, err := url.Parse(endpoint) + if err != nil { + return fmt.Errorf("failed to parse request URL: %w", err) + } + if opts.depth > 0 { + query := reqURL.Query() + query.Set("$depth", strconv.Itoa(opts.depth)) + reqURL.RawQuery = query.Encode() + } + + client := conn.GetClientByUrl(strings.TrimRight(orgURL, "/")) + req, err := client.CreateRequestMessage(ctx.Context(), http.MethodGet, reqURL.String(), "7.1", nil, "", azuredevops.MediaTypeApplicationJson, nil) + if err != nil { + return fmt.Errorf("failed to construct request: %w", err) + } + + zap.L().Debug("listing project area paths", + zap.String("organization", org), + zap.String("project", project), + zap.String("path", strings.TrimSpace(opts.path)), + zap.Int("depth", opts.depth), + zap.String("endpoint", reqURL.String()), + ) + + resp, err := client.SendRequest(req) + if err != nil { + return fmt.Errorf("failed to fetch area paths: %w", err) + } + defer resp.Body.Close() + + var root workItemClassificationNode + if err := client.UnmarshalBody(resp, &root); err != nil { + return fmt.Errorf("failed to decode area paths response: %w", err) + } + + var nodes []areaNode + flattenAreaNodes(&root, "", &nodes) + + if len(nodes) == 0 { + return util.NewNoResultsError("no area paths found") + } + + sort.Slice(nodes, func(i, j int) bool { + return strings.ToLower(nodes[i].Path) < strings.ToLower(nodes[j].Path) + }) + + if opts.exporter != nil { + ios.StopProgressIndicator() + progressStopped = true + return opts.exporter.Write(ios, nodes) + } + + tp, err := ctx.Printer("list") + if err != nil { + return err + } + + ios.StopProgressIndicator() + progressStopped = true + + tp.AddColumns("Name", "Path", "HasChildren") + for _, n := range nodes { + tp.AddField(n.Name) + tp.AddField(n.Path) + if n.HasChildren { + tp.AddField("true") + } else { + tp.AddField("false") + } + tp.EndRow() + } + + return tp.Render() +} + +func resolveProjectScope(ctx util.CmdContext, arg string) (string, string, error) { + parts := strings.Split(strings.TrimSpace(arg), "/") + switch len(parts) { + case 1: + project := strings.TrimSpace(parts[0]) + if project == "" { + return "", "", util.FlagErrorf("project argument cannot be empty") + } + cfg, err := ctx.Config() + if err != nil { + return "", "", fmt.Errorf("failed to read configuration: %w", err) + } + org, err := cfg.Authentication().GetDefaultOrganization() + if err != nil || strings.TrimSpace(org) == "" { + return "", "", util.FlagErrorf("no organization specified and no default organization configured") + } + return strings.TrimSpace(org), project, nil + case 2: + org := strings.TrimSpace(parts[0]) + project := strings.TrimSpace(parts[1]) + if org == "" || project == "" { + return "", "", util.FlagErrorf("invalid project argument %q; expected format ORGANIZATION/PROJECT", arg) + } + return org, project, nil + default: + return "", "", util.FlagErrorf("invalid project argument %q; expected format ORGANIZATION/PROJECT", arg) + } +} + +func buildAreaEndpoint(baseURL, project, path string) (string, error) { + projectSegment := url.PathEscape(project) + endpoint := fmt.Sprintf("%s/%s/_apis/wit/classificationnodes/Areas", baseURL, projectSegment) + + normalized, err := shared.BuildClassificationPath(project, true, "Area", path) + if err != nil { + return "", util.FlagErrorf("invalid path: %w", err) + } + if normalized != "" { + endpoint = endpoint + "/" + normalized + } + return endpoint, nil +} + +func flattenAreaNodes(node *workItemClassificationNode, parent string, rows *[]areaNode) { + if node == nil { + return + } + + name := types.GetValue(node.Name, "") + rawPath := types.GetValue(node.Path, "") + path := shared.NormalizeClassificationPath(rawPath) + id := types.GetValue(node.ID, 0) + identifier := types.GetValue(node.Identifier, "") + hasChildren := types.GetValue(node.HasChildren, false) + + row := areaNode{ + ID: id, + Identifier: identifier, + Name: name, + Path: path, + HasChildren: hasChildren, + } + if parent != "" { + row.ParentPath = shared.NormalizeClassificationPath(parent) + } + *rows = append(*rows, row) + + if len(node.Children) == 0 { + return + } + for i := range node.Children { + child := &node.Children[i] + flattenAreaNodes(child, rawPath, rows) + } +} diff --git a/internal/cmd/boards/area/project/project.go b/internal/cmd/boards/area/project/project.go new file mode 100644 index 00000000..88d48f07 --- /dev/null +++ b/internal/cmd/boards/area/project/project.go @@ -0,0 +1,28 @@ +package project + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" + listcmd "github.com/tmeckel/azdo-cli/internal/cmd/boards/area/project/list" + "github.com/tmeckel/azdo-cli/internal/cmd/util" +) + +// NewCmd registers project-scoped area commands. +func NewCmd(ctx util.CmdContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "project ", + Short: "Manage area paths scoped to a project.", + Example: heredoc.Doc(` + # List area paths under a project + azdo boards area project list Fabrikam + `), + Aliases: []string{ + "prj", + "p", + }, + } + + cmd.AddCommand(listcmd.NewCmd(ctx)) + + return cmd +} diff --git a/internal/cmd/boards/boards.go b/internal/cmd/boards/boards.go new file mode 100644 index 00000000..2a132bbe --- /dev/null +++ b/internal/cmd/boards/boards.go @@ -0,0 +1,28 @@ +package boards + +import ( + "github.com/MakeNowJust/heredoc" + "github.com/spf13/cobra" + "github.com/tmeckel/azdo-cli/internal/cmd/boards/area" + "github.com/tmeckel/azdo-cli/internal/cmd/util" +) + +// NewCmd constructs the root command for Azure Boards functionality. +func NewCmd(ctx util.CmdContext) *cobra.Command { + cmd := &cobra.Command{ + Use: "boards ", + Short: "Work with Azure Boards resources.", + GroupID: "core", + Example: heredoc.Doc(` + # List area paths for the default organization's Fabrikam project + azdo boards area project list Fabrikam + `), + Aliases: []string{ + "b", + }, + } + + cmd.AddCommand(area.NewCmd(ctx)) + + return cmd +} diff --git a/internal/cmd/root/root.go b/internal/cmd/root/root.go index a07e61b1..c11dfef6 100644 --- a/internal/cmd/root/root.go +++ b/internal/cmd/root/root.go @@ -8,6 +8,7 @@ import ( "github.com/google/shlex" "github.com/spf13/cobra" "github.com/tmeckel/azdo-cli/internal/cmd/auth" + "github.com/tmeckel/azdo-cli/internal/cmd/boards" "github.com/tmeckel/azdo-cli/internal/cmd/config" "github.com/tmeckel/azdo-cli/internal/cmd/graph" "github.com/tmeckel/azdo-cli/internal/cmd/pr" @@ -93,6 +94,7 @@ func NewCmdRoot(ctx util.CmdContext, version, buildDate string) (*cobra.Command, cmd.AddCommand(graph.NewCmdGraph(ctx)) cmd.AddCommand(security.NewCmd(ctx)) cmd.AddCommand(serviceendpoint.NewCmd(ctx)) + cmd.AddCommand(boards.NewCmd(ctx)) // Help topics var referenceCmd *cobra.Command From 4ed9b0472bc366655fe282579f93747e9b3cb203 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 22:12:03 +0000 Subject: [PATCH 4/6] =?UTF-8?q?docs:=20=F0=9F=93=84=20add=20azdo=20boards?= =?UTF-8?q?=20area=20project=20list=20documentation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new documentation pages for the `azdo boards` command family, including area, area project, and the `azdo boards area project list` command. --- docs/azdo.md | 1 + docs/azdo_boards.md | 22 ++++++++++ docs/azdo_boards_area.md | 22 ++++++++++ docs/azdo_boards_area_project.md | 23 ++++++++++ docs/azdo_boards_area_project_list.md | 60 +++++++++++++++++++++++++++ docs/azdo_help_reference.md | 48 +++++++++++++++++++++ 6 files changed, 176 insertions(+) create mode 100644 docs/azdo_boards.md create mode 100644 docs/azdo_boards_area.md create mode 100644 docs/azdo_boards_area_project.md create mode 100644 docs/azdo_boards_area_project_list.md diff --git a/docs/azdo.md b/docs/azdo.md index 54eccaa3..52e9daa8 100644 --- a/docs/azdo.md +++ b/docs/azdo.md @@ -5,6 +5,7 @@ Work seamlessly with Azure DevOps from the command line. ### Core commands * [azdo auth](./azdo_auth.md) +* [azdo boards](./azdo_boards.md) * [azdo graph](./azdo_graph.md) * [azdo pr](./azdo_pr.md) * [azdo project](./azdo_project.md) diff --git a/docs/azdo_boards.md b/docs/azdo_boards.md new file mode 100644 index 00000000..0e06b534 --- /dev/null +++ b/docs/azdo_boards.md @@ -0,0 +1,22 @@ +## Command `azdo boards` + +Work with Azure Boards resources. + +### Available commands + +* [azdo boards area](./azdo_boards_area.md) + +### ALIASES + +- `b` + +### Examples + +```bash +# List area paths for the default organization's Fabrikam project +azdo boards area project list Fabrikam +``` + +### See also + +* [azdo](./azdo.md) diff --git a/docs/azdo_boards_area.md b/docs/azdo_boards_area.md new file mode 100644 index 00000000..37867cef --- /dev/null +++ b/docs/azdo_boards_area.md @@ -0,0 +1,22 @@ +## Command `azdo boards area` + +Manage area paths used by Azure Boards. + +### Available commands + +* [azdo boards area project](./azdo_boards_area_project.md) + +### ALIASES + +- `a` + +### Examples + +```bash +# List the area paths for a project +azdo boards area project list Fabrikam +``` + +### See also + +* [azdo boards](./azdo_boards.md) diff --git a/docs/azdo_boards_area_project.md b/docs/azdo_boards_area_project.md new file mode 100644 index 00000000..32369b8c --- /dev/null +++ b/docs/azdo_boards_area_project.md @@ -0,0 +1,23 @@ +## Command `azdo boards area project` + +Manage area paths scoped to a project. + +### Available commands + +* [azdo boards area project list](./azdo_boards_area_project_list.md) + +### ALIASES + +- `prj` +- `p` + +### Examples + +```bash +# List area paths under a project +azdo boards area project list Fabrikam +``` + +### See also + +* [azdo boards area](./azdo_boards_area.md) diff --git a/docs/azdo_boards_area_project_list.md b/docs/azdo_boards_area_project_list.md new file mode 100644 index 00000000..dbf5ffdf --- /dev/null +++ b/docs/azdo_boards_area_project_list.md @@ -0,0 +1,60 @@ +## Command `azdo boards area project list` + +``` +azdo boards area project list [ORGANIZATION/]PROJECT [flags] +``` + +List Azure Boards area paths for a project. The project argument accepts the form +[ORGANIZATION/]PROJECT. When the organization segment is omitted, the default +organization from configuration is used. + + +### Options + + +* `--depth` `int` (default `1`) + + Depth of child nodes to include (use 0 to omit child nodes). + +* `-q`, `--jq` `expression` + + Filter JSON output using a jq expression + +* `--json` `fields` + + Output JSON with the specified fields. Prefix a field with '-' to exclude it. + +* `--path` `string` + + Restrict results to a specific area path (relative paths like "Payments" or "Payments/Sub" are resolved under <project>/Area). + +* `-t`, `--template` `string` + + Format JSON output using a Go template; see "azdo help formatting" + + +### ALIASES + +- `ls` +- `l` + +### JSON Fields + +`hasChildren`, `id`, `identifier`, `name`, `parentPath`, `path` + +### Examples + +```bash +# List the top-level area paths for Fabrikam using the default organization +azdo boards area project list Fabrikam + +# List the full area tree for a project in a specific organization +azdo boards area project list myorg/Fabrikam --depth 5 + +# List the sub-tree under a specific area path (relative paths are resolved under /Area) +azdo boards area project list myorg/Fabrikam --path Payments --depth 3 +``` + +### See also + +* [azdo boards area project](./azdo_boards_area_project.md) diff --git a/docs/azdo_help_reference.md b/docs/azdo_help_reference.md index 5a87b8ce..9b90663f 100644 --- a/docs/azdo_help_reference.md +++ b/docs/azdo_help_reference.md @@ -33,6 +33,54 @@ Setup git with AzDO CLI View authentication status +## `azdo boards ` + +Work with Azure Boards resources. + +Aliases + +``` +b +``` + +### `azdo boards area ` + +Manage area paths used by Azure Boards. + +Aliases + +``` +a +``` + +#### `azdo boards area project ` + +Manage area paths scoped to a project. + +Aliases + +``` +prj, p +``` + +##### `azdo boards area project list [ORGANIZATION/]PROJECT [flags]` + +List area paths defined for a project. + +``` + --depth int Depth of child nodes to include (use 0 to omit child nodes). (default 1) +-q, --jq expression Filter JSON output using a jq expression + --json fields[=*] Output JSON with the specified fields. Prefix a field with '-' to exclude it. + --path string Restrict results to a specific area path (relative paths like "Payments" or "Payments/Sub" are resolved under /Area). +-t, --template string Format JSON output using a Go template; see "azdo help formatting" +``` + +Aliases + +``` +ls, l +``` + ## `azdo co` Alias for "pr checkout" From 70562cbfcba6dfab7dbe0703157418ff2758732a Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 22:19:14 +0000 Subject: [PATCH 5/6] ci: run tests on pull requests Add a workflow step to execute `go test ./...` only for `pull_request` events. --- .github/workflows/build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 73a2340d..fd36534b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,6 +39,13 @@ jobs: with: go-version: ${{ env.GO_VERSION }} + - name: Run tests (only for pull requests) + if: ${{ github.event_name == 'pull_request' }} + run: | + set -e + echo "Running unit tests..." + go test ./... + - name: GoReleaser uses: goreleaser/goreleaser-action@v6.4.0 with: From 3df69aa6f2e882aa56d02a254d2ae8a0f1f1bba3 Mon Sep 17 00:00:00 2001 From: Codex CLI Date: Mon, 10 Nov 2025 22:21:05 +0000 Subject: [PATCH 6/6] chore: rename test step in build workflow --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd36534b..4ffbf8a1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: with: go-version: ${{ env.GO_VERSION }} - - name: Run tests (only for pull requests) + - name: Run tests if: ${{ github.event_name == 'pull_request' }} run: | set -e