Skip to content

Commit 779ea1c

Browse files
resolving conflicts
Signed-off-by: Avinash Singh <avinashsingh.rcoem@gmail.com>
2 parents 7b59e3a + ef37971 commit 779ea1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1485
-132
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@ jobs:
2020
runs-on: ubuntu-latest
2121
steps:
2222
- name: Checkout code
23-
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
23+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2424
with:
2525
submodules: recursive
2626

2727
- name: Install Go
28-
uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00
28+
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
2929
with:
3030
go-version-file: go.mod
3131

.github/workflows/codeql-analysis.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ jobs:
2828

2929
steps:
3030
- name: Checkout repository
31-
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
31+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3232

3333
- name: Initialize CodeQL
34-
uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e
34+
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
3535
with:
3636
languages: ${{ matrix.language }}
3737

3838
- name: Autobuild
39-
uses: github/codeql-action/autobuild@1b168cd39490f61582a9beae412bb7057a6b2c4e
39+
uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
4040

4141
- name: Perform CodeQL Analysis
42-
uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e
42+
uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9

.github/workflows/e2e.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ jobs:
3333
PACKAGE_DIR: modctl-test-package
3434
steps:
3535
- name: Checkout code
36-
uses: actions/checkout@v6
36+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3737
with:
3838
submodules: recursive
3939

4040
- name: Install Go
41-
uses: actions/setup-go@v6
41+
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
4242
with:
4343
go-version-file: go.mod
4444
cache-dependency-path: go.sum
@@ -49,7 +49,7 @@ jobs:
4949
5050
- name: Cache Package
5151
id: cache-package
52-
uses: actions/cache@v5
52+
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
5353
with:
5454
path: ${{ env.PACKAGE_DIR }}
5555
key: modctl-test-packages
@@ -79,7 +79,7 @@ jobs:
7979
go build -tags "static system_libgit2 enable_libgit2"
8080
8181
- name: Upload modctl
82-
uses: actions/upload-artifact@v6
82+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
8383
with:
8484
name: modctl-artifact
8585
path: modctl
@@ -90,15 +90,15 @@ jobs:
9090
runs-on: ubuntu-latest
9191
steps:
9292
- name: Cache model
93-
uses: actions/cache@v5
93+
uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1
9494
id: cache-model
9595
with:
9696
path: ${{ env.MODEL_DIR }}
9797
key: ${{env.MODEL_DIR}}-${{ env.MODEL }}
9898

9999
- name: Set up Python
100100
if: steps.cache-model.outputs.cache-hit != 'true'
101-
uses: actions/setup-python@v6
101+
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
102102
with:
103103
python-version: "3.10"
104104

@@ -110,7 +110,7 @@ jobs:
110110
hf download ${{ env.MODEL }} --local-dir ${{ env.MODEL_DIR }}
111111
112112
- name: Upload model
113-
uses: actions/upload-artifact@v6
113+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
114114
with:
115115
name: model-artifact
116116
path: ${{ env.MODEL_DIR }}
@@ -122,12 +122,12 @@ jobs:
122122
needs: [build-modctl, download-model]
123123
steps:
124124
- name: Download modctl artifact
125-
uses: actions/download-artifact@v7
125+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
126126
with:
127127
name: modctl-artifact
128128
path: modctl
129129
- name: Download model artifact
130-
uses: actions/download-artifact@v7
130+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
131131
with:
132132
name: model-artifact
133133
path: ${{ env.MODEL_DIR }}

.github/workflows/lint.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
timeout-minutes: 30
1717
steps:
1818
- name: Checkout code
19-
uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3
19+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
2020
with:
2121
fetch-depth: '0'
2222

@@ -39,7 +39,7 @@ jobs:
3939
LIBGIT2_SYS_USE_PKG_CONFIG: "1"
4040

4141
- name: Golangci lint
42-
uses: golangci/golangci-lint-action@v9.2.0
42+
uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9.2.0
4343
with:
4444
version: v2.4
4545
args: --verbose --timeout=10m

.github/workflows/release.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ jobs:
2727

2828
steps:
2929
- name: Checkout code
30-
uses: actions/checkout@v6
30+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
3131
with:
3232
fetch-depth: 0
3333

3434
- name: Set up Go
35-
uses: actions/setup-go@v6
35+
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
3636
with:
3737
go-version: '1.24' # Adjust to your Go version
3838

@@ -125,7 +125,7 @@ jobs:
125125
nfpm pkg --packager rpm --config hack/nfpm.yaml --target dist/modctl-${TAG}-${{ matrix.goos }}-${{ matrix.goarch }}.rpm
126126
127127
- name: Upload artifacts
128-
uses: actions/upload-artifact@v6
128+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
129129
with:
130130
name: modctl-${{ matrix.goos }}-${{ matrix.goarch }}
131131
path: dist/
@@ -135,7 +135,7 @@ jobs:
135135
runs-on: ubuntu-latest
136136
steps:
137137
- name: Download all artifacts
138-
uses: actions/download-artifact@v7
138+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
139139
with:
140140
path: artifacts
141141

@@ -145,7 +145,7 @@ jobs:
145145
find . -type f \( -name "modctl-*.tar.gz" -o -name "modctl-*.deb" -o -name "modctl-*.rpm" \) -exec shasum -a 256 {} \; > ../checksums.txt
146146
147147
- name: Create draft release
148-
uses: softprops/action-gh-release@v2
148+
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
149149
with:
150150
draft: true
151151
files: |

cmd/attach.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func init() {
5151
flags := attachCmd.Flags()
5252
flags.StringVarP(&attachConfig.Source, "source", "s", "", "source model artifact name")
5353
flags.StringVarP(&attachConfig.Target, "target", "t", "", "target model artifact name")
54+
flags.StringVarP(&attachConfig.DestinationDir, "destination-dir", "d", "", "destination directory for the attached file should be specified as a relative path; by default, it will match the original directory of the attachment")
5455
flags.BoolVarP(&attachConfig.OutputRemote, "output-remote", "", false, "turning on this flag will output model artifact to remote registry directly")
5556
flags.BoolVarP(&attachConfig.PlainHTTP, "plain-http", "", false, "turning on this flag will use plain HTTP instead of HTTPS")
5657
flags.BoolVarP(&attachConfig.Insecure, "insecure", "", false, "turning on this flag will disable TLS verification")

cmd/modelfile/generate.go

Lines changed: 111 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,65 @@ import (
2626

2727
configmodelfile "github.com/modelpack/modctl/pkg/config/modelfile"
2828
"github.com/modelpack/modctl/pkg/modelfile"
29+
"github.com/modelpack/modctl/pkg/modelprovider"
2930
)
3031

3132
var generateConfig = configmodelfile.NewGenerateConfig()
3233

3334
// generateCmd represents the modelfile tools command for generating modelfile.
3435
var generateCmd = &cobra.Command{
35-
Use: "generate [flags] <path>",
36-
Short: "A command line tool for generating modelfile in the workspace, the workspace must be a directory including model files and model configuration files",
37-
Args: cobra.ExactArgs(1),
36+
Use: "generate [flags] [<path>]",
37+
Short: "Generate a modelfile from a local workspace or remote model provider",
38+
Long: `Generate a modelfile from either a local directory containing model files or by downloading a model from a supported provider.
39+
40+
The workspace must be a directory including model files and model configuration files.
41+
Alternatively, use --model-url to download a model from a supported provider (e.g., HuggingFace, ModelScope).
42+
43+
For short-form URLs (owner/repo), you must explicitly specify the provider using --provider flag.
44+
Full URLs with domain names will auto-detect the provider.`,
45+
Example: ` # Generate from local directory
46+
modctl modelfile generate ./my-model-dir
47+
48+
# Generate from Hugging Face using full URL (auto-detects provider)
49+
modctl modelfile generate --model-url https://huggingface.co/meta-llama/Llama-2-7b-hf
50+
51+
# Generate from Hugging Face using short form (requires --provider)
52+
modctl modelfile generate --model-url meta-llama/Llama-2-7b-hf --provider huggingface
53+
54+
# Generate from ModelScope using full URL (auto-detects provider)
55+
modctl modelfile generate --model-url https://modelscope.cn/models/qwen/Qwen-7B
56+
57+
# Generate from ModelScope using short form (requires --provider)
58+
modctl modelfile generate --model-url qwen/Qwen-7B --provider modelscope
59+
60+
# Generate with custom download directory
61+
modctl modelfile generate --model-url meta-llama/Llama-2-7b-hf --provider huggingface --download-dir $HOME/models
62+
63+
# Generate with custom output path
64+
modctl modelfile generate ./my-model-dir --output ./output/modelfile.yaml
65+
66+
# Generate with metadata overrides
67+
modctl modelfile generate ./my-model-dir --name my-custom-model --family llama3`,
68+
Args: cobra.MaximumNArgs(1),
3869
DisableAutoGenTag: true,
3970
SilenceUsage: true,
4071
FParseErrWhitelist: cobra.FParseErrWhitelist{UnknownFlags: true},
4172
RunE: func(cmd *cobra.Command, args []string) error {
42-
if err := generateConfig.Convert(args[0]); err != nil {
73+
// If model-url is provided, path is optional
74+
workspace := "."
75+
if len(args) > 0 {
76+
workspace = args[0]
77+
}
78+
79+
// Validate that either path or model-url is provided
80+
if generateConfig.ModelURL != "" && len(args) > 0 {
81+
return fmt.Errorf("the <path> argument and the --model-url flag are mutually exclusive")
82+
}
83+
if generateConfig.ModelURL == "" && len(args) == 0 {
84+
return fmt.Errorf("either a <path> argument or the --model-url flag must be provided")
85+
}
86+
87+
if err := generateConfig.Convert(workspace); err != nil {
4388
return err
4489
}
4590

@@ -64,6 +109,9 @@ func init() {
64109
flags.StringVarP(&generateConfig.Output, "output", "O", ".", "specify the output path of modelfilem, must be a directory")
65110
flags.BoolVar(&generateConfig.IgnoreUnrecognizedFileTypes, "ignore-unrecognized-file-types", false, "ignore the unrecognized file types in the workspace")
66111
flags.BoolVar(&generateConfig.Overwrite, "overwrite", false, "overwrite the existing modelfile")
112+
flags.StringVar(&generateConfig.ModelURL, "model-url", "", "download model from a supported provider (full URL or short-form with --provider)")
113+
flags.StringVarP(&generateConfig.Provider, "provider", "p", "", "explicitly specify the provider for short-form URLs (huggingface, modelscope)")
114+
flags.StringVar(&generateConfig.DownloadDir, "download-dir", "", "custom directory for downloading models (default: system temp directory)")
67115
flags.StringArrayVar(&generateConfig.ExcludePatterns, "exclude", []string{}, "specify glob patterns to exclude files/directories (e.g. *.log, checkpoints/*)")
68116

69117
// Mark the ignore-unrecognized-file-types flag as deprecated and hidden
@@ -76,7 +124,65 @@ func init() {
76124
}
77125

78126
// runGenerate runs the generate modelfile.
79-
func runGenerate(_ context.Context) error {
127+
func runGenerate(ctx context.Context) error {
128+
// If model URL is provided, download the model first
129+
if generateConfig.ModelURL != "" {
130+
fmt.Printf("Model URL provided: %s\n", generateConfig.ModelURL)
131+
132+
// Get the appropriate provider for this URL
133+
registry := modelprovider.GetRegistry()
134+
provider, err := registry.SelectProvider(generateConfig.ModelURL, generateConfig.Provider)
135+
if err != nil {
136+
return fmt.Errorf("failed to select provider: %w", err)
137+
}
138+
139+
fmt.Printf("Using provider: %s\n", provider.Name())
140+
141+
// Check if user is authenticated with the provider
142+
if err := provider.CheckAuth(); err != nil {
143+
return fmt.Errorf("%s authentication check failed: %w", provider.Name(), err)
144+
}
145+
146+
// Determine the download directory
147+
var downloadDir string
148+
var cleanupDir bool
149+
150+
if generateConfig.DownloadDir != "" {
151+
// Use user-specified directory
152+
downloadDir = generateConfig.DownloadDir
153+
cleanupDir = false
154+
155+
// Create the directory if it doesn't exist
156+
if err := os.MkdirAll(downloadDir, 0755); err != nil {
157+
return fmt.Errorf("failed to create download directory: %w", err)
158+
}
159+
fmt.Printf("Using custom download directory: %s\n", downloadDir)
160+
} else {
161+
// Create a temporary directory for downloading the model
162+
tmpDir, err := os.MkdirTemp("", "modctl-model-downloads-*")
163+
if err != nil {
164+
return fmt.Errorf("failed to create temporary directory: %w", err)
165+
}
166+
downloadDir = tmpDir
167+
cleanupDir = true
168+
}
169+
170+
// Clean up the directory only if it was a temporary directory
171+
if cleanupDir {
172+
defer os.RemoveAll(downloadDir)
173+
}
174+
175+
// Download the model
176+
downloadPath, err := provider.DownloadModel(ctx, generateConfig.ModelURL, downloadDir)
177+
if err != nil {
178+
return fmt.Errorf("failed to download model from %s: %w", provider.Name(), err)
179+
}
180+
181+
// Update workspace to the downloaded model path
182+
generateConfig.Workspace = downloadPath
183+
fmt.Printf("Using downloaded model at: %s\n", downloadPath)
184+
}
185+
80186
fmt.Printf("Generating modelfile for %s\n", generateConfig.Workspace)
81187
modelfile, err := modelfile.NewModelfileByWorkspace(generateConfig.Workspace, generateConfig)
82188
if err != nil {

cmd/upload.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func init() {
5353
flags.BoolVarP(&uploadConfig.PlainHTTP, "plain-http", "", false, "turning on this flag will use plain HTTP instead of HTTPS")
5454
flags.BoolVarP(&uploadConfig.Insecure, "insecure", "", false, "turning on this flag will disable TLS verification")
5555
flags.BoolVar(&uploadConfig.Raw, "raw", true, "turning on this flag will upload model artifact layer in raw format")
56+
flags.StringVar(&uploadConfig.DestinationDir, "destination-dir", "", "destination directory for the uploaded file should be specified as a relative path; by default, it will match the original directory of the uploaded file")
5657

5758
if err := viper.BindPFlags(flags); err != nil {
5859
panic(fmt.Errorf("bind cache list flags to viper: %w", err))

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/modelpack/modctl
33
go 1.24.1
44

55
require (
6-
d7y.io/api/v2 v2.1.94
6+
d7y.io/api/v2 v2.2.1
77
github.com/antgroup/hugescm v0.18.3
88
github.com/avast/retry-go/v4 v4.7.0
99
github.com/distribution/distribution/v3 v3.0.0
@@ -21,7 +21,7 @@ require (
2121
github.com/spf13/cobra v1.10.2
2222
github.com/spf13/viper v1.21.0
2323
github.com/stretchr/testify v1.11.1
24-
github.com/vbauerster/mpb/v8 v8.11.2
24+
github.com/vbauerster/mpb/v8 v8.11.3
2525
golang.org/x/crypto v0.45.0
2626
golang.org/x/sync v0.18.0
2727
golang.org/x/sys v0.39.0

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
d7y.io/api/v2 v2.1.94 h1:4IY/KFhj2tVvRisIPWqiFI2s4xOQTAlJtkZTodNucpQ=
2-
d7y.io/api/v2 v2.1.94/go.mod h1:TtW9UE0CebRB/CWIEbWfRnljmpKf/mNoe2qIUO+PoP0=
1+
d7y.io/api/v2 v2.2.1 h1:po39adZpbGn6sIl9vR9E1fVbOLim5SOP/3Tt0g8Ii58=
2+
d7y.io/api/v2 v2.2.1/go.mod h1:TtW9UE0CebRB/CWIEbWfRnljmpKf/mNoe2qIUO+PoP0=
33
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
44
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
55
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
@@ -245,8 +245,8 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
245245
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
246246
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
247247
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
248-
github.com/vbauerster/mpb/v8 v8.11.2 h1:OqLoHznUVU7SKS/WV+1dB5/hm20YLheYupiHhL5+M1Y=
249-
github.com/vbauerster/mpb/v8 v8.11.2/go.mod h1:mEB/M353al1a7wMUNtiymmPsEkGlJgeJmtlbY5adCJ8=
248+
github.com/vbauerster/mpb/v8 v8.11.3 h1:iniBmO4ySXCl4gVdmJpgrtormH5uvjpxcx/dMyVU9Jw=
249+
github.com/vbauerster/mpb/v8 v8.11.3/go.mod h1:n9M7WbP0NFjpgKS5XdEC3tMRgZTNM/xtC8zWGkiMuy0=
250250
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
251251
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
252252
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=

0 commit comments

Comments
 (0)