Use GRUB Generators to create boot entries

GRUB Plugin
I've started work on a plug-in for grub. In my limited testing in a virtual machine, it currently is able to create boot entries for for every existing boot environment.
It uses a python GRUB generator to create the boot entries for GRUB. It bind mounts directories from /mnt/boot/env as was done with systemd-boot.

[x] Allow boot on ZFS.
[x] Build grub.cfg for active boot environment
[x] Append other boot environments to grub.cfg
[x] Test

cc @zdykstra Continuing on from https://github.com/johnramsden/zedenv/pull/4

10_linux now works for one of the four uses cases / needs. As I see them, the following setups need to be handled:
/boot is ext4/xfs/etc

[x]  Build grub.cfg for active boot environment
[ ] Append other boot environments to grub.cfg

/boot is ZFS

[ ] Build grub.cfg for active boot environment
[ ] Append other boot environments to grub.cfg

Writing a generator for alternate environments when /boot is ext4 shouldn't be hard, if we're happy with 10_linux as it stands now. I have a couple changes in my fork, but they're small syntax fixes.
The question is how do you want to handle things when /boot is backed by ZFS? Do you want to mount all alternate environments by zedenv, then bind-mount /boot from each into a duplicate of the directory structure used when /boot is ext4? Once grub-mkconfig is done, then all the alternate environments would get unmounted?
I'm going to test the current generator more fully against /boot on ext4 and ZFS to ensure it builds correct and bootable grub.cfg files for the currently booted environment.

It looks like the generator in my cloned repository creates correct linux and initrd lines for files on a ZFS boot. The mechanism is a helper function that at it's core is this:
$ /usr/bin/grub-mkrelpath /boot
/ROOT/default@/boot

An easier way to determine what /boot is, rather than looking for a manually set property, is:
grub-probe /boot 2>/dev/null || true
It'll return an empty string if grub-probe can't figure it out, or ext2, zfs, etc.

-bash-4.4# grub-probe /
zfs
-bash-4.4# grub-probe /boot
ext2

If zedenv can manage mounting the alternate environments for a pure ZFS /boot to a common/parseable structure, I can extend a generator to work through them and create all the entries.  Just mount all the environments to wherever you want, then call grub-mkconfig -o /boot/grub/grub.cfg.  10_linux does what it needs to right now for the active environment. I'll then duplicate that generator and wrap the relevant bits in a for env in list of our environments here; do ; done loop. Sound reasonable?

Ahh good, grub-mkrelpath sounds like what I was looking for. That makes it look a lot easier than I thought it would be.
What I'll probably do is mount the existing boot environments to ${grubboot}/env/zedenv-${boot_environment}/
For example:
$ zedenv mount -v default-3 /mnt/boot/env/zedenv-default-3
$ grub-mkrelpath /mnt/boot/env/zedenv-default-3/boot
/sys/wooly/ROOT/default-3@/boot

Then we can just walk over all of the directories in ${grubboot}/env/*

I've run into a bit of a problem, was wondering if you had any ideas.
We have been discussing keeping the boot partition mounted to /mnt/boot, and bindmounting the current boot environment to /boot. The problem is, since grub wants to keep its configuration file in /boot/grub, we either have to have an entire /boot/grub directory for each environment, which doesn't work - or we have to figure out a way to put the grub directory somewhere else. I've been trying to find out what defines the location, but haven't come up with much.
Do you know how grub finds the /boot/grub/grub.cfg configuration file? There must be some way to change it but I haven't had any luck finding out what defines its location.

Okay, i'm pretty sure the grub directory just has to be in the directory relative to the install point. So as long as we actually install grub to /mnt/boot, we shouldn't have a problem, and we just direct the config to /mnt/boot/grub/grub.cfg

Well, ideally the only thing in the different boot environment directories would be the kernel. If we do it the way you outlined, it means there needs to be a copy of grub for every boot environment. Or they need to be copied back and forth.
I didn't really consider bindmounting /mnt/boot/grub, I guess that might work. I'm not really sure what you mean about copying back and forth though. There shouldn't be any reason to do that, unless I'm misunderstanding something.
For what reason does the grub install actually need to live in /boot/grub? Isn't the real concern kernels getting rebuilt correctly?

If we're going to bindmount grub, it means more moving parts but couldn't this work?

We leave the active boot environment bindmounted to /boot so that kernel rebuilds work correctly.
We also bindmount /mnt/boot/grub to /boot/grub, so that we can run grub-mkconfig -o /boot/grub/grub.cfg, as expected.
Upon upgrade we unmount /boot/grub, and /boot, then remount /boot as the new boot environment, remount  /boot/grub, then run grub-mkconfig.

grub.cfg for the booted environment has to live at /boot/grub/grub.cfg, so
when a kernel is installed the upgrade hook to to rebuild grub completes
successfully. If grub.cfg is somewhere else, package hooks for every OS
this can be installed on need to be written, and then the stock hooks have
to be disabled. Or if grub.cfg is just left where everything expects it to
be, this fits in transparently on virtually every distro it's installed on.
On Wed, Jun 6, 2018, 12:27 AM John<EMAIL_ADDRESS>wrote:

Well, ideally the only thing in the different boot environment directories
would be the kernel. If we do it the way you outlined, it means there needs
to be a copy of grub for every boot environment. Or they need to be copied
back and forth.
I didn't really consider bindmounting /mnt/boot/grub, I guess that might
work. I'm not really sure what you mean about copying back and forth
though. There shouldn't be any reason to do that, unless I'm
misunderstanding something.
For what reason does the grub install actually need to live in /boot/grub?
Isn't the real concern kernels getting rebuilt correctly?
If we're going to bindmount grub, it means more moving parts but couldn't
this work?

We leave the active boot environment bindmounted to /boot so that
kernel rebuilds work correctly.
We also bindmount /mnt/boot/grub to /boot/grub, so that we can run grub-mkconfig
-o /boot/grub/grub.cfg, as expected.
Upon upgrade we unmount /boot/grub, and /boot, then remount /boot
as the new boot environment, remount /boot/grub, then run grub-mkconfig
.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/johnramsden/zedenv-grub/pull/1#issuecomment-394944372,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ANO2pcvGVAekAeJngb_rCaVyZ9S14Y_9ks5t52gqgaJpZM4UYdkO
.

Could we not just bindmount /mnt/boot/grub to /boot/grub, and unmount it when we do the upgrade, then remount it after? You talked about copying it back and forth, I just don't follow why that would be necessary.

I'm probably operating under incorrect assumptions. Would grub.cfg be regenerated every time a boot environment is created OR activated? If so, then grub.cfg doesn't need to be preserved - when it's made again, it'll always be accurate.

For grub, I would say we might as well run it every time a change Is made so it's always accurate.

I'm taking a look at what would be involved to replace the shell script generator with a custom written python script. I think it would make pelagic a lot easier to understand, it would also integrate better with zedenv.

Python generator is going well. Almost finished initial version. I'm currently adding the section for individual BE entries.

cc @zdykstra
Successfully generated a menu with the new python generator. It still has a few things that need adding such as replicating the following sections:
  if [ x$dirname = x/ ]; then
    if [ -z "${prepare_root_cache}" ]; then
      prepare_root_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE} | grub_add_tab)"
    fi
    printf '%s\n' "${prepare_root_cache}" | sed "s/^/$submenu_indentation/"
  else
    if [ -z "${prepare_boot_cache}" ]; then
      prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | grub_add_tab)"
    fi
    printf '%s\n' "${prepare_boot_cache}" | sed "s/^/$submenu_indentation/"
  fi

and
      if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then
	  replacement_title="$(echo "Advanced options for ${OS}" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"
	  quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"
	  title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"
	  grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"
      fi

Here's an example menu I created from the following boot environments:
$ zedenv list
Name                  Active   Mountpoint   Creation
linux-4.16.11-1                -            Sun-May-27-15:48-2018
linux-4.16.13-1                -            Sun-Jun-3-2:39-2018
linux-4.16.13-2                -            Wed-Jun-13-23:31-2018
nvidia-vsync                   -            Sat-Jun-16-10:25-2018
linux-4.17.2-1                 -            Mon-Jun-18-16:39-2018
plasma-5.13.0-5.13.1           -            Tue-Jun-19-13:22-2018
linux-lts-4.14.50     NR       /            Tue-Jun-19-14:57-2018

Generated grub.cfg:
menuentry 'Arch GNU/Linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-vault/sys/wooly/ROOT/linux-4.16.13-2' {
	load_video
	set gfxpayload=keep
	insmod gzio
	echo 'Loading Linux linux ...'
	linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro  quiet
	echo 'Loading initial ramdisk ...'
	initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img
}
Advanced options for Arch GNU/Linux $menuentry_id_option 'gnulinux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-2' {
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-2' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.13-2' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.11-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.11-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.11-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.11-1/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.11-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.11-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.11-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.11-1/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-1/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.13-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-1/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/nvidia-vsync' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-nvidia-vsync/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/nvidia-vsync ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-nvidia-vsync/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/nvidia-vsync' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-nvidia-vsync/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/nvidia-vsync ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-nvidia-vsync/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.17.2-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.17.2-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.17.2-1/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.17.2-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.17.2-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.17.2-1/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-plasma-5.13.0-5.13.1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-plasma-5.13.0-5.13.1/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-plasma-5.13.0-5.13.1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-plasma-5.13.0-5.13.1/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux.img
	}
}
	menuentry 'Arch GNU/Linux with Linux linux-lts' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-advanced-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux-lts ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux-lts root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux-lts.img
	}
	menuentry 'Arch GNU/Linux with Linux linux-lts (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-recovery-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		echo 'Loading Linux linux-lts ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux-lts root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux-lts.img
	}
}

I still need to add the org.zedenv.grub:bootonzfs generator, and fix a few problems so it's probably not quite ready for testing, but it's getting there.

@zdykstra Regarding the last few problem sections, if you have any input I've been having trouble reproducing the 'preparing the file systems' section:
https://github.com/johnramsden/zedenv-grub/blob/ecb7884d6905c1cad515ec52c6a4d523713bac52/grub.d/10_linux#L131-L141
prepare_grub_to_access_device from grub-mkconfig_lib does the following:
prepare_grub_to_access_device ()
{
  old_ifs="$IFS"
  IFS='
'
  partmap="`"${grub_probe}" --device $@ --target=partmap`"
  for module in ${partmap} ; do
    case "${module}" in
      netbsd | openbsd)
        echo "insmod part_bsd";;
      *)
        echo "insmod part_${module}";;
    esac
  done

  # Abstraction modules aren't auto-loaded.
  abstraction="`"${grub_probe}" --device $@ --target=abstraction`"
  for module in ${abstraction} ; do
    echo "insmod ${module}"
  done

  fs="`"${grub_probe}" --device $@ --target=fs`"
  for module in ${fs} ; do
    echo "insmod ${module}"
  done

  if [ x$GRUB_ENABLE_CRYPTODISK = xy ]; then
      for uuid in `"${grub_probe}" --device $@ --target=cryptodisk_uuid`; do
	  echo "cryptomount -u $uuid"
      done
  fi

  # If there's a filesystem UUID that GRUB is capable of identifying, use it;
  # otherwise set root as per value in device.map.
  fs_hint="`"${grub_probe}" --device $@ --target=compatibility_hint`"
  if [ "x$fs_hint" != x ]; then
    echo "set root='$fs_hint'"
  fi
  if fs_uuid="`"${grub_probe}" --device $@ --target=fs_uuid 2> /dev/null`" ; then
    hints="`"${grub_probe}" --device $@ --target=hints_string 2> /dev/null`" || hints=
    echo "if [ x\$feature_platform_search_hint = xy ]; then"
    echo "  search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}"
    echo "else"
    echo "  search --no-floppy --fs-uuid --set=root ${fs_uuid}"
    echo "fi"
  fi
  IFS="$old_ifs"
}

The biggest problem I have is using grub-probe with ZFS because it doesn't work well with mirrored ZFS pools, meaning I'm not sure what to do. Setting export ZPOOL_VDEV_NAME_PATH=1 seems to help avoid getting the message 'error: failed to get canonical path', but that's as far as I've gotten. I'm not quite sure what GRUB_DEVICE needs to be when ZFS is used...
Help is appreciated. Even if you can narrow down how to get ${grub_probe}" --device $@ --target=${some_target} working, and how it should be changed in regards to the above code, that would be a huge help.

For now i'll continue on to get the bootonzfs code working. I think you could probably see if the menu is generated correctly for you actually, besides it maybe missing a few insmods.
I haven't actually tried moving it to /etc/grub.d, and making it executable yet. Should be interesting to see if that works. If you just want to see what the output looks like you can just run python3.6 10_zfs_linux.py, but keep in mind when you run it directly without grub-mkconfig it will probably be missing a few environment variables.

Okay, made some progress with the probing. I found out that requires root access!
# /usr/bin/grub-probe --device /dev/nvme0n1 /dev/nvme1n1 --target=fs
zfs

I was able to get all the code working to load modules ◔ ⌣ ◔! It should now detect which modules to load.
Here's an example menu
menuentry 'Arch GNU/Linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-vault/sys/wooly/ROOT/linux-4.16.13-2' {
	load_video
	set gfxpayload=keep
	insmod gzio
	insmod zfs
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
	else
	  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
	fi
	echo 'Loading Linux linux ...'
	linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro  quiet
	echo 'Loading initial ramdisk ...'
	initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img /env/zedenv-linux-4.16.13-2/intel-ucode.img
}
submenu 'Advanced options for Arch GNU/Linux' $menuentry_id_option 'gnulinux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-2' {
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-2' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img /env/zedenv-linux-4.16.13-2/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.13-2' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-2/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-2 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-2/initramfs-linux.img /env/zedenv-linux-4.16.13-2/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.11-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.11-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.11-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.11-1/initramfs-linux.img /env/zedenv-linux-4.16.11-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.11-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.11-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.11-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.11-1/initramfs-linux.img /env/zedenv-linux-4.16.11-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.16.13-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-1/initramfs-linux.img /env/zedenv-linux-4.16.13-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.16.13-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.16.13-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.16.13-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.16.13-1/initramfs-linux.img /env/zedenv-linux-4.16.13-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/nvidia-vsync' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-nvidia-vsync/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/nvidia-vsync ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-nvidia-vsync/initramfs-linux.img /env/zedenv-nvidia-vsync/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/nvidia-vsync' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-nvidia-vsync/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/nvidia-vsync ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-nvidia-vsync/initramfs-linux.img /env/zedenv-nvidia-vsync/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.17.2-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.17.2-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.17.2-1/initramfs-linux.img /env/zedenv-linux-4.17.2-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.17.2-1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-4.17.2-1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-4.17.2-1/initramfs-linux.img /env/zedenv-linux-4.17.2-1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-plasma-5.13.0-5.13.1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-plasma-5.13.0-5.13.1/initramfs-linux.img /env/zedenv-plasma-5.13.0-5.13.1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-plasma-5.13.0-5.13.1/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/plasma-5.13.0-5.13.1 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-plasma-5.13.0-5.13.1/initramfs-linux.img /env/zedenv-plasma-5.13.0-5.13.1/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux.img /env/zedenv-linux-lts-4.14.50/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux.img /env/zedenv-linux-lts-4.14.50/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux-lts' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-advanced-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux-lts ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux-lts root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro  quiet
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux-lts.img /env/zedenv-linux-lts-4.14.50/intel-ucode.img
	}
	menuentry 'Arch GNU/Linux with Linux linux-lts (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-lts-recovery-vault/sys/wooly/ROOT/linux-lts-4.14.50' {
		load_video
		set gfxpayload=keep
		insmod gzio
		insmod zfs
		if [ x$feature_platform_search_hint = xy ]; then
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		else
		  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
		fi
		echo 'Loading Linux linux-lts ...'
		linux /env/zedenv-linux-lts-4.14.50/vmlinuz-linux-lts root=ZFS=vault/sys/wooly/ROOT/linux-lts-4.14.50 ro single
		echo 'Loading initial ramdisk ...'
		initrd /env/zedenv-linux-lts-4.14.50/initramfs-linux-lts.img /env/zedenv-linux-lts-4.14.50/intel-ucode.img
	}
}

bootonzfs entries working. Should be ready for testing. There are likely some bugs, so let me know if you see anything that looks a little odd.
To use, install the plug-in, move grub.d/10_zfs_linux.py to /etc/grub.d, set the execute bit, and run zedenv activate or grub-mkconfig as root.
Example bootonzfs grub.cfg
### BEGIN /etc/grub.d/10_zfs_linux.py ###
menuentry 'Arch GNU/Linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-vault/sys/wooly/ROOT/linux-4.17.2-1' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod zfs
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
        else
          search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
        fi
        echo 'Loading Linux linux ...'
        linux /sys/wooly/ROOT/linux-4.17.2-1@/boot/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro  quiet
        echo 'Loading initial ramdisk ...'
        initrd<EMAIL_ADDRESS><EMAIL_ADDRESS>}
submenu 'Advanced options for Arch GNU/Linux' $menuentry_id_option 'gnulinux-advanced-vault/sys/wooly/ROOT/linux-4.17.2-1' {
        menuentry 'Arch GNU/Linux with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/wooly/ROOT/linux-4.17.2-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod zfs
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
                else
                  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
                fi
                echo 'Loading Linux linux ...'
                linux /sys/wooly/ROOT/linux-4.17.2-1@/boot/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro  quiet
                echo 'Loading initial ramdisk ...'
                initrd<EMAIL_ADDRESS><EMAIL_ADDRESS>        }
        menuentry 'Arch GNU/Linux with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/wooly/ROOT/linux-4.17.2-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod zfs
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
                else
                  search --no-floppy --fs-uuid --set=root 14fd793cadf7d7df
                fi
                echo 'Loading Linux linux ...'
                linux /sys/wooly/ROOT/linux-4.17.2-1@/boot/vmlinuz-linux root=ZFS=vault/sys/wooly/ROOT/linux-4.17.2-1 ro single
                echo 'Loading initial ramdisk ...'
                initrd<EMAIL_ADDRESS><EMAIL_ADDRESS>        }
}

Found a few things that are backwards. Don't run it yet without a backup config.

Successfully generated a menu and booted using this setup.
The question is what's the best type of menu to generate. Right now I am putting the active boot environment at the top, and creating a subbmenu with the rest of the boot environments with one option for each kernel.
/boot/grub/grub.cfg
#
# DO NOT EDIT THIS FILE
#
# It is automatically generated by grub-mkconfig using templates
# from /etc/grub.d and settings from /etc/default/grub
#

### BEGIN /etc/grub.d/00_header ###
insmod part_gpt
insmod part_msdos
if [ -s $prefix/grubenv ]; then
  load_env
fi
if [ "${next_entry}" ] ; then
   set default="${next_entry}"
   set next_entry=
   save_env next_entry
   set boot_once=true
else
   set default="0"
fi

if [ x"${feature_menuentry_id}" = xy ]; then
  menuentry_id_option="--id"
else
  menuentry_id_option=""
fi

export menuentry_id_option

if [ "${prev_saved_entry}" ]; then
  set saved_entry="${prev_saved_entry}"
  save_env saved_entry
  set prev_saved_entry=
  save_env prev_saved_entry
  set boot_once=true
fi

function savedefault {
  if [ -z "${boot_once}" ]; then
    saved_entry="${chosen}"
    save_env saved_entry
  fi
}

function load_video {
  if [ x$feature_all_video_module = xy ]; then
    insmod all_video
  else
    insmod efi_gop
    insmod efi_uga
    insmod ieee1275_fb
    insmod vbe
    insmod vga
    insmod video_bochs
    insmod video_cirrus
  fi
}

if [ x$feature_default_font_path = xy ] ; then
   font=unicode
else
insmod part_gpt
insmod zfs
set root='hd0,gpt2'
if [ x$feature_platform_search_hint = xy ]; then
  search --no-floppy --fs-uuid --set=root --hint-ieee1275='ieee1275//disk@0,gpt2' --hint-bios=hd0,gpt2 --hint-efi=hd0,gpt2 --hint-baremetal=ahci0,gpt2  a1b916c0819a1863
else
  search --no-floppy --fs-uuid --set=root a1b916c0819a1863
fi
<EMAIL_ADDRESS>fi

if loadfont $font ; then
  set gfxmode=auto
  load_video
  insmod gfxterm
  set locale_dir=$prefix/locale
  set lang=en_US
  insmod gettext
fi
terminal_input console
terminal_output gfxterm
if [ x$feature_timeout_style = xy ] ; then
  set timeout_style=menu
  set timeout=5
# Fallback normal timeout code in case the timeout_style feature is
# unavailable.
else
  set timeout=5
fi
### END /etc/grub.d/00_header ###

### BEGIN /etc/grub.d/10_zfs_linux.py ###
menuentry 'Arch GNU/Linux BE [grub-test-3]' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-simple-vault/sys/zedenv/ROOT/grub-test-3' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod fat
        set root='hd0,gpt1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
        else
          search --no-floppy --fs-uuid --set=root B11F-0328
        fi
        echo 'Loading Linux linux ...'
        linux /env/zedenv-grub-test-3/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-3 rw  quiet
        echo 'Loading initial ramdisk ...'
        initrd /env/zedenv-grub-test-3/initramfs-linux.img
}
menuentry 'Arch GNU/Linux BE [grub-test-3] with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/zedenv/ROOT/grub-test-3' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod fat
        set root='hd0,gpt1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
        else
          search --no-floppy --fs-uuid --set=root B11F-0328
        fi
        echo 'Loading Linux linux ...'
        linux /env/zedenv-grub-test-3/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-3 rw  quiet
        echo 'Loading initial ramdisk ...'
        initrd /env/zedenv-grub-test-3/initramfs-linux.img
}
menuentry 'Arch GNU/Linux BE [grub-test-3] with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/zedenv/ROOT/grub-test-3' {
        load_video
        set gfxpayload=keep
        insmod gzio
        insmod fat
        set root='hd0,gpt1'
        if [ x$feature_platform_search_hint = xy ]; then
          search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
        else
          search --no-floppy --fs-uuid --set=root B11F-0328
        fi
        echo 'Loading Linux linux ...'
        linux /env/zedenv-grub-test-3/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-3 rw single
        echo 'Loading initial ramdisk ...'
        initrd /env/zedenv-grub-test-3/initramfs-linux.img
}
submenu 'Boot Environments (Arch GNU/Linux)' $menuentry_id_option 'gnulinux-advanced-be-vault/sys/zedenv/ROOT/grub-test-3' {
        menuentry 'Arch GNU/Linux BE [default] with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/zedenv/ROOT/default' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-default/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/default rw  quiet
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-default/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [default] with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/zedenv/ROOT/default' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-default/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/default rw single
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-default/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [default-1] with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/zedenv/ROOT/default-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-default-1/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/default-1 rw  quiet
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-default-1/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [default-1] with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/zedenv/ROOT/default-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-default-1/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/default-1 rw single
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-default-1/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [grub-test-1] with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/zedenv/ROOT/grub-test-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-grub-test-1/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-1 rw  quiet
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-grub-test-1/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [grub-test-1] with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/zedenv/ROOT/grub-test-1' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-grub-test-1/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-1 rw single
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-grub-test-1/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [grub-test-2] with Linux linux' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-advanced-vault/sys/zedenv/ROOT/grub-test-2' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-grub-test-2/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-2 rw  quiet
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-grub-test-2/initramfs-linux.img
        }
        menuentry 'Arch GNU/Linux BE [grub-test-2] with Linux linux (recovery mode)' --class arch --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-linux-recovery-vault/sys/zedenv/ROOT/grub-test-2' {
                load_video
                set gfxpayload=keep
                insmod gzio
                insmod fat
                set root='hd0,gpt1'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root B11F-0328 --hint-ieee1275='ieee1275//disk@0,gpt1' --hint-bios=hd0,gpt1 --hint-efi=hd0,gpt1 --hint-baremetal=ahci0,gpt1
                else
                  search --no-floppy --fs-uuid --set=root B11F-0328
                fi
                echo 'Loading Linux linux ...'
                linux /env/zedenv-grub-test-2/vmlinuz-linux root=ZFS=vault/sys/zedenv/ROOT/grub-test-2 rw single
                echo 'Loading initial ramdisk ...'
                initrd /env/zedenv-grub-test-2/initramfs-linux.img
        }
}
### END /etc/grub.d/10_zfs_linux.py ###

@zdykstra have you had a chance to test this out yet?

To  zdykstra , how's it going with the test? I would like to see it happen in a rather quicker manner because I'm want to see grub-plugin appear in the zedenv's main branch.

Squished some commits removing unused code such as the old shell script generators. The old Branch is archived here.

Regarding GRUB, and where configuration is stored on an all ZFS setup, a problem I have had is when the configuration is stored in an initial boot environment such as zpool/ROOT/default, and then a clone is made it seems to continue to read the GRUB configuration from the original boot environment. This is a problem since if the initial clone is destroyed, grub fails to boot. A solution to this would be to always use a small partition to hold the grub configuration, similar to what is used on a non all ZFS setup, except in this case the kernels would be still stored on ZFS in the in the boot environments.
@danboid What is your opinion on this? Would that be suitable for your use case?

Hi John
It seems PCBSD 10.2 was the last release to use GRUB. I can download it in the UK much faster from
http://ftp.icm.edu.pl/packages/pcbsd/iso/10.2-RELEASE/amd64/
Than downloading it from the official TrueOS/PCBSD site.
When doing a default (ZFS) install of PCBSD 10.2 to a single disk VM, the installer creates 3 partitions - a 1 MB GRUB BIOS partition, a 512 MB swap partition (at the end of the disk) and everything inbetween is just one large ZFS partition, so they didn't use a separate partition for /etc or GRUB.
Within the PC-BSD Control Panel, there is Boot Manager, their old Qt GUI for managing BE's. I've not checked but I expect it is just a GUI for beadm. If I try to clone the default BE without having made any others first (and activated it) it gives the error:
"You cannot make a copy of the currently running boot environment"
So they (iXSystems,or more precisely beadm / Boot Manager) don't seem to allow what you were doing anyway.

@danboid Thanks, I'll take a look at how they are managing boot environments. If they only have datasets holding the grub information it should be possible without an extra partition.

So after taking a look, they don't seem to be doing anything different than what we are already doing. I'm not sure how grub knows where to read the configuration file from, but upon destroying the original boot environment in pcbsd, the grub configuration is just re-created in the current boot environment.

I've been meaning to ask you about the Linux port of beadm ( https://github.com/b333z/beadm ) and why you decided to write zedenv instead of fixing /improving Linux beadm? I had a quick look at that Linux beadm port and it seems to have some grub update support although it didn't work when I tried it and it seems that the Linux beadm port has been unmaintained for some time. I presume its GRUB support was a WIP?
I'd imagine you have already looked into adding your grub generator script or the PCBSD one to the Linux beadm port and decided against it, that it was easier or better to start over?

@danboid Like you said, it would need some work and once I read the code I thought it would be a lot easier to manage a program that was written in a programming language rather than Bourne shell.
When you're talking about grub update support, all beadm does is runs:
grub-mkconfig -o /boot/grub/grub.cfg

So basically everything in this plug-in would still be necessary. As it currently stands that will only generate an entry for the currently booted BE.
On top of that, Linux uses lots of different bootloaders, and I wanted a way to support all of them if possible, for instance I use systemd-boot and would have had to add a lot of extra code to generate the bootloader entries. Using a plug-in system means as possible to add them external to the main code that's doing manipulation of datasets and clones.

I'm still getting an error when I destroy the original boot environment, I'm wondering if it's because it's initially where GRUB was installed.
As mentioned in https://github.com/zfsonlinux/zfs/issues/5961 I'm going to try creating a zpool/grub dataset that is shared between the environments and see if that fixes the problem.

This seems to work, proceeding testing:
zfs create -o canmount=off zroot/boot
zfs create -o mountpoint=/boot/grub zroot/boot/grub

grub-install --target=i386-pc /dev/vda

Great! Let me know when you think its ready for me to test.

@danboid Okay, it should be good to go for testing. Just be careful, as I'm sure you know twiddling around with the bootloader can be dangerous.
You're going to want to create a grub dataset and mount it at /boot/grub. I'm mounting mine through fstab. If you have old boot environments keep in mind they won't mount the grub dataset because it's not in their fstab. I'm sure it probably works with ZFS mounts too, but I've been using legacy for testing.
Make sure you're using the latest zedenv-grub. Running the PKGBUILD-git should update it, make sure the branch is set to grub-generators.

I want to update the ISO before testing zedenv but the zfs commands you gave above
zfs create -o canmount=off "${zroot}"/boot
zfs create -o mountpoint=/boot/grub "${zroot}"/boot/grub

Aren't quite right for ALEZ, the second command errors re: the directory already being mounted or somesuch. Wouldn't it need to be:
zfs create -o canmount=off "${zroot}"/ROOT/boot
zfs create -o mountpoint=/boot/grub "${zroot}"/data/boot/grub

Or something?

@danboid you can actually put it wherever, zroot/grub would be fine too, maybe it erorred because you were creating it on the iso which already contained the directory. Just like you would get an error for mountpoint=/. For alez you could do the same thing we are doing for / with:
{ zfs create -o mountpoint=/boot/grub "${zroot}"/boot/grub || : ; }  &> /dev/null

You could also mount his legacy and do it through the fstab with:
zfs create -o mountpoint=legacy "${zroot}"/boot/grub

Let me know if you are still having problems, I can test something out and send you a PR.

@danboid figured I might as well just write the PR, I tested it in a new VM and it seemed to work just fine.

Going to merge this now, should now be ready for Alpha testing. Thanks for everyone's help.

Great! Should we be able to install zedenv and the grub plugin from the AUR now?
As I said, I'd like to see the ZFS repo host packages too to make installing even easier.

@danboid I wasn't sure if I should stick it in the AUR yet since it has gotten so little testing so far. Will you be using this on a system you are using regularly where you might be able to use it for a week and make sure we don't notice any problems? I'm a little wary since comparatively speaking, the grub plugin is significantly more complex then the other plugins.
I do it myself, but I'm not using GRUB - and would prefer not to - on any of my systems.

In regards to installing - you can definitely install zedenv from the AUR. As for the plugin, this PKGBUILD should be working now with the release.

I'm going to do another update of the ISO and then use it to do an install on my personal laptop and run it as my main/only OS. I should be able to get both done today then I can give you an update in a week or two.


Ambiguous import error with yarn pnp

When I tried to start the dev server with yarn v3 and noderLinker set to pnp, this error appears:
PS C:\Users\user\Documents\sources\appt-frontend> yarn dev
failed to load config from C:\Users\user\Documents\sources\appt-frontend\vite.config.ts
error when starting dev server:
Error: @preact/preset-vite tried to access @babel/core (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.

Required package: @babel/core (via<EMAIL_ADDRESS>Required by: @preact/preset-vite@virtual:477b2cede8cf0bfea85632ec9f519cda9b54e21d6ebc7600dbb0c5d62a8a94da58a04b136c769fefb52b9ee632e2542060b59c08a961728f02ec197b6c2f7b9c#npm:2.5.0 (via C:\Users\user\Documents\sources\appt-frontend\.yarn\__virtual__\@preact-preset-vite-virtual-839bfe540e\0\cache\<EMAIL_ADDRESS>Ancestor breaking the chain: placeholderpt@workspace:.

    at makeError (C:\Users\user\Documents\sources\appt-frontend\.pnp.cjs:11616:34)
    at resolveToUnqualified (C:\Users\user\Documents\sources\appt-frontend\.pnp.cjs:13275:21)
    at Object.resolveToUnqualified (C:\Users\user\Documents\sources\appt-frontend\.pnp.cjs:13518:26)
    at resolve$1 (file:///C:/Users/user/Documents/sources/appt-frontend/.pnp.loader.mjs:1981:31)
    at nextResolve (node:internal/modules/esm/hooks:654:28)
    at Hooks.resolve (node:internal/modules/esm/hooks:309:30)
    at ESMLoader.resolve (node:internal/modules/esm/loader:312:26)
    at ESMLoader.getModuleJob (node:internal/modules/esm/loader:172:38)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:76:40)
    at link (node:internal/modules/esm/module_job:75:36)

You may need to manually add @babel/core to your project's dependencies if Yarn PNP isn't going to install peer deps when they cannot be found.

I also had the same issue. Don't have this issue when using normal react preset

Closing this out, we're not doing anything special or odd with our peer deps here.


[Package Request]: Python.Python.Latest meta package

How can we help?
I would like someone else to build the manifest.
Please read and ensure the following

[X] The installer meets the above requirements

Please provide the following information
Download Page Url: https://github.com/microsoft/winget-pkgs/tree/3b74cb8554db7a74ae03816f5430cf40f7a14e30/manifests/p/Python/Python/3/11/3.11.4
Publisher: Python
Package Name: Python.Python.Latest
Description: metapackage that will pull latest version of python, like in chocolatey https://community.chocolatey.org/packages/python/
Package Version: 3.11.4
Installer URL: https://github.com/microsoft/winget-pkgs/tree/3b74cb8554db7a74ae03816f5430cf40f7a14e30/manifests/p/Python/Python/3/11/3.11.4

If the msstore source is enabled, winget install python will install the latest. If only the winget source is enabled, winget install python3 will install the latest

@Trenly where can i learn about this package aliases like python/python or nodejs?

@Trenly where can i learn about this package aliases like python/python or nodejs?

If you do winget search <query> there may be a column that specified what exactly was matched - in the case of python or nodejs you should see the first option shows that moniker was matched.
The other way is to look at the manifests themselves. If you look at Python.Python.3.11, the defaultLocale manifest contains the moniker.
Unfortunately there isn’t really a good way to get a list of all the monikers directly

@Trenly, thank you!


As an user, I would want to see a snippet creation confirmation page

The existing implementation creates the snippet directly without asking for any confirmation from the user.
The team members used the extension extensively and ran into a situation where multiple snippet files got created.
Analyze and implement the confirmation page in VSCode extension

What I proposed yesterday was adding a confirmation page when copying the existing snippets to the editor, but this is also a possible feature to add.

Fude could you add a screenshot to this issue for better understanding and documenation

The cursor is put on the editor.
Click on the snippet file on the left side
The code snippet is added to the cursor position.
So I want a confirmation page between 2 and 3 to avoid adding by accident, like avoiding deleting by accident.

Yes, indeed that will cost one more click. But in the current extension, double-clicking on the snippet file would add the code snippet twice. I would say this is not a common protocol.

Makes sense. Let's discuss this once with the team in the standup tomorrow.

functionality documentation.pdf
Please take a look at it. I am not sure if I have made my point clear.

Let's go through it as a team today and decide on whether to take this up as a feature tmw

It is an easy implementation. I have done it and uploaded to Fude_Confirmation_Dialogue branch. It should work, at least on my side.
https://github.com/cse210-fa24-group13/codesnip/tree/Fude_Confirmation_Dialogue

Add test cases to the code written for this task


RFC: validate that only a single instance of ServiceLifecycle is created per process

motivation: having multiple instance of ServiceLifecycle generally points to a mistake, which we can help validate
changes: add check in init to validate single instance
alternatively, we may be less rigid, we can move this check to start so multiple instance may be created, but only one started - I think I prefer this option

@tomerd Wanna go forward with this PR?

Going to close this now since our new APIs don't have that restriction.


166 bidding pallet execute bidding workflow periodically

Added periodic call to the bidding pallet

Added BiddingExecutionPeriod in Bidding config pallet
Added hook to call each BiddingExecutionPeriod the bidding workflow

@letodunc can we test that the hook works as intended ?

New session should start the hook
The hook should make the bidding pallet scan

Please before accepting we need the test for the hook transition

I propose to do the test in a second step. For simpliciy, let's merge the #168 and this PR in main as there are changes in #168 impacting #166. The new PR will contains test on periodic call.


npx degit failed due to missing #!/usr/bin/env node line

npx degit https://github.com/xyteam/autobdd-test.git#main autobdd-test
npx: installed 1 in 0.681s
/home/xywang68/.npm/_npx/805/bin/degit: 1: use strict: not found
/home/xywang68/.npm/_npx/805/bin/degit: 3: Syntax error: "(" unexpected

npm install degit and npm install degit and added line:
#!/usr/bin/env node

to  bin/degit solve the problem.

faced the same issue solved it exactly as  @xywang68  did.
Giving a bit more context:
Stumbled upon similar issue:
https://github.com/domenic/worm-scraper/issues/5#issuecomment-321033496
Stack overflow answer
https://stackoverflow.com/a/34354713

the same problem happened to me

Install degit npm install -g degit
Edit degit, add this line #!/usr/bin/env node at the top of the file
nano /usr/local/bin/degit

I'm also getting the same issue. I did the same thing @nashaad did and it works for me.

Had the same issue today (was working fine two days ago).
I noticed I was not using the latest npx version, so I upgraded npm 7.7.6.
As proposed above, I edited degit script and added the following line at the top of the file:
#!/usr/bin/env node

It fixed the issue. I'm on ubuntu 20.04.

Yeah I was teaching a class which I guess was 30 minutes after the update and had the same issue with all my students. Turned it into an impromptu lesson on reading github issues (then they just cloned the starter code). Sounds like a quick fix so hopefully the Saturday class will go smoother :).

Thank you for quick fixes!

https://github.com/Rich-Harris/degit/commit/07222570613a5326db11269c2f8dc0324add765f#diff-f9469b2caca44d79b8f2f7c81296a7b2bf9b19e25fb3e1450b9f4f3bf4117e2b
https://github.com/Rich-Harris/degit/commit/64b80577acf3313b669840f7452800ee8d09fbf3#diff-f9469b2caca44d79b8f2f7c81296a7b2bf9b19e25fb3e1450b9f4f3bf4117e2b

Now v2.8.4 works fine 🎉

YES, Thank you!


Changed alphaMode of materials to OPAQUE.

This should fix #38 for the current models, but we should assure gltf files are exported with alphaMode set to OPAQUE by default.

I think it should implement both options. It could be good to do it when exporting, so we assure the exported models have the correct values, but it would also be good to do it when loading the models, so we cover the case of the user modifying the file with external tools. Maybe we can do like Unreal Engine, and show warnings when loading the models.


Bug: pageNumber not working for Pagination

Info
This is a React specific issue. It has been tested in Chrome, Firefox, and Edge.
On page load, the provided pageNumber value does not show in the Dropdown. It only shows when the user selects a new page.
This is tested with the code provided for the React implementation of Pagination in Storybook.
Acceptance Criteria:

On page load, using React, the dropdown in Pagination should show the beginning page.

:tada: This issue has been resolved in version 1.17.0-alpha.10 :tada:
The release is available on:

npm package (@alpha dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

:tada: This issue has been resolved in version 4.17.0-alpha.10 :tada:
The release is available on:

npm package (@alpha dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

:tada: This issue has been resolved in version 4.18.1 :tada:
The release is available on:

npm package (@latest dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

:tada: This issue has been resolved in version 1.18.1 :tada:
The release is available on:

npm package (@latest dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

:tada: This issue has been resolved in version 2.6.0-alpha.1 :tada:
The release is available on:

npm package (@alpha dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

:tada: This issue has been resolved in version 2.6.0 :tada:
The release is available on:

npm package (@latest dist-tag)
GitHub release

Your semantic-release bot :package::rocket:

This story has been re-opened as it was discovered to be happening again


care empty string of profile image url

fix StringIndexOutOfBoundsException: length=0; regionStart=0; regionLength=-1 when the profile image url is empty (not null).

The profile image url of suspended user (such as temporarily unavailable because it violates the Twitter Media Policy, etc.) is empty.


[Meta issue] Scale types/broken graphs from input data

If you find a graph doesn't work, please add it here for easier tracking. A lot issues probably stem from the same basic issue of recognizing the scale data types properly (linear, ordinal, log, sqrt, pow, quantize, quantile, time and utc)

[ ] Support vector of vectors data type (or document that "long data" is preferred/requirement) #32
[ ] Determine scale types by looking at Julia type and/or "sniffing" first 10-100 rows of data #61
[ ] Line graph doesn't support time series #80
[ ] Heatmap example from vega.js isn't particularly robust #84 #86

The problem as I see it is two/three branches of data cleanliness/differences:

Arrays with a firm Julia type such as Array{Int} or Array{Date}. These should be easy to check for and write subsequent rules
Nullable arrays: I presume these work with the package, since all functions use an AbstractVector type, though I haven't tried yet
Array{Any} arrays will be most difficult, these will need to have type inferred.

Alternatively, could have scale types as a keyword argument, but that feels hacky.

See also #107

The longer this stays open, the more I think that it is really the work of JSON.jl to serialize the data correctly, and most graphs only work with a certain type of data.
Until bugs come in from other people, closing this as "fixed"


Disable screensaver feature from SpecialK

Hello! Any chance you could add the feature to disable screensaver from SpecialK?

Added by default in v0.7.7


Replace MySQL driver with MariaDB driver in documentation examples

Using MySQL driver doesn't work as expected; more information here: https://github.com/HotelsDotCom/circus-train/issues/129

Coverage remained the same at 60.064% when pulling<PHONE_NUMBER>31b28d1c9bd553c22b3557355fb136 on update-docs into 1a856ad91c21e2fdc80568e76858a4b1d07ff8e3 on master.


Add aspnet/Templating to the universe build

Build the templates in a universe build.
Depends on https://github.com/aspnet/templating/pull/58
Resolves #579
cc @SteveSandersonMS

For now, I have not added aspnet/Templating to the tests. I couldn't get them to pass on Windows or Linux. Once we stabilize the tests, we can add this to our build as well.

Merged in https://github.com/aspnet/Universe/commit/446de15f0bc1b8d7d651c5e90c11c0479512e8b8


Fix compose extensions capturing lambda parameters forever

Fixes an issue in cases where side effect collection lambdas capture some outside parameters.
Since we use a LaunchedEffect that lambda would never change, even if the provided one did - resulting in always using the original captured parameters.

LGTM


[ENH] Transformers module full refactor - part II, panel module (1st half)

This PR refactors all transformers in the transformations module to the new interface.
This is part II - a sizeable chunk of the transformations.panel module.
For all transformers, the following was carried out:

inheritance parent is now BaseTransformer
adding tags as appropriate
moving logic to underscore methods _fit, _transform, and _inverse_transform (where applicable)
removal of check/conversion logic which is already covered by BaseTransformer
linting and cleaning up docstrings

Reviewers should focus on individual transformers and the general pattern.
This PR includes bugfixes and changes to BaseTransformer from #1855, these should be reviewed there.
This PR makes the following changes to BaseTransformer:

added requires_y tag for transformers that need a y passed in fit. This is also used in filtering scenarios with y being passed.
raises error if no y is passed but requires_y tag is True
y is converted only if it is not ignored internally (y_inner_mtype is not "None"), otherwise replaced by None
allowed y depend now on type of X. If X is Series, then y must be Series. If X is Panel, y can be Panel or Table.

This PR also contains some changes to individual transformers:

the PCA transformer was not correctly implemented - it returned principal scores (primitives), not the projected principal components (time series). This was fixed, and dependent tests removed.
tests for PCA duplicated tests in the general test suite. These were removed.
Detrender sets its multivariate tag correctly now, depending on the forecaster that is passed
simplified ExponentTransformer to use pandas onboard functionality directly, and removed requirement to run fit (no training is required in a simple exponentiation).
test for TSFreshFeatureExtractor no longer creates unused variables

Further changes:

added a pandas.Series typed Table mtype, to allow y in transformers to be passed as pd.Series if a Table is meant (as in various tests of former "panel-to-tabular" transformers, such as the TSFreshRelevantFeatureExtractor)
changed transform scenarios so number of time points in fit is same as in transform
y argument was missing in the transform of the scenario TransformerFitTransformPanelUnivariateWithClassY, fixed
ShapeDTW called the SlidingWindowSegmenter transformer, assuming numpy3D input and nested_univ output, which was hard-coded in the transformer. As that had changed, convert needed to be introduced.
ShapeDTW was also calling legacy conversion functions. Replaced by suitable convert calls.
_conditional_fixtures now has a functionality to raise errors instead of just passing them. By default, the fixture generation now raises errors if fixture construction fails.
removed strange check in check_series_to_primitive_transform_multivariate that would assert that univariate series-to-primitives transformers always return data frames with 3 columns. Why would that always be true? Must be leftovers from an incomplete coding session.

Dependence on other PR:

test_persistence_via_pickle now uses scenarios, removed _make_args dependency from test_all_estimators entirely https://github.com/alan-turing-institute/sktime/pull/2105

merging after self-review, as discussed in dev meeting.


redesign the access control mechanism

WHAT DOES THIS PR DO?

[x] Creation of the appropriate endpoints for the access control mechanism of the analytics platform. With a focus on mainly four (4) entities which are: Users, Networks, Permissions and Access Tokens
[x] Refactor the entire microservice to meet best practices and improve performance where possible. Apply rate limiting, reorganise files, etc.
[x] Resolve a number of runtime errors in the microsevice.
[ ] Migrate KCCA users data to the AirQo space
[x] Adding scope and expiry dates to user tokens

WHAT ISSUES ARE RELATED TO THIS PR?

[x] Available Users List for Network
[x] v1 Assign User to Network
[x] Assign User to Network
[x] UnAssign User from Network
[x] Set manager for Network
[x] check if network exists using email

Users:

[x] Get Users List: GET /users
[x] Get User Information: GET /user/{usr_uid}
[x] Create User: POST /user
[ ] Upload User Image: POST /user/{usr_uid}/image-upload
[x] Update User Information: PUT /user/{usr_uid}
[x] Delete User: DELETE /user/{usr_uid}
[x] v1.1 Create User
[x] verify email link

Clients

[x] Create Client
[x] Get Clients
[x] Get Client Information
[x] Delete Client
[ ] Update Client Details

Permissions:

[ ] Get Permissions List: GET /permissions
[ ] Get Permission Information: GET /permissions/{perm_id}
[ ] Create Permission: POST /permissions
[ ] Update Permission: PUT /permissions/{perm_id}
[ ] Delete Permission: DELETE /permissions/{perm_id}

Scopes

[x] Create Scope
[ ] Get Scopes
[ ] Get Scope Information
[ ] Delete Scope
[ ] Update Scope Details

Access Tokens:

[x] Get Access Token List: GET /tokens
[x] Get Access Token Information: GET /tokens/{token_id}
[x] Create Access Token: POST /tokens
[x] Update Access Token: PUT /tokens/{token_id}
[x] Delete Access Token: DELETE /tokens/{token_id}
[x] Verify Token

Roles:

[x] Get Roles List: GET /roles
[x] Get Role Information: GET /role/{rol_uid}
[x] Create Role: POST /role
[x] Update Role: PUT /role/{rol_uid}
[x] Delete Role: DELETE /role/{rol_uid}
[x] Get Users with Role: GET /role/{rol_uid}/users
[x] Available Users for Role: GET /role/{rol_uid}/available-users
[x] Assign User to Role: POST /role/{rol_uid}/user
[x] Unassign User from Role: DELETE /role/{rol_uid}/user/{usr_uid}
[ ] Permissions List for Role: GET /role/{rol_uid}/permissions
[ ] Available Permissions for Role: GET /role/{rol_uid}/available-permissions
[ ] Assign Permission to Role: POST /role/{rol_uid}/permission
[ ] Unassign Permission from Role: DELETE /role/{rol_uid}/permission/{per_uid}

Departments:

[ ] Get Departments List: GET /departments
[ ] Get Department Information: GET /department/{dep_uid}
[ ] Create Department: POST /department
[ ] Update Department: PUT /department/{dep_uid}
[ ]  Delete Department: DELETE /department/{dep_uid}
[ ] Get Users List for Department: GET /department/{dep_uid}/assigned-user
[ ] Available Users List for Department: GET /department/{dep_uid}/available-user
[ ] v1: Assign User to Department: PUT /department/{dep_uid}/assign-user/{usr_uid}
[ ] Assign User to Department: POST /department/{dep_uid}/assign-user
[ ] Unassign User from Department: DELETE /department/{dep_uid}/unassign-user/{usr_uid}
[ ] Set Manager for Department: PUT /department/{dep_uid}/set-manager/{usr_uid}

Groups:

[ ] Get Groups List: GET /groups
[ ]  Get Group Information: GET /groups/{grp_uid}
[ ] Create Group: POST /groups
[ ] Update Group: PUT /groups/{grp_uid}
[ ] Delete Group: DELETE /groups/{grp_uid}
[ ] Get Group Members: GET /groups/{grp_uid}/users
[ ] Get Available Users: GET /groups/{grp_uid}/available-users
[ ] Assign User to Group: POST /groups/{grp_uid}/user
[ ] Batch assignment of users to a group: POST /groups/batch-users
[ ] Unassign User from Group: DELETE /groups/{grp_uid}/unassign-user/{usr_uid}

Thanks @Codebmk for this.
The access token requires one to have an account.
These access tokens are additional authentication mechanisms to the existing JWT. They are not replacing the JWTs.
On that note, a guest user implementation is about to be made where a user without an account receives a JWT token assigned to an "anonymous" user.
I am looking forward to more clarification questions.

Awesome to hear. Have you already added the client token field as a parameter to the different endpoints? @Baalmart

Hi @Codebmk that would have to be done at the gateway level. @123MwanjeMike needs to join this conversation asap!

Also @Codebmk please table this for our next sync. Just realised that things might not be obvious.
With our microservice architecture, things are not very straightforward. But we shall handle. 😀😀

Also @Codebmk please table this for our next sync. Just realized that things might not be obvious.
With our microservice architecture, things are not very straightforward. But we shall handle. grinninggrinning

yeah sure


feat: add aplayer shortcode

Close #358

https://6abb2c2b.hugodoit.pages.dev/aplayer-tests/
Managed to get something to work today... :)

Thanks, I have been waiting for this shortcode.


Changed Beta font and font-size

Issue that this pull request solves
Closes: #335
Proposed changes
Changed the font-family and font of beta
Brief description of what is fixed or changed
The font has been changed
Types of changes
Put an x in the boxes that apply

[x] Bugfix (non-breaking change which fixes an issue)
[ ] New feature (non-breaking change which adds functionality)
[ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
[ ] Documentation update (Documentation content changed)
[ ] Other (please describe):

Checklist
Put an x in the boxes that apply

[x] My code follows the style guidelines of this project
[x] I have performed a self-review of my own code
[ ] I have commented my code, particularly in hard-to-understand areas
[ ] I have made corresponding changes to the documentation
[x] My changes generate no new warnings
[x] My changes does not break the current system and it passes all the current test cases.

Screenshots
Please attach the screenshots of the changes made in case of change in user interface

Other information
Any other information that is important to this pull request

Reverted the change in angular.json

Reverted the change in angular.json

LGTM :+1:

LGTM :+1:

LGTM 👍

Thanks, I am from SwoC

LGTM 👍

Thanks, I am from SwoC


Gh 884

Fixes #884

Looks like this PR was done on top of the other PR #894 branch :-)

Though it is just a test and can have any name, I think it is better to update RelaxedPropertiesUtilsTests with the name change as well.

LGTM, merging the changes that are only applicable for #884 and with the changes in RelaxedPropertiesUtilsTests

Merged as 7438fde0884e12f47b9dd3c1eb7fdeb7a4ad07aa along with 934e36ab090558ce3a18bd74393f62daeef19a9b


[#4558] Change the span data type for c++ compatibility

Codecov Report

Merging #5765 into master will decrease coverage by 0.01%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master    #5765      +/-   ##
==========================================
- Coverage   40.66%   40.65%   -0.02%
==========================================
  Files        2923     2923
  Lines       87845    87845
  Branches    11560    11560
==========================================
- Hits        35725    35714      -11
- Misses      49029    49038       +9
- Partials     3091     3093       +2

Impacted Files
Coverage Δ

...vercorp/pinpoint/rpc/packet/ServerClosePacket.java
52% <0%> (-16%)
:arrow_down:

...pc/server/LoggingServerMessageListenerFactory.java
90% <0%> (-10%)
:arrow_down:

...rp/pinpoint/rpc/server/PinpointServerAcceptor.java
84.1% <0%> (-4.64%)
:arrow_down:

.../profiler/sender/StandbySpanStreamDataStorage.java
72.88% <0%> (-3.39%)
:arrow_down:

...navercorp/pinpoint/rpc/common/SocketStateCode.java
82.92% <0%> (-2.44%)
:arrow_down:

...java/com/navercorp/pinpoint/rpc/DefaultFuture.java
72.5% <0%> (-1.67%)
:arrow_down:

.../pinpoint/rpc/client/PinpointClientHandshaker.java
65% <0%> (-1.43%)
:arrow_down:

...orp/pinpoint/rpc/server/DefaultPinpointServer.java
80.98% <0%> (+1.76%)
:arrow_up:

...cluster/zookeeper/ZookeeperClusterDataManager.java
55.41% <0%> (+1.91%)
:arrow_up:

...vercorp/pinpoint/rpc/packet/ClientClosePacket.java
66.66% <0%> (+11.11%)
:arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 111d702...08cb4d6. Read the comment docs.


Upgrade circe to 0.9.0-M1

Circe 0.9.0-M1 was published recently. It is the first circe release using cats 1.0.0-MF. It would be good to have a corresponding akka-http-circe version out, so that people could check their applications for potential problems ahead of cats 1.0.0 releases.

Thanks.
Just publishing 1.19.0-M1 with your PR included.


Installation fails.

Cannot install for the reason that info.plist is missing.
error: Build input file cannot be found: '/Users/dev/Xcode/Examples/ShazamKit-Demo/Application/ShazamKit-Demo/Info.plist' (in target 'ShazamKit-Demo' from project 'ShazamKit-Demo')

Hi @s-ota-66, This is a bug for SwiftUI apps in Xcode 13.
Please follow option 1 of this article to retrieve the property list.

Thank you!
I was able to launch the application.
Thanks for the great program!


Error installing better-sqlite3

Been troubleshooting for a while now.
TRACKER : error TRK0005: Failed to locate: "CL.exe"
I had Python 2.7 and windows-build-tools set up before attempting to install better-sqlite3. I tried re-configuring the build tools with --vs2015/2013/2017 with no success. I've tested other node-gyp dependent packages which built just fine no errors. Double-checked Python 2.7 is in PATH environment variables
Here is one of the log files generated: https://hastebin.com/susediroyi.sql

Small update, I've found that attempting to install quick.db also produces the same error.

This is a duplicate of https://github.com/JoshuaWise/better-sqlite3/issues/73


Unit test failure in TestEtcdraft

Seeing this failure in local environment:
{"level":"debug","msg":"Creating snapshot at index 7 from MemoryStorage","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Persisting snapshot (term: 2, index: 7) to WAL and disk","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Applied config change to remove node 3, current nodes in channel: [1 2]","channel":"multi-node-channel","node":3}
{"level":"info","msg":"This node is being removed from replica set","channel":"multi-node-channel","node":3}
{"level":"info","msg":"Raft node stopped","channel":"multi-node-channel","node":3}
{"level":"info","msg":"Stop garbage collecting","channel":"multi-node-channel","node":3}
{"level":"info","msg":"Stop serving requests","channel":"multi-node-channel","node":3}
{"level":"info","msg":"Periodic check is stopping.","channel":"multi-node-channel","node":3}
{"level":"debug","msg":"Releasing lock to wal files prior to 7","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Raft node stopped","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Stop serving requests","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Periodic check is stopping.","channel":"multi-node-channel","node":1}
{"level":"debug","msg":"Purging in-memory raft entries prior to 6","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Snapshot is taken at index 7","channel":"multi-node-channel","node":1}
{"level":"debug","msg":"Snapshots on disk (3) < limit (4), no need to purge wal/snapshot","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Stop garbage collecting","channel":"multi-node-channel","node":1}
{"level":"debug","msg":"Quit proposing blocks, discarded 0 blocks in the queue","channel":"multi-node-channel","node":1}
{"level":"info","msg":"Raft node stopped","channel":"multi-node-channel","node":2}
{"level":"info","msg":"Stop garbage collecting","channel":"multi-node-channel","node":2}
{"level":"info","msg":"Stop serving requests","channel":"multi-node-channel","node":2}
{"level":"info","msg":"Periodic check is stopping.","channel":"multi-node-channel","node":2}
Send artificial MsgTimeoutNow to elect node 1
STEP: order envelop on node 1 to accumulate bytes

• Failure [0.982 seconds]
Chain
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:101
3-node Raft cluster
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:1556
when 3/3 nodes are running
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:2479
when Snapshotting is enabled
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:2978
take snapshot on accumlated bytes condition met [It]
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:2984
    Expected
        <int>: 2
    to equal
        <int>: 3

    /Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:3056

Summarizing 1 Failure:
[Fail] Chain 3-node Raft cluster when 3/3 nodes are running when Snapshotting is enabled [It] take snapshot on accumlated bytes condition met
/Users/enyeart/work/src/github.com/hyperledger/fabric/orderer/consensus/etcdraft/chain_test.go:3056
Ran 124 of 124 Specs in 68.138 seconds
FAIL! -- 123 Passed | 1 Failed | 0 Pending | 0 Skipped
--- FAIL: TestEtcdraft (68.16s)
2022-03-21 16:25:07.582 EDT 0046 INFO [test] Stop -> Periodic check is stopping.
FAIL
exit status 1
FAIL	github.com/hyperledger/fabric/orderer/consensus/etcdraft	82.570s

Getting the exact same failure in local environment as well. This failure occurs after merging commit fix fabric/orderer unit test flake.

The unittest is failing on some machines because it takes some (variable duration) time to write snapshots to disk and the Expect comparison happens while the write is still in progress, so we get wrong number of snapshots, which is less than the expected number. It is fixed by replacing Expect by Eventually which waits for some time to check the expected values.

Looks like a fix has been merged.  Can this Issue be closed?  Thanks Shivdeep and Julian for tracking this down.


Deploy in Vercel?

Great app! Thank you for sharing this in the community.
Is there instruction on how to deploy this using Vercel?

Will provide a one-click vercel deploy version in the next update

Thank you so much for replying. Looking forward to the next update. Hope it is soon! 😊

This is tricky, because the db.json file is written to, and Vercel doesn't really have a file system. I'm working on something to remove the db.json altogether (assistants list comes from the API, and the OpenAI key is from an environment variable.

is the vercel deploy already there?


Run lint on CI

Codecov Report

Merging #666 (2b404f3) into master (57dee93) will decrease coverage by 0.23%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master     #666      +/-   ##
==========================================
- Coverage   89.80%   89.57%   -0.24%
==========================================
  Files          26       26
  Lines        1726     1726
  Branches      257      257
==========================================
- Hits         1550     1546       -4
- Misses        140      144       +4
  Partials       36       36

Impacted Files
Coverage Δ

vcr/serializers/yamlserializer.py
80.00% <0.00%> (-20.00%)
:arrow_down:

vcr/migration.py
74.48% <0.00%> (-2.05%)
:arrow_down:

:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more


Clarification on reward/value heads in PPOV2

First, thank you for your efforts in helping to bring accurate and performant RLHF techniques to the open-source community.
I'm raising this issue hoping to get some clarification on a couple implementation details in PPOV2:
--- 1 ---
The default AutoModelForSequenceClassification implementation in Transformers uses bias=False for the classification nn.Linear. In a recent fork for training reward models, and alongside the suggestion in The N Implementation Details, the bias is correctly initialised prior to reward model training.
However, when I run the snippet from examples/scripts/ppo/ppo.py for an exemplar RM:
# Load model directly
from transformers import AutoModelForSequenceClassification

reward_model = AutoModelForSequenceClassification.from_pretrained("trl-internal-testing/rm_descriptiveness_1b")

""" output:
config.json: 100%
 869/869 [00:00<00:00, 12.0kB/s]
model.safetensors: 100%
 3.64G/3.64G [02:49<00:00, 25.7MB/s]

Some weights of the model checkpoint at trl-internal-testing/rm_descriptiveness_1b were not used when initializing GPTNeoXForSequenceClassification: ['score.bias']
- This IS expected if you are initializing GPTNeoXForSequenceClassification from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing GPTNeoXForSequenceClassification from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
"""
sd = model.state_dict().items()
"score.bias" in sd
"""
False
"""

Is this expected behaviour - to not use the bias during PPO training?
--2--
In the previous PPO implementation, the value head model is simply another head which shares the base model backbone, however, in PPOV2, it seems the value model is instantiated separately. Is my understanding correct here? If so, I'm curious about the reasoning behind this, since a separate value model would require an additional reward-model-size memory capacity. Do you see an improvment in algorithm performance here?
Many thanks!
P.S. For context, I've been working on a PPO implementation in parallel in Torchtune https://github.com/pytorch/torchtune/pull/1005/, and I've found all the empirical work and implementation details invaluable so far.

Thanks for the issue. Regarding the model
The default AutoModelForSequenceClassification implementation in Transformers uses bias=False for the classification nn.Linear

That is expected because bias cancels out in the RM loss. Here is a script that trains using the said RM
examples/scripts/ppo/ppo.py --output_dir models/minimal/ppo1 --num_ppo_epochs 4 --num_mini_batches 1 --learning_rate 3e-6 --per_device_train_batch_size 32 --gradient_accumulation_steps 16 --local_rollout_forward_batch_size 32 --total_episodes 100000 --model_name_or_path EleutherAI/pythia-1b-deduped --sft_model_path EleutherAI/pythia-1b-deduped --reward_model_path trl-internal-testing/rm_sentiment_1b --kl_coef 0.1 --stop_token period --non_eos_penalty --min_response_length 13 --penalty_reward_value -3

wandb here: https://wandb.ai/costa-huang/huggingface/runs/fmof4oxq/workspace?nw=nwusercostahuang
You can see the model's completion works as intended: the output text becomes more positive.
https://github.com/huggingface/trl/assets/5555347/44538fe2-0fcf-4e24-bcf9-a76ad75641a8

t seems the value model is instantiated separately. Is my understanding correct here?

yes. separate value network is per OpenAI's setting in summarize from feedback and instructGPT

P.S. For context, I've been working on a PPO implementation in parallel in Torchtune https://github.com/pytorch/torchtune/pull/1005, and I've found all the empirical work and implementation details invaluable so far.

that's amazing 💪👍!

Thanks so much for the reply!

Here is a script that trains using the said RM

I've been hunting for this whilst I was doing some replication work against PPOV2 - so helpful, thanks :)

separate value network is per OpenAI's setting in summarize from feedback and instructGPT

I'd be really interested to hear if you have any thoughts on reducing the memory footprint of PPO - I noticed you guys were trying out some PEFT stuff similar to PPOV1, did you end up scaling the PEFT experiments to compare?

Yes peft absolutely helps with the memory. In the N+ impl work @mnoukhov did some peft work and they perform pretty well, too. See screenshot below (missing the 6.9B lora checkpoint results, but it's pretty promising).


runtime: dynamically adjust initial stack size according to workload

The issue
Typical server written in go has the following loop (net/http.Server has similar loop):
for {
    conn := listener.Accept()
    go serveConn(conn)
}

or
for {
    req := getRequest()
    go serveRequest(req)
}

This code starts new goroutine for serving each incoming connection or request. Go runtime starts new goroutines with small initial stack sizes (2KB). This stack may grow if serveConn or serveRequest calls many nested functions. This results in unnecessary CPU time spent in newStack calls for each incoming connection or request. See this article from Uber engineers for details.
The solution
Create new goroutines with dynamic initial stack sizes according to stack size stats from recently exited goroutines. This will eliminate newStack calls in typical server code, including net/http.Server.
The workaround I don't like
To serve connections / requests via goroutine pool. See this article for details.
cc'ing @josharian and @aclements

Dup of #18138


serve_connection_with_upgrades does not enforce its timeout from initial connection, but initial data.

Sysinfo: Hyper 1.4.1 on Darwin 23.6.0 root:xnu-10063.141.2~1/RELEASE_ARM64_T6020 arm64
While l was looking into tokio-rs/axum#2741
I tried this code:
use hyper::{body::Incoming, Request, Response};
use hyper_util::rt::{TokioExecutor, TokioIo, TokioTimer};
use std::convert::Infallible;
use std::time::Duration;
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let listener = TcpListener::bind("<IP_ADDRESS>:3000").await.unwrap();
    loop {
        let (socket, _remote_addr) = listener.accept().await.unwrap();
        tokio::spawn(async move {
            let socket = TokioIo::new(socket);
            let hyper_service =
                hyper::service::service_fn(move |_request: Request<Incoming>| async {
                    let t: Result<_, Infallible> = Ok(Response::new("test".to_string()));
                    t
                });

            let mut server = hyper_util::server::conn::auto::Builder::new(TokioExecutor::new());

            server
                .http1()
                .timer(TokioTimer::new())
                .header_read_timeout(Duration::from_secs(1));

            if let Err(err) = server.serve_connection_with_upgrades(socket, hyper_service).await {
                eprintln!("failed to serve connection: {err:#}");
            }
        });
    }
}

I expected a TCP connection opened to the server terminated after not sending data within one second, however, the connection was persisted indefinitely, and only terminated after some amount of data was sent. However, if instead of serve_connection_with_upgrades, serve_connection is used, and http1_only() is also set, Hyper exhibits the correct behavior

I suspect it's not the upgrades part, but rather the auto part. Since it's doing an initial read to detect the HTTP version before passing on to the http1 state machine which knows about the timeout.

after some further testing, that makes sense. Is this something that hyper-util concerns itself with? Is it not possible to do SlowLoris with HTTP/2.0 in some other way?