mirror of
https://github.com/yarlson/lnk.git
synced 2025-08-29 17:49:47 +02:00
feat: implement CI/CD pipeline and release automation
This commit is contained in:
84
.github/workflows/ci.yml
vendored
Normal file
84
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Cache Go modules
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/go/pkg/mod
|
||||||
|
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-go-
|
||||||
|
|
||||||
|
- name: Download dependencies
|
||||||
|
run: go mod download
|
||||||
|
|
||||||
|
- name: Format check
|
||||||
|
run: |
|
||||||
|
gofmt -l .
|
||||||
|
test -z "$(gofmt -l .)"
|
||||||
|
|
||||||
|
- name: Vet
|
||||||
|
run: go vet ./...
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: go test -v -race -coverprofile=coverage.out ./test
|
||||||
|
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v3
|
||||||
|
with:
|
||||||
|
file: ./coverage.out
|
||||||
|
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: golangci-lint
|
||||||
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
with:
|
||||||
|
version: latest
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [test, lint]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: go build -v ./...
|
||||||
|
|
||||||
|
- name: Test GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v5
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: build --snapshot --clean
|
35
.github/workflows/release.yml
vendored
Normal file
35
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: go test ./test
|
||||||
|
|
||||||
|
- name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v5
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: release --clean
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
40
.github/workflows/validate.yml
vendored
Normal file
40
.github/workflows/validate.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Validate
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
paths:
|
||||||
|
- '.goreleaser.yml'
|
||||||
|
- 'main.go'
|
||||||
|
- 'cmd/**'
|
||||||
|
- 'internal/**'
|
||||||
|
- 'go.mod'
|
||||||
|
- 'go.sum'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: '1.24'
|
||||||
|
|
||||||
|
- name: Check GoReleaser config
|
||||||
|
uses: goreleaser/goreleaser-action@v5
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: check
|
||||||
|
|
||||||
|
- name: Test GoReleaser build
|
||||||
|
uses: goreleaser/goreleaser-action@v5
|
||||||
|
with:
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: build --snapshot --clean
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -41,3 +41,6 @@ desktop.ini
|
|||||||
# Temporary files
|
# Temporary files
|
||||||
*.tmp
|
*.tmp
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
# GoReleaser artifacts
|
||||||
|
goreleaser/
|
129
.goreleaser.yml
Normal file
129
.goreleaser.yml
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# GoReleaser configuration for lnk
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
project_name: lnk
|
||||||
|
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
# you may remove this if you don't need go generate
|
||||||
|
- go generate ./...
|
||||||
|
|
||||||
|
builds:
|
||||||
|
- env:
|
||||||
|
- CGO_ENABLED=0
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
- windows
|
||||||
|
- darwin
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
# Optional: exclude specific combinations
|
||||||
|
ignore:
|
||||||
|
- goos: windows
|
||||||
|
goarch: arm64
|
||||||
|
ldflags:
|
||||||
|
- -s -w
|
||||||
|
- -X main.version={{.Version}}
|
||||||
|
- -X main.buildTime={{.Date}}
|
||||||
|
main: ./main.go
|
||||||
|
binary: lnk
|
||||||
|
|
||||||
|
archives:
|
||||||
|
- id: default
|
||||||
|
# this name template makes the OS and Arch compatible with the results of uname.
|
||||||
|
name_template: >-
|
||||||
|
{{ .ProjectName }}_
|
||||||
|
{{- title .Os }}_
|
||||||
|
{{- if eq .Arch "amd64" }}x86_64
|
||||||
|
{{- else if eq .Arch "386" }}i386
|
||||||
|
{{- else }}{{ .Arch }}{{ end }}
|
||||||
|
{{- if .Arm }}v{{ .Arm }}{{ end }}
|
||||||
|
files:
|
||||||
|
- README.md
|
||||||
|
- LICENSE
|
||||||
|
builds_info:
|
||||||
|
group: root
|
||||||
|
owner: root
|
||||||
|
|
||||||
|
checksum:
|
||||||
|
name_template: 'checksums.txt'
|
||||||
|
|
||||||
|
snapshot:
|
||||||
|
version_template: "{{ incpatch .Version }}-next"
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
use: github
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- '^docs:'
|
||||||
|
- '^test:'
|
||||||
|
- '^ci:'
|
||||||
|
- '^chore:'
|
||||||
|
- '^style:'
|
||||||
|
- '^refactor:'
|
||||||
|
groups:
|
||||||
|
- title: Features
|
||||||
|
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
|
||||||
|
order: 0
|
||||||
|
- title: 'Bug fixes'
|
||||||
|
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
|
||||||
|
order: 1
|
||||||
|
- title: Others
|
||||||
|
order: 999
|
||||||
|
|
||||||
|
# GitHub release configuration
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: yarlson
|
||||||
|
name: lnk
|
||||||
|
draft: false
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
header: |
|
||||||
|
## Lnk {{.Tag}}
|
||||||
|
|
||||||
|
Git-native dotfiles management that doesn't suck.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Quick install
|
||||||
|
curl -sSL https://raw.githubusercontent.com/yarlson/lnk/main/install.sh | bash
|
||||||
|
|
||||||
|
# Manual download
|
||||||
|
wget https://github.com/yarlson/lnk/releases/download/{{.Tag}}/lnk_{{.Os}}_{{.Arch}}.tar.gz
|
||||||
|
tar -xzf lnk_{{.Os}}_{{.Arch}}.tar.gz
|
||||||
|
sudo mv lnk /usr/local/bin/
|
||||||
|
```
|
||||||
|
|
||||||
|
footer: |
|
||||||
|
---
|
||||||
|
**Full Changelog**: https://github.com/yarlson/lnk/compare/{{.PreviousTag}}...{{.Tag}}
|
||||||
|
|
||||||
|
# Homebrew tap (optional - you can enable this later)
|
||||||
|
# brews:
|
||||||
|
# - repository:
|
||||||
|
# owner: yarlson
|
||||||
|
# name: homebrew-tap
|
||||||
|
# homepage: "https://github.com/yarlson/lnk"
|
||||||
|
# description: "Git-native dotfiles management"
|
||||||
|
# license: "MIT"
|
||||||
|
# test: |
|
||||||
|
# system "#{bin}/lnk --version"
|
||||||
|
|
||||||
|
# Docker images (optional)
|
||||||
|
# dockers:
|
||||||
|
# - image_templates:
|
||||||
|
# - "yarlson/lnk:latest"
|
||||||
|
# - "yarlson/lnk:{{ .Tag }}"
|
||||||
|
# - "yarlson/lnk:v{{ .Major }}"
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# build_flag_templates:
|
||||||
|
# - "--label=org.opencontainers.image.created={{.Date}}"
|
||||||
|
# - "--label=org.opencontainers.image.title={{.ProjectName}}"
|
||||||
|
# - "--label=org.opencontainers.image.revision={{.FullCommit}}"
|
||||||
|
# - "--label=org.opencontainers.image.version={{.Version}}"
|
28
Makefile
28
Makefile
@@ -16,7 +16,7 @@ YELLOW=\033[0;33m
|
|||||||
BLUE=\033[0;34m
|
BLUE=\033[0;34m
|
||||||
NC=\033[0m # No Color
|
NC=\033[0m # No Color
|
||||||
|
|
||||||
.PHONY: help build test clean install uninstall fmt lint vet tidy run dev cross-compile release
|
.PHONY: help build test clean install uninstall fmt lint vet tidy run dev cross-compile release goreleaser-check goreleaser-snapshot
|
||||||
|
|
||||||
## help: Show this help message
|
## help: Show this help message
|
||||||
help:
|
help:
|
||||||
@@ -42,8 +42,10 @@ help:
|
|||||||
@echo " uninstall Remove binary from /usr/local/bin"
|
@echo " uninstall Remove binary from /usr/local/bin"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "$(GREEN)Release:$(NC)"
|
@echo "$(GREEN)Release:$(NC)"
|
||||||
@echo " cross-compile Build for multiple platforms"
|
@echo " cross-compile Build for multiple platforms (legacy)"
|
||||||
@echo " release Create release builds"
|
@echo " release Create release builds (legacy)"
|
||||||
|
@echo " goreleaser-check Validate .goreleaser.yml config"
|
||||||
|
@echo " goreleaser-snapshot Build snapshot release with GoReleaser"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "$(GREEN)Utilities:$(NC)"
|
@echo "$(GREEN)Utilities:$(NC)"
|
||||||
@echo " clean Clean build artifacts"
|
@echo " clean Clean build artifacts"
|
||||||
@@ -158,7 +160,27 @@ clean:
|
|||||||
deps:
|
deps:
|
||||||
@echo "$(BLUE)Installing development dependencies...$(NC)"
|
@echo "$(BLUE)Installing development dependencies...$(NC)"
|
||||||
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
@go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
|
||||||
|
@if ! command -v goreleaser >/dev/null 2>&1; then \
|
||||||
|
echo "$(BLUE)Installing GoReleaser...$(NC)"; \
|
||||||
|
go install github.com/goreleaser/goreleaser@latest; \
|
||||||
|
fi
|
||||||
@echo "$(GREEN)✓ Dependencies installed$(NC)"
|
@echo "$(GREEN)✓ Dependencies installed$(NC)"
|
||||||
|
|
||||||
|
## goreleaser-check: Validate GoReleaser configuration
|
||||||
|
goreleaser-check:
|
||||||
|
@echo "$(BLUE)Validating GoReleaser configuration...$(NC)"
|
||||||
|
@if command -v goreleaser >/dev/null 2>&1; then \
|
||||||
|
goreleaser check; \
|
||||||
|
echo "$(GREEN)✓ GoReleaser configuration is valid$(NC)"; \
|
||||||
|
else \
|
||||||
|
echo "$(YELLOW)⚠ GoReleaser not found. Install with: make deps$(NC)"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
## goreleaser-snapshot: Build snapshot release with GoReleaser
|
||||||
|
goreleaser-snapshot: goreleaser-check
|
||||||
|
@echo "$(BLUE)Building snapshot release with GoReleaser...$(NC)"
|
||||||
|
@goreleaser build --snapshot --clean
|
||||||
|
@echo "$(GREEN)✓ Snapshot release built in dist/$(NC)"
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
all: check build
|
all: check build
|
131
RELEASE.md
Normal file
131
RELEASE.md
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# Release Process
|
||||||
|
|
||||||
|
This document describes how to create releases for the lnk project using GoReleaser.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Push access to the main repository
|
||||||
|
- Git tags pushed to GitHub trigger releases automatically
|
||||||
|
- GoReleaser is configured in `.goreleaser.yml`
|
||||||
|
- GitHub Actions will handle the release process
|
||||||
|
|
||||||
|
## Creating a Release
|
||||||
|
|
||||||
|
### 1. Ensure everything is ready
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all quality checks
|
||||||
|
make check
|
||||||
|
|
||||||
|
# Test GoReleaser configuration
|
||||||
|
make goreleaser-check
|
||||||
|
|
||||||
|
# Test build process
|
||||||
|
make goreleaser-snapshot
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Create and push a version tag
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a new tag (replace x.y.z with actual version)
|
||||||
|
git tag -a v1.0.0 -m "Release v1.0.0"
|
||||||
|
|
||||||
|
# Push the tag to trigger the release
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Monitor the release
|
||||||
|
|
||||||
|
- GitHub Actions will automatically build and release when the tag is pushed
|
||||||
|
- Check the [Actions tab](https://github.com/yarlson/lnk/actions) for build status
|
||||||
|
- The release will appear in [GitHub Releases](https://github.com/yarlson/lnk/releases)
|
||||||
|
|
||||||
|
## What GoReleaser Does
|
||||||
|
|
||||||
|
1. **Builds binaries** for multiple platforms:
|
||||||
|
- Linux (amd64, arm64)
|
||||||
|
- macOS (amd64, arm64)
|
||||||
|
- Windows (amd64)
|
||||||
|
|
||||||
|
2. **Creates archives** with consistent naming:
|
||||||
|
- `lnk_Linux_x86_64.tar.gz`
|
||||||
|
- `lnk_Darwin_arm64.tar.gz`
|
||||||
|
- etc.
|
||||||
|
|
||||||
|
3. **Generates checksums** for verification
|
||||||
|
|
||||||
|
4. **Creates GitHub release** with:
|
||||||
|
- Automatic changelog from conventional commits
|
||||||
|
- Installation instructions
|
||||||
|
- Download links for all platforms
|
||||||
|
|
||||||
|
## Manual Release (if needed)
|
||||||
|
|
||||||
|
If you need to create a release manually:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Export GitHub token
|
||||||
|
export GITHUB_TOKEN="your_token_here"
|
||||||
|
|
||||||
|
# Create release (requires a git tag)
|
||||||
|
goreleaser release --clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Releases Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test the build process without releasing
|
||||||
|
make goreleaser-snapshot
|
||||||
|
|
||||||
|
# Built artifacts will be in dist/
|
||||||
|
ls -la dist/
|
||||||
|
|
||||||
|
# Test a binary
|
||||||
|
./dist/lnk_<platform>/lnk --version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version Numbering
|
||||||
|
|
||||||
|
We use [Semantic Versioning](https://semver.org/):
|
||||||
|
|
||||||
|
- `v1.0.0` - Major release (breaking changes)
|
||||||
|
- `v1.1.0` - Minor release (new features, backward compatible)
|
||||||
|
- `v1.1.1` - Patch release (bug fixes)
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
GoReleaser automatically generates changelogs from git commits using conventional commit format:
|
||||||
|
|
||||||
|
- `feat:` - New features
|
||||||
|
- `fix:` - Bug fixes
|
||||||
|
- `docs:` - Documentation changes (excluded from changelog)
|
||||||
|
- `test:` - Test changes (excluded from changelog)
|
||||||
|
- `ci:` - CI changes (excluded from changelog)
|
||||||
|
|
||||||
|
## Installation Script
|
||||||
|
|
||||||
|
The `install.sh` script automatically downloads the latest release:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sSL https://raw.githubusercontent.com/yarlson/lnk/main/install.sh | bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Release failed to create
|
||||||
|
|
||||||
|
1. Check that the tag follows the format `vX.Y.Z`
|
||||||
|
2. Ensure GitHub Actions has proper permissions
|
||||||
|
3. Check the Actions log for detailed error messages
|
||||||
|
|
||||||
|
### Missing binaries in release
|
||||||
|
|
||||||
|
1. Verify GoReleaser configuration: `make goreleaser-check`
|
||||||
|
2. Test build locally: `make goreleaser-snapshot`
|
||||||
|
3. Check the build matrix in `.goreleaser.yml`
|
||||||
|
|
||||||
|
### Changelog is empty
|
||||||
|
|
||||||
|
1. Ensure commits follow conventional commit format
|
||||||
|
2. Check that there are commits since the last tag
|
||||||
|
3. Verify changelog configuration in `.goreleaser.yml`
|
12
cmd/root.go
12
cmd/root.go
@@ -7,12 +7,24 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
version = "dev"
|
||||||
|
buildTime = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "lnk",
|
Use: "lnk",
|
||||||
Short: "Dotfiles, linked. No fluff.",
|
Short: "Dotfiles, linked. No fluff.",
|
||||||
Long: "Lnk is a minimalist CLI tool for managing dotfiles using symlinks and Git.",
|
Long: "Lnk is a minimalist CLI tool for managing dotfiles using symlinks and Git.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetVersion sets the version information for the CLI
|
||||||
|
func SetVersion(v, bt string) {
|
||||||
|
version = v
|
||||||
|
buildTime = bt
|
||||||
|
rootCmd.Version = fmt.Sprintf("%s (built %s)", version, buildTime)
|
||||||
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
126
install.sh
Normal file
126
install.sh
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Lnk installer script
|
||||||
|
# Downloads and installs the latest release of lnk
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# GitHub repository
|
||||||
|
REPO="yarlson/lnk"
|
||||||
|
INSTALL_DIR="/usr/local/bin"
|
||||||
|
BINARY_NAME="lnk"
|
||||||
|
|
||||||
|
# Detect OS and architecture
|
||||||
|
detect_platform() {
|
||||||
|
local os arch
|
||||||
|
|
||||||
|
# Detect OS
|
||||||
|
case "$(uname -s)" in
|
||||||
|
Linux) os="Linux" ;;
|
||||||
|
Darwin) os="Darwin" ;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*) os="Windows" ;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Error: Unsupported operating system $(uname -s)${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Detect architecture
|
||||||
|
case "$(uname -m)" in
|
||||||
|
x86_64|amd64) arch="x86_64" ;;
|
||||||
|
arm64|aarch64) arch="arm64" ;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Error: Unsupported architecture $(uname -m)${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "${os}_${arch}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get the latest release version
|
||||||
|
get_latest_version() {
|
||||||
|
curl -s "https://api.github.com/repos/${REPO}/releases/latest" | \
|
||||||
|
grep '"tag_name":' | \
|
||||||
|
sed -E 's/.*"([^"]+)".*/\1/'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Download and install
|
||||||
|
install_lnk() {
|
||||||
|
local platform version
|
||||||
|
|
||||||
|
echo -e "${BLUE}🔗 Installing lnk...${NC}"
|
||||||
|
|
||||||
|
platform=$(detect_platform)
|
||||||
|
version=$(get_latest_version)
|
||||||
|
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
echo -e "${RED}Error: Failed to get latest version${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}Latest version: ${version}${NC}"
|
||||||
|
echo -e "${BLUE}Platform: ${platform}${NC}"
|
||||||
|
|
||||||
|
# Download URL
|
||||||
|
local filename="lnk_${platform}.tar.gz"
|
||||||
|
local url="https://github.com/${REPO}/releases/download/${version}/${filename}"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Downloading ${url}...${NC}"
|
||||||
|
|
||||||
|
# Create temporary directory
|
||||||
|
local tmp_dir=$(mktemp -d)
|
||||||
|
cd "$tmp_dir"
|
||||||
|
|
||||||
|
# Download the binary
|
||||||
|
if ! curl -sL "$url" -o "$filename"; then
|
||||||
|
echo -e "${RED}Error: Failed to download ${url}${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract the binary
|
||||||
|
if ! tar -xzf "$filename"; then
|
||||||
|
echo -e "${RED}Error: Failed to extract ${filename}${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make binary executable
|
||||||
|
chmod +x "$BINARY_NAME"
|
||||||
|
|
||||||
|
# Install to system directory
|
||||||
|
echo -e "${YELLOW}Installing to ${INSTALL_DIR} (requires sudo)...${NC}"
|
||||||
|
if ! sudo mv "$BINARY_NAME" "$INSTALL_DIR/"; then
|
||||||
|
echo -e "${RED}Error: Failed to install binary${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
cd - > /dev/null
|
||||||
|
rm -rf "$tmp_dir"
|
||||||
|
|
||||||
|
echo -e "${GREEN}✅ lnk installed successfully!${NC}"
|
||||||
|
echo -e "${GREEN}Run 'lnk --help' to get started.${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if running with --help
|
||||||
|
if [ "$1" = "--help" ] || [ "$1" = "-h" ]; then
|
||||||
|
echo "Lnk installer script"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: curl -sSL https://raw.githubusercontent.com/yarlson/lnk/main/install.sh | bash"
|
||||||
|
echo ""
|
||||||
|
echo "This script will:"
|
||||||
|
echo " 1. Detect your OS and architecture"
|
||||||
|
echo " 2. Download the latest lnk release"
|
||||||
|
echo " 3. Install it to /usr/local/bin (requires sudo)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the installer
|
||||||
|
install_lnk
|
7
main.go
7
main.go
@@ -2,6 +2,13 @@ package main
|
|||||||
|
|
||||||
import "github.com/yarlson/lnk/cmd"
|
import "github.com/yarlson/lnk/cmd"
|
||||||
|
|
||||||
|
// These variables are set by GoReleaser via ldflags
|
||||||
|
var (
|
||||||
|
version = "dev"
|
||||||
|
buildTime = "unknown"
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
cmd.SetVersion(version, buildTime)
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user