Skip to content

import-dir uploads secondary artifacts before their primary API definition #561

Open

Description

@doraem-on

Problem

import-dir can upload a secondary artifact before its primary API definition. For example, a directory containing examples.yaml and openapi.yaml uploads examples.yaml with primary=false first, then openapi.yaml with primary=true.

ImportDirectory uploads files in their discovery order. RealFileSystem uses filepath.Walk, so lexical filename order determines which artifact is uploaded first; the files are not grouped by primary/secondary status.

The multi-artifact documentation explains that a secondary artifact is ignored when its matching API name/version does not yet exist. On a first import, this ordering can therefore leave the API without the examples from its secondary artifact.

Expected behavior

Upload primary artifacts before secondary artifacts, regardless of filename order, so the API definition exists before its secondary artifacts are imported.

Reproduction test

Tested on upstream master at e54dc4719d1f14085f5bb551a910139628babbbc, with go version go1.26.5 darwin/arm64 (macOS, ARM64).

Save this as cmd/import_order_regression_test.go and run:

go test ./cmd -run '^TestReviewImportDirPrimaryOrder$' -count=1 -v

The test calls the production ImportDirectory with RealFileSystem and records calls to the upload client. Fixture contents are placeholders because the recording client does not parse them.

package cmd

import (
	"fmt"
	"os"
	"path/filepath"
	"testing"
)

type reviewUploadClient struct{ calls []string }

func (c *reviewUploadClient) UploadArtifact(path string, primary bool) (string, error) {
	c.calls = append(c.calls, fmt.Sprintf("%s primary=%t", filepath.Base(path), primary))
	return "accepted", nil
}

func TestReviewImportDirPrimaryOrder(t *testing.T) {
	dir := t.TempDir()
	for _, name := range []string{"examples.yaml", "openapi.yaml"} {
		if err := os.WriteFile(filepath.Join(dir, name), []byte("fixture"), 0600); err != nil {
			t.Fatal(err)
		}
	}
	client := &reviewUploadClient{}
	result, err := ImportDirectory(client, &RealFileSystem{}, dir, ImportConfig{})
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("upload order: %v; success=%d failed=%d", client.calls, result.SuccessCount, result.FailedCount)
	if client.calls[0] != "openapi.yaml primary=true" {
		t.Errorf("secondary artifact uploaded before the primary API definition")
	}
}

Actual test output

For the recorded run, the test file was supplied through a temporary Go overlay to leave the checkout unchanged:

go test -overlay=/tmp/microcks-import-order-overlay.json ./cmd -run '^TestReviewImportDirPrimaryOrder$' -count=1 -v
=== RUN   TestReviewImportDirPrimaryOrder
Microcks has completed 'accepted'
Microcks has discovered 'accepted'
    import_order_regression_test.go:29: upload order: [examples.yaml primary=false openapi.yaml primary=true]; success=2 failed=0
    import_order_regression_test.go:31: secondary artifact uploaded before the primary API definition
--- FAIL: TestReviewImportDirPrimaryOrder (0.00s)
FAIL
FAIL	github.com/microcks/microcks-cli/cmd	0.917s
FAIL

Exit status: 1. The secondary artifact was uploaded first.

This test confirms the CLI upload order only. The accepted responses and success counters come from the recording client, not a live Microcks server. The missing-examples impact follows from the documented secondary-artifact behavior; I have not run a live-server reproduction.

A possible fix is to stably group the discovered files by IsPrimary before uploading them, keeping the existing relative order within each group.

I searched existing issues and PRs for import-dir ordering/primary/secondary reports and found no matching report. PR #459 concerns import-url success-message wording, not directory upload ordering.

Activity

  1. doraem-on commented on Oct 1, 2026

    @doraem-on
    Author

    @Harsh4902 could you pls confirm this issue ....thanks

  2. Harsh4902 commented on Oct 8, 2026

    @Harsh4902
    Member

    @doraem-on Sorry for the late reply, I saw this issue last week and yes it's clearly an issue.

  3. added this to the Next milestone on Oct 8, 2026
  4. doraem-on commented on Oct 8, 2026

    @doraem-on
    Author

    @Harsh4902 thanks for checking

  5. yada commented on Oct 14, 2026

    @yada
    Member

    Reproduced on master (f9550f5) against a real Microcks server, using a fresh instance and the file names from this issue.

    microcks import-dir on a directory with examples.yaml (an APIExamples artifact) and openapi.yaml (the API Pastry spec):

    Microcks has completed 'API Pastry - 2.0:2.0.0'     <- secondary uploaded first
    Microcks has discovered 'API Pastry - 2.0:2.0.0'    <- primary
    

    The example defined only in the secondary artifact was lost: the mock returned HTTP 400 ("The response /name=SecondaryOnly does not exist"). Importing in the right order (primary then secondary) returned HTTP 200 with the example.

    Cause: ImportDirectory uploads files in filepath.Walk (lexical) order, and detectFileType is only applied at upload time. Suggested fix: classify all files first, then upload primaries before secondaries.
    Note: with names like APIPastry-openapi.yaml and a-examples.yaml the order happens to be right (uppercase sorts first), so the bug depends on file names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions