Skip to content

Swap from 'package' to 'instance' and use new v1 API where able#225

Open
chrisghill wants to merge 3 commits intomainfrom
package-to-instance-switch
Open

Swap from 'package' to 'instance' and use new v1 API where able#225
chrisghill wants to merge 3 commits intomainfrom
package-to-instance-switch

Conversation

@chrisghill
Copy link
Copy Markdown
Member

No description provided.

@chrisghill chrisghill requested a review from coryodaniel as a code owner March 23, 2026 23:29
Deprecated: "This has been moved under `package`. This command will be removed in v2.",
Args: cobra.ExactArgs(1),
RunE: runPkgConfigure,
RunE: runInstanceConfigure,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should drop application command for our v1 release.

"testing"

"github.com/massdriver-cloud/mass/internal/api"
"github.com/massdriver-cloud/mass/internal/api/v0"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we shoud keep v0 in the next release at all. I think we just make a new major version of the cli that is for our v1 and drop v0. the API still exists, if someone wants to call it they can use the old CLI for now

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely agree, I was just planning for this to be iterative as apposed to all-at-once. We can swap everything over v1 in a single PR if you prefer.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the CLI and internal API client to align terminology around “instances” (vs “packages”) and introduces a new internal/api/v1 client where available, while moving the existing GraphQL client to internal/api/v0.

Changes:

  • Split the internal API client into versioned packages (internal/api/v0 and internal/api/v1) and update call sites/imports accordingly.
  • Replace the top-level mass package command implementation with mass instance (keeping legacy naming via aliases) and adjust templates/docs.
  • Update various commands and TUIs to use the versioned API clients and new URL helper semantics.

Reviewed changes

Copilot reviewed 91 out of 136 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
internal/tui/components/artifacttable/model.go Switch TUI component to import internal/api/v0.
internal/tui/components/artifacttable/model_test.go Update tests to use internal/api/v0.
internal/tui/components/artdeftable/model.go Switch TUI component to import internal/api/v0.
internal/tui/components/artdeftable/model_test.go Update tests to use internal/api/v0.
internal/definition/publish.go Update definition publishing to use internal/api/v0.
internal/definition/publish_test.go Update tests to use internal/api/v0.
internal/definition/get.go Update definition retrieval to use internal/api/v0.
internal/definition/get_test.go Update tests to use internal/api/v0.
internal/definition/delete.go Update definition deletion to use internal/api/v0.
internal/commands/project/export.go Update project export command to use internal/api/v0.
internal/commands/preview/new.go Update preview flow to use internal/api/v0.
internal/commands/preview/new_test.go Update tests to use internal/api/v0.
internal/commands/preview/model.go Update preview model to use internal/api/v0.
internal/commands/preview/deploy.go Update preview deploy to use internal/api/v0.
internal/commands/preview/deploy_test.go Update tests to use internal/api/v0.
internal/commands/preview/decommission.go Update preview decommission to use internal/api/v0.
internal/commands/instance/reset.go Rename package to instance command package and move to internal/api/v0.
internal/commands/instance/reset_test.go Update reset tests for instance terminology and v0 API.
internal/commands/instance/patch.go Rename package to instance command package and move to internal/api/v0.
internal/commands/instance/patch_test.go Update patch tests for instance terminology and v0 API.
internal/commands/instance/export.go Rename package to instance command package and move to internal/api/v0.
internal/commands/instance/export_test.go Update export tests for instance terminology and v0 API.
internal/commands/instance/deploy.go Rename package to instance and update deploy docs/vars and v0 API import.
internal/commands/instance/deploy_test.go Update deploy tests to use internal/api/v0 and commands/instance.
internal/commands/instance/configure.go Rename package to instance and update v0 API import.
internal/commands/instance/configure_test.go Update configure tests to use internal/api/v0 and commands/instance.
internal/commands/image/push.go Update image push to use internal/api/v0.
internal/commands/image/push_test.go Update image push tests to use internal/api/v0.
internal/commands/image/docker_client.go Update docker client integration to use internal/api/v0.
internal/commands/environment/export.go Swap environment export to use commands/instance and internal/api/v0.
internal/commands/bundle/pull.go Update bundle pull to use internal/api/v0.
internal/commands/bundle/publish.go Update bundle publish to use internal/api/v0.
internal/commands/artifact/update.go Update artifact update to use internal/api/v0.
internal/commands/artifact/import.go Update artifact import to use internal/api/v0.
internal/artifact/import_prompt.go Update artifact import prompting to use internal/api/v0.
internal/api/v1/tools.go Add tools-only file to pin genqlient generator deps.
internal/api/v1/scalars/json.go Add v1 JSON scalar marshaling/unmarshaling helpers.
internal/api/v1/scalars/json_test.go Add tests for scalar JSON helpers.
internal/api/v1/scalars/cursor.go Add v1 Cursor scalar struct.
internal/api/v1/project.go Implement v1 Project API wrapper functions.
internal/api/v1/project_test.go Add tests for v1 Project API wrappers.
internal/api/v1/main.go Add go:generate for genqlient in v1.
internal/api/v1/instance.go Add v1 Instance model.
internal/api/v1/genqlient.yaml Configure genqlient generation/bindings for v1.
internal/api/v1/genqlient.graphql Add v1 GraphQL operations (projects/environments).
internal/api/v1/error.go Add v1 mutation error type.
internal/api/v1/environment.go Implement v1 Environment API wrapper functions.
internal/api/v1/environment_test.go Add tests for v1 Environment API wrappers.
internal/api/v1/cost.go Add v1 cost models.
internal/api/v1/bundle.go Add v1 bundle model.
internal/api/v1/blueprint.go Add v1 blueprint model.
internal/api/v0/zz_generated.go Update generated v0 client imports and deployedVersion pointer handling.
internal/api/v0/urls.go Rename URL helper methods and shift naming toward IDs/instances.
internal/api/v0/server.go Add v0 Server API wrapper.
internal/api/v0/server_test.go Update server tests to use internal/api/v0.
internal/api/v0/scalars/json.go Add v0 JSON scalar marshaling/unmarshaling helpers.
internal/api/v0/scalars/json_test.go Update scalar tests to use internal/api/v0/scalars.
internal/api/v0/scalars/cursor.go Add v0 Cursor scalar struct.
internal/api/v0/repo.go Update repo client to use versioned scalars import.
internal/api/v0/repo_test.go Update repo tests to use internal/api/v0.
internal/api/v0/project.go Add v0 Project API wrapper (migrated from unversioned).
internal/api/v0/project_test.go Update project tests to use internal/api/v0.
internal/api/v0/preview_environment.go Add v0 preview environment API wrapper.
internal/api/v0/preview_environment_test.go Update preview env tests to use internal/api/v0.
internal/api/v0/preview_config.go Add v0 preview config models.
internal/api/v0/preview_config_test.go Update preview config tests to use internal/api/v0.
internal/api/v0/package.go Add v0 Package API wrapper/models with pointer deployedVersion handling.
internal/api/v0/package_test.go Update package tests to use internal/api/v0.
internal/api/v0/oci.go Add v0 OCI repo wrapper.
internal/api/v0/oci_test.go Update OCI tests to use internal/api/v0.
internal/api/v0/manifest.go Add v0 manifest wrapper.
internal/api/v0/main.go Add go:generate for genqlient in v0.
internal/api/v0/genqlient.yaml Fix v0 genqlient bindings to point to internal scalars.
internal/api/v0/genqlient.graphql Add v0 GraphQL operations file for genqlient.
internal/api/v0/error.go Add v0 mutation error type.
internal/api/v0/error_test.go Update error tests to use internal/api/v0.
internal/api/v0/environment.go Add v0 Environment wrapper/model (includes URL helper).
internal/api/v0/environment_test.go Update environment tests to use internal/api/v0.
internal/api/v0/deployment.go Add v0 deployment wrapper/models and log retrieval.
internal/api/v0/deployment_test.go Update deployment tests to use internal/api/v0.
internal/api/v0/credential.go Add v0 credential/artifact listing helpers.
internal/api/v0/credential_test.go Update credential tests to use internal/api/v0.
internal/api/v0/cost.go Add v0 cost models.
internal/api/v0/container_repository.go Add v0 container repository wrapper.
internal/api/v0/container_repository_test.go Update container repository tests to use internal/api/v0.
internal/api/v0/bundle.go Add v0 bundle wrapper.
internal/api/v0/bundle_test.go Update bundle tests to use internal/api/v0.
internal/api/v0/artifact.go Add v0 artifact CRUD wrappers.
internal/api/v0/artifact_test.go Update artifact tests to use internal/api/v0.
internal/api/v0/artifact_definitions.go Add v0 artifact definition wrappers.
internal/api/v0/artifact_definitions_test.go Update artifact definition tests to use internal/api/v0.
internal/api/main.go Remove unversioned internal/api entrypoint.
go.sum Update sums for new dependencies / sdk version.
go.mod Update Go version directive and bump massdriver-sdk-go requirement.
docs/helpdocs/instance/version.md Add instance command helpdoc (currently still package-centric wording/examples).
docs/helpdocs/instance/reset.md Add instance reset helpdoc (currently still package-centric wording/examples).
docs/helpdocs/instance/patch.md Add instance patch helpdoc.
docs/helpdocs/instance/list.md Add instance list helpdoc.
docs/helpdocs/instance/get.md Add instance get helpdoc.
docs/helpdocs/instance/export.md Add instance export helpdoc.
docs/helpdocs/instance/deploy.md Add instance deploy helpdoc.
docs/helpdocs/instance/create.md Add instance create helpdoc.
docs/helpdocs/instance/configure.md Add instance configure helpdoc.
docs/helpdocs/instance.md Add top-level instance helpdoc page.
docs/generated/mass.md Update generated CLI docs index to list mass instance instead of mass package.
docs/generated/mass_instance.md Add generated docs for instance root command.
docs/generated/mass_instance_version.md Add generated docs for instance version subcommand.
docs/generated/mass_instance_reset.md Add generated docs for instance reset subcommand.
docs/generated/mass_instance_patch.md Add generated docs for instance patch subcommand.
docs/generated/mass_instance_list.md Add generated docs for instance list subcommand.
docs/generated/mass_instance_get.md Add generated docs for instance get subcommand.
docs/generated/mass_instance_export.md Add generated docs for instance export subcommand.
docs/generated/mass_instance_destroy.md Add generated docs for instance destroy subcommand.
docs/generated/mass_instance_deploy.md Add generated docs for instance deploy subcommand.
docs/generated/mass_instance_create.md Add generated docs for instance create subcommand.
docs/generated/mass_instance_configure.md Add generated docs for instance configure subcommand.
cmd/version.go Switch CLI version command to import internal/api/v0.
cmd/templates/project.get.md.tmpl Update project template fields (ID + new cost field names).
cmd/templates/instance.get.md.tmpl Add new instance “get” template (renders v0 Package as instance).
cmd/templates/environment.get.md.tmpl Update environment template to v1 fields/instances list and new cost fields.
cmd/root.go Swap root command from NewCmdPkg() to NewCmdInstance().
cmd/project.go Update project CLI to v1 project APIs and adjust displayed fields/URLs.
cmd/preview.go Switch preview command to import internal/api/v0.
cmd/package.go Remove legacy mass package command implementation.
cmd/logs.go Switch logs command to import internal/api/v0.
cmd/instance.go Add new mass instance command implementation (replacement for package).
cmd/infrastructure.go Update deprecated infra command wiring to point at instance handlers/flags.
cmd/environment.go Update environment CLI to use v1 for get/create and v0 for list/default URL helper.
cmd/definition.go Switch definition command to import internal/api/v0.
cmd/credential.go Switch credential command to import internal/api/v0.
cmd/bundle.go Switch bundle command to import internal/api/v0.
cmd/artifact.go Switch artifact command to import internal/api/v0.
cmd/application.go Update deprecated app command wiring to point at instance handlers/flags.
Comments suppressed due to low confidence (1)

internal/api/v0/urls.go:53

  • InstanceURL’s doc comment still says it returns a URL for a "package". Since this helper was renamed to InstanceURL, update the comment to refer to an instance (and consider mentioning that the query parameter name is still package if that’s intentional for the app URL scheme).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +3 to +8
import (
"reflect"
"testing"

"github.com/massdriver-cloud/mass/internal/api/v0/scalars"
)
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test file is in the v1 scalars package but it imports and exercises the v0 scalars implementation, so it won’t catch regressions in internal/api/v1/scalars. Import internal/api/v1/scalars here (or alias the import) so the v1 bindings are actually tested.

Copilot uses AI. Check for mistakes.
Comment on lines +7 to 12
## Instances
| Name | Bundle | Status |
| ---- | ------ | ------ |
{{- range .Packages}}
| **{{.Manifest.Name}}** | {{.Bundle.Name}} | {{.Status}} |
{{- range .Blueprint.Instances}}
| **{{.Name}}** | {{.Bundle.Name}} | {{.Status}} |
{{- end}}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This template ranges over .Blueprint.Instances unconditionally. In the v1 API conversion, Blueprint is only set when there are instances, so .Blueprint can be nil and this will error at render time for environments with zero instances. Guard with an {{if .Blueprint}}...{{end}} (or ensure Blueprint is always non-nil in the API type).

Copilot uses AI. Check for mistakes.
if err == nil && instanceDetails.Environment != nil && instanceDetails.Environment.Project != nil && instanceDetails.Manifest != nil {
urlHelper, urlErr := apiv0.NewURLHelper(ctx, mdClient)
if urlErr == nil {
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, instanceDetails.Manifest.ID))
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL is built using instanceDetails.Manifest.ID as the package query parameter. Elsewhere (e.g., create) this helper is called with the manifest slug, and the actual instance/package also has its own ID. Please use a single, correct identifier consistently (likely instanceDetails.ID if the UI expects the package/instance ID, or instanceDetails.Manifest.Slug if it expects the manifest slug), otherwise the generated link can point to the wrong canvas node.

Suggested change
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, instanceDetails.Manifest.ID))
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, instanceDetails.ID))

Copilot uses AI. Check for mistakes.
if err == nil && instanceDetails.Environment != nil && instanceDetails.Environment.Project != nil && instanceDetails.Manifest != nil {
urlHelper, urlErr := apiv0.NewURLHelper(ctx, mdClient)
if urlErr == nil {
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, instanceDetails.Manifest.ID))
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as configure: this URL uses instanceDetails.Manifest.ID for the package query parameter. Use the correct identifier consistently (instance/package ID vs manifest slug) to avoid generating broken links.

Suggested change
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, instanceDetails.Manifest.ID))
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instanceDetails.Environment.Project.ID, instanceDetails.Environment.ID, updatedPkg.ID))

Copilot uses AI. Check for mistakes.
Comment on lines +484 to +487
if instance.Environment != nil && instance.Environment.Project != nil && instance.Manifest != nil {
urlHelper, urlErr := apiv0.NewURLHelper(ctx, mdClient)
if urlErr == nil {
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instance.Environment.Project.ID, instance.Environment.ID, instance.Manifest.ID))
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same issue as configure/version: this URL uses instance.Manifest.ID for the package query parameter. Use the correct identifier consistently (instance/package ID vs manifest slug) to avoid generating broken links.

Suggested change
if instance.Environment != nil && instance.Environment.Project != nil && instance.Manifest != nil {
urlHelper, urlErr := apiv0.NewURLHelper(ctx, mdClient)
if urlErr == nil {
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instance.Environment.Project.ID, instance.Environment.ID, instance.Manifest.ID))
if instance.Environment != nil && instance.Environment.Project != nil {
urlHelper, urlErr := apiv0.NewURLHelper(ctx, mdClient)
if urlErr == nil {
fmt.Printf("🔗 %s\n", urlHelper.InstanceURL(instance.Environment.Project.ID, instance.Environment.ID, instance.ID))

Copilot uses AI. Check for mistakes.
Comment on lines 153 to 166
tbl := cli.NewTable("ID/Slug", "Name", "Description", "Monthly $", "Daily $")

for _, project := range projects {
monthly := ""
daily := ""
if project.Cost.Monthly.Average.Amount != nil {
monthly = fmt.Sprintf("%v", *project.Cost.Monthly.Average.Amount)
if project.Cost.MonthlyAverage.Amount != nil {
monthly = fmt.Sprintf("%v", *project.Cost.MonthlyAverage.Amount)
}
if project.Cost.Daily.Average.Amount != nil {
daily = fmt.Sprintf("%v", *project.Cost.Daily.Average.Amount)
if project.Cost.DailyAverage.Amount != nil {
daily = fmt.Sprintf("%v", *project.Cost.DailyAverage.Amount)
}
description := cli.TruncateString(project.Description, 60)
tbl.AddRow(project.Slug, project.Name, description, monthly, daily)
tbl.AddRow(project.ID, project.Name, description, monthly, daily)
}
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This table now prints project.ID values, but the header still says "ID/Slug". Update the header to just "ID" (or include both fields) to keep CLI output accurate.

Copilot uses AI. Check for mistakes.
}

tbl := cli.NewTable("ID/Slug", "Name", "Description", "Monthly $", "Daily $")
tbl := cli.NewTable("ID", "Name", "Description", "Monthly $", "Daily $")
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The table header was updated to "ID", but the rows below still add env.Slug as the first column. Update either the header (back to "Slug"/"ID/Slug") or the row value (to env.ID) so the output matches what’s displayed.

Suggested change
tbl := cli.NewTable("ID", "Name", "Description", "Monthly $", "Daily $")
tbl := cli.NewTable("Slug", "Name", "Description", "Monthly $", "Daily $")

Copilot uses AI. Check for mistakes.
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.

3 participants