Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
286 changes: 286 additions & 0 deletions README-zh.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions cmd/skillshare/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ func parseOptsFromConfig(cfg *config.Config) install.ParseOptions {
return install.ParseOptions{
GitLabHosts: cfg.EffectiveGitLabHosts(),
AzureHosts: cfg.EffectiveAzureHosts(),
CNBHosts: cfg.EffectiveCNBHosts(),
GiteaHosts: cfg.EffectiveGiteaHosts(),
}
}

Expand All @@ -260,6 +262,8 @@ func parseOptsFromProjectConfig(cfg *config.ProjectConfig) install.ParseOptions
return install.ParseOptions{
GitLabHosts: cfg.EffectiveGitLabHosts(),
AzureHosts: cfg.EffectiveAzureHosts(),
CNBHosts: cfg.EffectiveCNBHosts(),
GiteaHosts: cfg.EffectiveGiteaHosts(),
}
}

Expand Down
42 changes: 42 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ type Config struct {
TUI *bool `yaml:"tui,omitempty"` // nil = default true
GitLabHosts []string `yaml:"gitlab_hosts,omitempty"`
AzureHosts []string `yaml:"azure_hosts,omitempty"`
CNBHosts []string `yaml:"cnb_hosts,omitempty"`
GiteaHosts []string `yaml:"gitea_hosts,omitempty"`

// PreserveTildeOnSave folds $HOME prefixes back to ~ when serializing the
// config to YAML. Useful when the config is shared via dotfiles across
Expand Down Expand Up @@ -358,6 +360,16 @@ func (c *Config) EffectiveAzureHosts() []string {
return mergeAzureHostsFromEnv(c.AzureHosts)
}

// EffectiveCNBHosts returns CNBHosts merged with SKILLSHARE_CNB_HOSTS env var.
func (c *Config) EffectiveCNBHosts() []string {
return mergeCNBHostsFromEnv(c.CNBHosts)
}

// EffectiveGiteaHosts returns GiteaHosts merged with SKILLSHARE_GITEA_HOSTS env var.
func (c *Config) EffectiveGiteaHosts() []string {
return mergeGiteaHostsFromEnv(c.GiteaHosts)
}

// IsTUIEnabled reports whether interactive TUI is enabled.
// nil (absent from config) is treated as true for backward compatibility.
func (c *Config) IsTUIEnabled() bool {
Expand Down Expand Up @@ -499,6 +511,20 @@ func Load() (*Config, error) {
}
cfg.AzureHosts = azureHosts

// Validate and normalize cnb_hosts
cnbHosts, err := normalizeCNBHosts(cfg.CNBHosts)
if err != nil {
return nil, err
}
cfg.CNBHosts = cnbHosts

// Validate and normalize gitea_hosts
giteaHosts, err := normalizeGiteaHosts(cfg.GiteaHosts)
if err != nil {
return nil, err
}
cfg.GiteaHosts = giteaHosts

// Migrate legacy flat target fields to skills: sub-key (one-time, persisted immediately)
if migrateTargetConfigs(cfg.Targets) {
if data, err := marshalYAML(&cfg); err == nil {
Expand Down Expand Up @@ -758,6 +784,14 @@ func normalizeAzureHosts(hosts []string) ([]string, error) {
return normalizeHostList(hosts, "azure_hosts")
}

func normalizeCNBHosts(hosts []string) ([]string, error) {
return normalizeHostList(hosts, "cnb_hosts")
}

func normalizeGiteaHosts(hosts []string) ([]string, error) {
return normalizeHostList(hosts, "gitea_hosts")
}

// mergeHostsFromEnv merges comma-separated env var entries with config file hosts.
// Invalid entries in the env var are silently skipped.
func mergeHostsFromEnv(configHosts []string, envKey string) []string {
Expand Down Expand Up @@ -791,6 +825,14 @@ func mergeAzureHostsFromEnv(configHosts []string) []string {
return mergeHostsFromEnv(configHosts, "SKILLSHARE_AZURE_HOSTS")
}

func mergeCNBHostsFromEnv(configHosts []string) []string {
return mergeHostsFromEnv(configHosts, "SKILLSHARE_CNB_HOSTS")
}

func mergeGiteaHostsFromEnv(configHosts []string) []string {
return mergeHostsFromEnv(configHosts, "SKILLSHARE_GITEA_HOSTS")
}

func normalizeAuditBlockThreshold(v string) (string, error) {
threshold := strings.ToUpper(strings.TrimSpace(v))
if threshold == "" {
Expand Down
26 changes: 26 additions & 0 deletions internal/config/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,8 @@ type ProjectConfig struct {
Hub HubConfig `yaml:"hub,omitempty"`
GitLabHosts []string `yaml:"gitlab_hosts,omitempty"`
AzureHosts []string `yaml:"azure_hosts,omitempty"`
CNBHosts []string `yaml:"cnb_hosts,omitempty"`
GiteaHosts []string `yaml:"gitea_hosts,omitempty"`
}

// EffectiveSkillsSource returns the resolved skills source directory.
Expand Down Expand Up @@ -339,6 +341,16 @@ func (c *ProjectConfig) EffectiveAzureHosts() []string {
return mergeAzureHostsFromEnv(c.AzureHosts)
}

// EffectiveCNBHosts returns CNBHosts merged with SKILLSHARE_CNB_HOSTS env var.
func (c *ProjectConfig) EffectiveCNBHosts() []string {
return mergeCNBHostsFromEnv(c.CNBHosts)
}

// EffectiveGiteaHosts returns GiteaHosts merged with SKILLSHARE_GITEA_HOSTS env var.
func (c *ProjectConfig) EffectiveGiteaHosts() []string {
return mergeGiteaHostsFromEnv(c.GiteaHosts)
}

// ProjectConfigPath returns the project config path for the given root.
func ProjectConfigPath(projectRoot string) string {
return filepath.Join(projectRoot, ".skillshare", "config.yaml")
Expand Down Expand Up @@ -381,6 +393,20 @@ func LoadProject(projectRoot string) (*ProjectConfig, error) {
}
cfg.AzureHosts = azureHosts

// Validate and normalize cnb_hosts
cnbHosts, err := normalizeCNBHosts(cfg.CNBHosts)
if err != nil {
return nil, fmt.Errorf("project config: %w", err)
}
cfg.CNBHosts = cnbHosts

// Validate and normalize gitea_hosts
giteaHosts, err := normalizeGiteaHosts(cfg.GiteaHosts)
if err != nil {
return nil, fmt.Errorf("project config: %w", err)
}
cfg.GiteaHosts = giteaHosts

for _, target := range cfg.Targets {
if strings.TrimSpace(target.Name) == "" {
return nil, fmt.Errorf("project config has target with empty name")
Expand Down
17 changes: 17 additions & 0 deletions internal/install/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const (
PlatformGitLab // gitlab.com and self-hosted GitLab
PlatformBitbucket // bitbucket.org
PlatformAzureDevOps // dev.azure.com and visualstudio.com
PlatformCNB // cnb.cool and self-hosted CNB instances
PlatformGitea // gitea.com and self-hosted Gitea instances
)

// extractHost returns the hostname from a clone URL.
Expand Down Expand Up @@ -62,6 +64,12 @@ func detectPlatform(cloneURL string) Platform {
if host == "dev.azure.com" || host == "ssh.dev.azure.com" || strings.HasSuffix(host, ".visualstudio.com") {
return PlatformAzureDevOps
}
if strings.Contains(host, "cnb.cool") {
return PlatformCNB
}
if strings.Contains(host, "gitea") {
return PlatformGitea
Comment on lines +67 to +71
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use configured CNB/Gitea hosts in platform detection

The new cnb_hosts / gitea_hosts configuration never affects token selection because detectPlatform only matches literal host substrings (cnb.cool, gitea). For self-hosted instances like git.company.internal, this returns PlatformUnknown, so resolveToken ignores CNB_TOKEN/GITEA_TOKEN and private installs fail unless users also set SKILLSHARE_GIT_TOKEN. This contradicts the advertised self-hosted support and is triggered whenever the host does not include those hard-coded substrings.

Useful? React with 👍 / 👎.

}
return PlatformUnknown
}

Expand Down Expand Up @@ -98,6 +106,14 @@ func resolveToken(cloneURL string) (token, username string) {
if t := os.Getenv("AZURE_DEVOPS_TOKEN"); t != "" {
return t, "x-access-token"
}
case PlatformCNB:
if t := os.Getenv("CNB_TOKEN"); t != "" {
return t, "cnb"
}
case PlatformGitea:
if t := os.Getenv("GITEA_TOKEN"); t != "" {
return t, "x-access-token"
}
}

// Generic fallback — use platform-appropriate username, or preserve
Expand Down Expand Up @@ -195,6 +211,7 @@ func sanitizeTokens(text string) string {
vars := []string{
"GITHUB_TOKEN", "GH_TOKEN", "GITLAB_TOKEN", "BITBUCKET_TOKEN",
"AZURE_DEVOPS_TOKEN", "SKILLSHARE_GIT_TOKEN", "BITBUCKET_USERNAME",
"CNB_TOKEN", "GITEA_TOKEN",
}
for _, v := range vars {
if t := os.Getenv(v); t != "" {
Expand Down
Loading