Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support snapshots #19

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open

Conversation

neezer
Copy link

@neezer neezer commented Aug 24, 2024

I haven't used Packer or HCL before, but from what I can tell, it looks like this should work.

To install the latest snapshot:

./build.sh 7.6 x86-64 -var checksum=536fda4f519359eebd092900b7ee27986cccb800aee321b3b5d4841d7ce42cd2

closes #18

@jacob-carlborg
Copy link
Contributor

Looks reasonable. A couple of things:

  • Have you tried this?
  • I'm pretty sure the variables needs to be declared upfront, see [1]
  • The checksums need to have a prefix indicating which algorithm. Should this be hardcoded so the user doesn't need to provide it? Either the prefix should be added or the documentation should be updated. See existing checksums:
    checksum = "sha256:05df229dc026785b5b3d1ec8b0dcd46780a2a5bdf99b7e739d83abf4ff7b3ff5"
  • Do you mind adding a test? If it doesn't fit into the existing matrix you can add a new job

Do you plan to use this with the GitHub action [2] or are you only interested in building the image?

[1]

variable "os_version" {
type = string
description = "The version of the operating system to download and install"
}
variable "architecture" {
default = "x86-64"
type = string
description = "The type of CPU to use when building"
}
variable "machine_type" {
default = "pc"
type = string
description = "The type of machine to use when building"
}
variable "cpu_type" {
default = "qemu64"
type = string
description = "The type of CPU to use when building"
}
variable "memory" {
default = 4096
type = number
description = "The amount of memory to use when building the VM in megabytes"
}
variable "cpus" {
default = 2
type = number
description = "The number of cpus to use when building the VM"
}
variable "disk_size" {
default = "12G"
type = string
description = "The size in bytes of the hard disk of the VM"
}
variable "net_device" {
default = "virtio-net"
type = string
description = "The driver to use for the network interface"
}
variable "network_interface" {
default = "vio0"
type = string
description = "The network interface as it's named in OpenBSD"
}
variable "checksum" {
type = string
description = "The checksum for the virtual hard drive file"
}
variable "root_password" {
default = "vagrant"
type = string
description = "The password for the root user"
}
variable "secondary_user_password" {
default = "vagrant"
type = string
description = "The password for the `secondary_user_username` user"
}
variable "secondary_user_username" {
default = "vagrant"
type = string
description = "The name for the secondary user"
}
variable "headless" {
default = false
description = "When this value is set to `true`, the machine will start without a console"
}
variable "use_default_display" {
default = true
type = bool
description = "If true, do not pass a -display option to qemu, allowing it to choose the default"
}
variable "display" {
default = "cocoa"
description = "What QEMU -display option to use"
}
variable "accelerator" {
default = "tcg"
type = string
description = "The accelerator type to use when running the VM"
}
variable "firmware" {
type = string
description = "The firmware file to be used by QEMU"
}
variable "readonly_boot_media" {
default = true
description = "If true, the boot media will be mounted as readonly"
}

[2] https://github.com/cross-platform-actions/action

build.sh Outdated Show resolved Hide resolved
openbsd.pkr.hcl Outdated Show resolved Hide resolved
@neezer
Copy link
Author

neezer commented Aug 24, 2024

Thanks for the quick feedback!

Have you tried this?

Not yet... still figuring out how I would. I need to eventually use this with https://github.com/cross-platform-actions/action, but I still don't have a very good handle about how to test these things locally. Also new to GH Actions in general. 😅

I'm pretty sure the variables needs to be declared upfront

Ahh, probably. As I said I'm new to HCL! I'll update.

The checksums need to have a prefix indicating which algorithm. Should this be hardcoded so the user doesn't need to provide it?

Yup, forgot about these. Considering the OpenBSD mirror site only uses SHA256, I think it's reasonable to hard-code it. I'll update.

Do you plan to use this with the GitHub action [2] or are you only interested in building the image?

My ultimate goal is to use this with https://github.com/cross-platform-actions/action, as I understand this a dependency there. My ultimate-ultimate goal is to build a rust binary for another open source project on GHA that requires rust v1.80, which is only available in snapshots currently.

@neezer
Copy link
Author

neezer commented Aug 24, 2024

Do you mind adding a test?

I don't mind trying! 😎

@neezer
Copy link
Author

neezer commented Aug 24, 2024

Ok. Think I addressed

  • quoting issue with the flags bash array
  • eliminated the new var is_snapshot
  • added an automatic hard-code of the checksum algorithm prefix

I'd love some guidance on

  • how to run this locally; I have an M1 Mac Mini and a few OpenBSD boxes, but no linux machines atm. What would you suggest?
  • how to add a test; not seeing any in the repo currently?

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Aug 25, 2024

I should have asked this from the beginning: do you plan to use a custom image with the GitHub action [1] or do you expect upstream to release snapshot images? A custom image is perfectly fine but unfortunately I do not have the capacity to release snapshot images.

This leads to the next question: does this need to be supported in upstream or is this something that you can do in your fork? In general I would say it should go into a fork. But this has been asked before (#10), and it doesn't seem to complicate the code that much, so I guess I could accept this in upstream.

[1] https://github.com/cross-platform-actions/action?tab=readme-ov-file#custom-vm-image-image_url

@jacob-carlborg
Copy link
Contributor

My ultimate goal is to use this with cross-platform-actions/action, as I understand this a dependency there. My ultimate-ultimate goal is to build a rust binary for another open source project on GHA that requires rust v1.80, which is only available in snapshots currently.

Keep in mind that there's no guarantee that a custom version will work in the future, or at all. Custom images are intended for doing work ahead of time of existing supported operating systems and versions.

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Aug 25, 2024

how to run this locally; I have an M1 Mac Mini and a few OpenBSD boxes, but no linux machines atm. What would you suggest?

I have an M1 Mac as well, so that's perfectly fine 😃. It's documented in the readme: https://github.com/cross-platform-actions/openbsd-builder?tab=readme-ov-file#building-locally. Please let me know if anything is not clear or missing and I can update the documentation. Packer and QEMU are available from Homebrew.

@jacob-carlborg
Copy link
Contributor

how to add a test; not seeing any in the repo currently?

The test is just building the image, which you already have added a job for 👍. Is the only difference the extra checksum variable? https://github.com/cross-platform-actions/openbsd-builder/pull/19/files#diff-5c3fa597431eda03ac3339ae6bf7f05e1a50d6fc7333679ec38e21b337cb6721R145. If that's the case, we should try to add it to the existing job, otherwise there's a lot of duplication. I'll give it some thought how to do that.

@jacob-carlborg
Copy link
Contributor

Not yet... still figuring out how I would. I need to eventually use this with cross-platform-actions/action, but I still don't have a very good handle about how to test these things locally. Also new to GH Actions in general. 😅

There's some documentation how to run the GH action locally in the action repository [1]. Please let me know if anything is not clear or missing and I can update the documentation.

[1] https://github.com/cross-platform-actions/action?tab=readme-ov-file#local-development

@jacob-carlborg
Copy link
Contributor

readme.md Outdated Show resolved Hide resolved
@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Aug 25, 2024

BTW, what is a snapshot? Is that like the next upcoming version? So now it's what will become OpenBSD 7.6 and eventually it will become 8.0?

@neezer
Copy link
Author

neezer commented Aug 25, 2024

It fails to build the snapshot image

Yeah, I accidentally inverted the logic for using a snapshot URL, resulting in a 404. Updated.

@neezer
Copy link
Author

neezer commented Aug 25, 2024

BTW, what is a snapshot? Is that like the next upcoming version?

OpenBSD commits to releases every 6 months. These are 7.3, 7.4, 7.5, etc.

Concurrently, they also release snapshot images at more frequent--yet less predictable--intervals between releases.

-current: The development branch. Every six months, -current is tagged and becomes the next release.

Snapshots of the -current branch are made available between formal releases of OpenBSD. These are builds of whatever code is in the tree at the time.

Snapshots contain more up-to-date ports and packages. In my case, the latest snapshot includes Rust v1.80, whereas the last release of OpenBSD includes v1.75. The project I'm trying to support on OpenBSD requires Rust >= v1.77, so building on OpenBSD 7.5 fails.

The update to the test GHA workflows does present a bit of a problem for maintenance on this project, which is what I think you're getting at with your line of questioning, as that SHA will change as new snapshots are released, and this will happen more frequently than stable releases (though in my experience, they don't release too often... I feel like the cadence is measured more in weeks than days, but that is more frequent than 6 months).

IMO it would be great to support this in upstream, though I confess I'm still a bit fuzzy about how your releases are structured, and how artifacts from this repo are consumed and used in cross-platform-actions/action. Given that various projects that lack OpenBSD support tend to move faster than the OpenBSD stable release cycle--and that many of those projects utilize GitHub Actions for their CI--it would be awesome if this behavior for building snapshots were made cannon and not confined to a fork... but I don't know what kind of additional overhead that would demand of you or other project maintainers.

I'm not sure I totally answered your question, but hopefully that made sense.

@neezer
Copy link
Author

neezer commented Aug 26, 2024

... as that SHA will change as new snapshots are released, and this will happen more frequently than stable releases ...

Case in point, there is a new snapshot release since I opened this PR:

- 536fda4f519359eebd092900b7ee27986cccb800aee321b3b5d4841d7ce42cd2
+ 92fe4343d60a963c1070ebd08f496070493bc9ea9c946b56d5dfb98fe880bb0a

@neezer
Copy link
Author

neezer commented Aug 26, 2024

I have an M1 Mac as well, so that's perfectly fine 😃. It's documented in the readme: https://github.com/cross-platform-actions/openbsd-builder?tab=readme-ov-file#building-locally. Please let me know if anything is not clear or missing and I can update the documentation. Packer and QEMU are available from Homebrew.

Installed packer & QEMU via homebrew. Still unclear where I should be sourcing resources/ovmf.fd as I don't have a Linux box. Is it possible to download it from somewhere?

@neezer
Copy link
Author

neezer commented Aug 26, 2024

Is the only difference the extra checksum variable? https://github.com/cross-platform-actions/openbsd-builder/pull/19/files#diff-5c3fa597431eda03ac3339ae6bf7f05e1a50d6fc7333679ec38e21b337cb6721R145. If that's the case, we should try to add it to the existing job, otherwise there's a lot of duplication. I'll give it some thought how to do that.

Think this'll work: e195f91

@jacob-carlborg
Copy link
Contributor

Perhaps you should run the CI workflow on your fork and make sure it works there first. Since you're a first time contributor GitHub requires me to approve the workflow to be run and apparently I need to approve it every time you make a change.

@neezer
Copy link
Author

neezer commented Aug 27, 2024

Perhaps you should run the CI workflow on your fork and make sure it works there first. Since you're a first time contributor GitHub requires me to approve the workflow to be run and apparently I need to approve it every time you make a change.

Ugh, sorry, that sounds annoying. Got them running on my repo, so I've got a more independent feedback loop now. My bad.

I got the newer snapshots building in GHA; there are two failures for older stable releases that look like timeouts (eg., not related to my changes): https://github.com/neezer/openbsd-builder/actions/runs/10585228557

Think I'm ready for a proper re-review now. If the commit history is too spammy, I'm happy to close this PR and re-open with a collapsed git history. Lemme know.

@jacob-carlborg
Copy link
Contributor

I got the newer snapshots building in GHA; there are two failures for older stable releases that look like timeouts (eg., not related to my changes): neezer/openbsd-builder/actions/runs/10585228557

Yeah, that looks unrelated.

@jacob-carlborg
Copy link
Contributor

Installed packer & QEMU via homebrew. Still unclear where I should be sourcing resources/ovmf.fd as I don't have a Linux box. Is it possible to download it from somewhere?

Not anywhere reliable that I have found. I copied it out from a Docker container.

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Aug 28, 2024

IMO it would be great to support this in upstream, though I confess I'm still a bit fuzzy about how your releases are structured, and how artifacts from this repo are consumed and used in cross-platform-actions/action

The full process to add support for a new version of an existing operating system and architecture is, in a best case scenario:

  1. Add the variable files with the checksums
  2. Create a git tag
  3. Pushing the tag will automatically build and create a GitHub draft release (https://github.com/cross-platform-actions/openbsd-builder/releases/latest)
  4. Manually publish the release
  5. Update the GitHub action to use the new release of the operating system (https://github.com/cross-platform-actions/action/blob/c5ad83c5341f4b43b5e6afe6315fb23d5047d3b8/src/version.ts#L5)
  6. Update the changelog
  7. Update the readme with the new version, both in the table of available versions and the examples (which should always use the latest versions)
  8. Create a git tag in the GitHub action
  9. Pushing the tag will automatically build and create a GitHub draft release for the GitHub action
  10. Manually publish the release

Of course, if upstream did break something then I'm in for a debugging session to figure out what has changed and try to adopt for the new behavior, ideally without breaking any existing versions. It's this part I'm most worried about. It can require changes to the GitHub action as well. Another part I'm not entirely sure about is how to know when a new snapshot is available. Currently I'm subscribed to a couple of mailing lists which posts when a new version is available. But I have not seen any updates on new snapshots. I don't want to look every day if a new snapshot is available. Perhaps a scheduled GitHub action workflow could do that, but those will be disabled after 60 days if there's been no changes to the repository.

@jacob-carlborg
Copy link
Contributor

For snapshots to work I need to figure out how to do this without having to update the Github action every time a new snapshot is available.

@neezer
Copy link
Author

neezer commented Aug 28, 2024

The full process ... is ...

For snapshots to work I need to figure out how to do this without having to update the Github action every time a new snapshot is available.

Thanks for the detailed explanation. Is this because the Packer images are pre-compiled for use by cross-platform-actions/action? If so, what about building the snapshot images on-demand instead? That definitely wouldn't make cross-platform-actions/action as fast & snappy for snapshots as it is for stable releases, but IMO that would be an acceptable trade-off. That would also save you from the need to track when new snapshots are available, since my most recent changes will always pull the latest one (note that .github/workflows/build.yml no longer includes the SHA of the latest snapshot).

@neezer
Copy link
Author

neezer commented Aug 28, 2024

Another part I'm not entirely sure about is how to know when a new snapshot is available. ... I don't want to look every day if a new snapshot is available. Perhaps a scheduled GitHub action workflow could do that, but those will be disabled after 60 days if there's been no changes to the repository.

I think the most reliable way is to schedule (eg., cron or similar) a curl call to an OpenBSD mirror to check the SHAs in snapshots/<arch>/SHA256. A scheduled GHA could work here--as you said--though there is no guarantee that there will be a new snapshot release within 60 days of the last one.

Anecdotally, I'd say it is 99.9% likely that there will be a new release within 60 days of the last one.

If snapshots were built on-demand, then this complication is voided, as I understand it.

@jacob-carlborg
Copy link
Contributor

Is this because the Packer images are pre-compiled for use by cross-platform-actions/action

Partly. I could point the action to the latest release of each operating system, instead of a hardcoding the version. But I'm working hard to not break the action. If you stick to a given version of the action it should ideally never break. I've worked very hard and spent a lot of time avoid breaking the action. GitHub has already broken the action a couple of times. Since things happen outside my control every time I build this repository there's a risk that something will break. I had to jump through hoops to avoid removing FreeBSD 12.x, because upstream had removed the package repository. Same with OpenBSD. I found a mirror that keeps old releases.

If so, what about building the snapshot images on-demand instead? That definitely wouldn't make cross-platform-actions/action as fast & snappy for snapshots as it is for stable releases, but IMO that would be an acceptable trade-off.

No, I don't think that's an acceptable trade-off. As you can see it takes between 15 and 20 minutes to build an image. If your job only takes a minute, or less, it's a huge overhead. Also, there are more moving parts, more dependencies outside my control. As you noticed, one of the jobs failed in a way unrelated to your change: https://github.com/neezer/openbsd-builder/actions/runs/10585228557.

@jacob-carlborg
Copy link
Contributor

I prefer the scheduled approach better. I don't mind enabling the job if GitHub disables it every 60 days. I get an email when it happens.

@neezer
Copy link
Author

neezer commented Aug 29, 2024

But I'm working hard to not break the action. If you stick to a given version of the action it should ideally never break. I've worked very hard and spent a lot of time avoid breaking the action.

👏🏻 This is a great goal! Thanks for your effort! For stable releases I'm 💯 on board with this.

I'm less convinced this level of effort is warranted (or even desired) for snapshots. I'm not aware of the official OpenBSD mirrors hosting snapshots older than whatever the current one is; I suppose your special mirror might.

If so, what about building the snapshot images on-demand instead? That definitely wouldn't make cross-platform-actions/action as fast & snappy for snapshots as it is for stable releases, but IMO that would be an acceptable trade-off.

No, I don't think that's an acceptable trade-off. As you can see it takes between 15 and 20 minutes to build an image. If your job only takes a minute, or less, it's a huge overhead.

If the images are persisted on the disk of the runner, they could be cached. Then you'd only pay the penalty on the initial build of a new snapshot release. Just trying to think of ways to reduce the operational complexity.

To be clear, I intended my earlier suggestion to pertain only to snapshots, not stable releases. But perhaps this bifurcates the user experience of this action too much?

@jacob-carlborg
Copy link
Contributor

I'm less convinced this level of effort is warranted (or even desired) for snapshots

No, definitely not. It's not something I ever considered.

To be clear, I intended my earlier suggestion to pertain only to snapshots, not stable releases. But perhaps this bifurcates the user experience of this action too much?

Yeah, I understood that. I don't mind the snapshots not being a stable as the rest. It just needs to be clearly documented.

The problem is, as the PR is implemented now, building a stable release can break due to a snapshot not building. The opposite is true as well, that is, building a snapshot could fail due to a stable release failing. Most likely an old release would fail. That's also one reason why the job, when it creates a release, it creates a draft release. Because I need to make sure that all jobs in the matrix has completed successfully before I can publish the release.

Here's an idea how to fully automate this and still build the images ahead of time:

  1. Create a scheduled GitHub action workflow. This can run every day and just terminate if there has not been a new snapshot sine the last run
  2. Separate the stable releases from the snapshots
  3. The scheduled workflow only builds the snapshots and the stable release are handled the same way as they are today
  4. To make sure all snapshots in the matrix have completed successfully before the release is created, the release step is moved to its own job. Then this will have the previous jobs as a dependency. This means it will not run until all the dependencies have completed successfully. The main job will store the built image in the GitHub cache/artifact instead of directly uploading it to a release
  5. The release job extracts the images from the cache and creates a release that is immediately published, instead of creating a draft release. Then I don't have to manually publish it as I have to do today
  6. Instead of creating a new release every time I hope it's possible to reuse a single release and update that with new images. I hope it will just overwrite the existing images if they have the same names. Or GitHub artifacts can be used. This needs some investigation. In the case of snapshots I don't think release are very interesting, we just need somewhere to store the images so I think reusing a release would be fine.
  7. Then a new property is added here [1], something like openbsd_snapshot: "snapshot"
  8. The action would always fetch snapshot images from the same URL
  9. The user would specify snapshot as the version for OpenBSD and get whatever version they get. It might not always work or get the latest snapshot if a build has failed.

[1] https://github.com/cross-platform-actions/action/blob/c5ad83c5341f4b43b5e6afe6315fb23d5047d3b8/src/version.ts#L6

@neezer
Copy link
Author

neezer commented Sep 3, 2024

  1. Instead of creating a new release every time I hope it's possible to reuse a single release and update that with new images. I hope it will just overwrite the existing images if they have the same names. Or GitHub artifacts can be used. This needs some investigation. In the case of snapshots I don't think release are very interesting, we just need somewhere to store the images so I think reusing a release would be fine.

I'm no expert, but my understanding is that releases are intended to be immutable. Even if it were possible to rewrite assets for an existing release, I'm not sure it's advisable to do so if it bucks the well-understood mental model.

I think rather than try to mutate an existing release, we should be creating new releases with some modifier, eg. v0.8.0-p123. The modifier could be an auto-incrementing integer, or a date, but something that is sortable. Or you could implement mixed-type releases like this project, where you could release new snapshots alongside main stable releases.

Then we'd change this step

  1. The action would always fetch snapshot images from the same URL

... to ...

  1. The action would always fetch the latest snapshot image available.

This also changes the following step:

  1. The user would specify snapshot as the version for OpenBSD and get whatever version they get. It might not always be the latest snapshot if the most recent build failed, but they're guaranteed to get at least some snapshot version.

This probably means a touch more work in cross-platform-actions/action to implement "would always fetch the latest snapshot image available."

Thoughts?

@jacob-carlborg
Copy link
Contributor

Or you could implement mixed-type releases like this project, where you could release new snapshots alongside main stable releases

The snapshot release in that project is a separate release. The snapshot release is attached to a tag called latest. So they have to change the git tag, which I think is just as bad as changing a release. I also don't see multiple snapshot releases, so they're probably modifying/overwriting the release, just as I suggested.

I don't know how you would access the latest release without doing this. You can access the latest release, but that might be a snapshot release or a stable release.

@jacob-carlborg
Copy link
Contributor

jacob-carlborg commented Sep 3, 2024

It doesn't need to be a GitHub release. It just needs to be somewhere to store the images in the cloud with a stable URL. Something free and reliable. Perhaps a GitHub artifact could work.

@neezer
Copy link
Author

neezer commented Sep 3, 2024

Or you could implement mixed-type releases like this project, where you could release new snapshots alongside main stable releases

The snapshot release in that project is a separate release. The snapshot release is attached to a tag called latest. So they have to change the git tag, which I think is just as bad as changing a release. I also don't see multiple snapshot releases, so they're probably modifying/overwriting the release, just as I suggested.

I don't know how you would access the latest release without doing this. You can access the latest release, but that might be a snapshot release or a stable release.

I was referring to the releases for autofill-parser, not for the main project. Apologies if that was unclear. The tags for those releases have a prefix that separates them from the main release, eg. autofill-parser-v1.1.1 instead of just v1.1.1.

I was thinking you could continue to do mainline releases with v0.8.0 and also publish snapshot-v123 or snapshot-v20240801. Then you could get a list of all releases, filter the list down to those that have the prefix snapshot-, sort descending, and take the head of the list.

@neezer
Copy link
Author

neezer commented Sep 10, 2024

@jacob-carlborg Nudge on my last comment. 😎

@jacob-carlborg
Copy link
Contributor

Yeah, sorry, I've been really busy. I think your suggestion is more complicated than it needs to be. I want to explore other options. IIRC, GitHub has some artifact registry, perhaps that can be used. Do you have time to look that up?

@neezer
Copy link
Author

neezer commented Sep 11, 2024

Yeah, sorry, I've been really busy.

I know how that goes. Thanks again for your time and effort devoted to this project! 👏🏻

I think your suggestion is more complicated than it needs to be. I want to explore other options. IIRC, GitHub has some artifact registry, perhaps that can be used. Do you have time to look that up?

I can try.

I think we're agreed on steps 1-5. Maybe we could move ahead with those changes while we continue to mull over the remaining steps? Seems like that automation would be useful to you regardless of what approach we think is best for snapshots specifically.

@jacob-carlborg
Copy link
Contributor

GitHub has some artifact registry, perhaps that can be used

The GitHub registry feature cannot be used. It's for package managers, like NPM, RubyGems, Debian packages and so on. Not for arbitrary files.

@neezer neezer mentioned this pull request Sep 19, 2024
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Current?
2 participants