Skip to content
Merged
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
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,53 @@ jobs:
run: npx github-actions-ctrf report.ctrf.json
if: always()

test-cli:
name: Test CLI
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
cache: true

- name: Get dependencies
run: |
cd cmd/modcli
go mod download
go mod verify

- name: Run CLI tests with coverage
run: |
cd cmd/modcli
go test ./... -v -coverprofile=cli-coverage.txt -covermode=atomic -json >> cli-report.json

- name: Upload CLI coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: GoCodeAlone/modular
directory: cmd/modcli/
files: cli-coverage.txt
flags: cli

- name: CTRF Test Output for CLI
run: |
go install github.com/ctrf-io/go-ctrf-json-reporter/cmd/go-ctrf-json-reporter@latest
cd cmd/modcli
cat cli-report.json | go-ctrf-json-reporter -o cli-report.ctrf.json
if: always()

- name: Publish CLI CTRF Test Summary Results
run: |
cd cmd/modcli
npx github-actions-ctrf cli-report.ctrf.json
if: always()

lint:
runs-on: ubuntu-latest
steps:
Expand Down
216 changes: 216 additions & 0 deletions .github/workflows/cli-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
name: Build and Release CLI

on:
push:
tags:
- 'cli-v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (leave blank for auto-increment)'
required: false
type: string
releaseType:
description: 'Release type'
required: true
type: choice
options:
- patch
- minor
- major
default: 'patch'

env:
GO_VERSION: '^1.23.5'

jobs:
prepare:
name: Prepare Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.determine_version.outputs.version }}
tag: ${{ steps.determine_version.outputs.tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Determine version
id: determine_version
run: |
# Determine if we're triggered by tag or manual workflow
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref_type }}" == "tag" ]]; then
# We're triggered by a tag push
VERSION="${GITHUB_REF#refs/tags/cli-v}"
echo "Using version from tag: $VERSION"
else
# We're triggered by workflow_dispatch, need to calculate version
# Find the latest tag for the CLI
LATEST_TAG=$(git tag -l "cli-v*" | sort -V | tail -n1 || echo "")
echo "Latest tag: $LATEST_TAG"

if [ -z "$LATEST_TAG" ]; then
# No existing tag, start with v0.0.0
CURRENT_VERSION="0.0.0"
echo "No previous version found, starting with 0.0.0"
else
CURRENT_VERSION=$(echo $LATEST_TAG | sed "s|cli-v||")
echo "Current version: $CURRENT_VERSION"
fi

# Extract the parts
MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1)
MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
PATCH=$(echo $CURRENT_VERSION | cut -d. -f3)

# Calculate next version based on release type
if [ "${{ github.event.inputs.releaseType }}" == "major" ]; then
VERSION="$((MAJOR + 1)).0.0"
elif [ "${{ github.event.inputs.releaseType }}" == "minor" ]; then
VERSION="${MAJOR}.$((MINOR + 1)).0"
else
VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
fi

# Use manual version if provided
if [ -n "${{ github.event.inputs.version }}" ]; then
MANUAL_VERSION="${{ github.event.inputs.version }}"
# Remove 'v' prefix if present
MANUAL_VERSION=$(echo $MANUAL_VERSION | sed 's/^v//')
VERSION="${MANUAL_VERSION}"
fi

echo "Calculated version: ${VERSION}"
fi

# Set outputs
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "tag=cli-v${VERSION}" >> $GITHUB_OUTPUT

- name: Create tag if needed
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
echo "Creating tag ${{ steps.determine_version.outputs.tag }}"
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git tag ${{ steps.determine_version.outputs.tag }} ${{ github.sha }}
git push origin ${{ steps.determine_version.outputs.tag }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

build:
name: Build CLI
needs: prepare
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
include:
- os: ubuntu-latest
artifact_name: modcli
asset_name: modcli-linux-amd64
- os: windows-latest
artifact_name: modcli.exe
asset_name: modcli-windows-amd64.exe
- os: macos-latest
artifact_name: modcli
asset_name: modcli-darwin-arm64

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true

- name: Build
run: |
cd cmd/modcli
go build -v -ldflags "-X github.com/GoCodeAlone/modular/cmd/modcli/cmd.Version=${{ needs.prepare.outputs.version }} -X github.com/GoCodeAlone/modular/cmd/modcli/cmd.Commit=${{ github.sha }} -X github.com/GoCodeAlone/modular/cmd/modcli/cmd.Date=$(date +'%Y-%m-%d')" -o ${{ matrix.artifact_name }}
shell: bash

- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.asset_name }}
path: cmd/modcli/${{ matrix.artifact_name }}

release:
name: Create Release
runs-on: ubuntu-latest
needs: [prepare, build]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch all history for changelog generation

- name: Generate changelog
id: changelog
run: |
# Get the current tag
CURRENT_TAG="${{ needs.prepare.outputs.tag }}"
VERSION="${{ needs.prepare.outputs.version }}"

# Find the previous tag for modcli to use as starting point for changelog
PREV_TAG=$(git tag -l "cli-v*" | grep -v "$CURRENT_TAG" | sort -V | tail -n1 || echo "")

echo "Current tag: $CURRENT_TAG, version: $VERSION"
echo "Previous tag: $PREV_TAG"

# Generate changelog by looking at commits that touched the modcli directory
if [ -z "$PREV_TAG" ]; then
echo "No previous modcli tag found, including all history for modcli"
CHANGELOG=$(git log --pretty=format:"- %s (%h)" -- "cmd/modcli")
else
echo "Generating changelog from $PREV_TAG to $CURRENT_TAG"
CHANGELOG=$(git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD -- "cmd/modcli")
fi

# If no specific changes found for modcli
if [ -z "$CHANGELOG" ]; then
CHANGELOG="- No specific changes to modcli since last release"
fi

# Save changelog to a file with version info
echo "# Modular CLI v${VERSION}" > changelog.md
echo "" >> changelog.md
echo "## Changes" >> changelog.md
echo "" >> changelog.md
echo "$CHANGELOG" >> changelog.md

cat changelog.md

- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: ./artifacts

- name: Create release
id: create_release
run: |
gh release create ${{ needs.prepare.outputs.tag }} \
--title "Modular CLI v${{ needs.prepare.outputs.version }}" \
--notes-file changelog.md \
--repo ${{ github.repository }} \
--latest=false './artifacts/modcli-linux-amd64/modcli#modcli-linux-amd64' \
'./artifacts/modcli-windows-amd64.exe/modcli.exe#modcli-windows-amd64.exe' \
'./artifacts/modcli-darwin-arm64/modcli#modcli-darwin-arm64'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Announce to Go proxy
run: |
VERSION="${{ needs.prepare.outputs.version }}"
MODULE_NAME="github.com/GoCodeAlone/modular/cmd/modcli"

GOPROXY=proxy.golang.org go list -m ${MODULE_NAME}@v${VERSION}

echo "Announced version ModCLI v${VERSION} to Go proxy"

- name: Display Release URL
run: echo "Released at ${{ steps.create_release.outputs.html_url }}"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ go.work.sum

# env file
.env
.idea
.idea
.DS_Store
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func main() {
app.RegisterModule(NewAPIModule())

// Run the application (this will block until the application is terminated)
if err := app.Run(); err != nil {
if err := app.Run(); err != nil) {
logger.Error("Application error", "error", err)
os.Exit(1)
}
Expand Down Expand Up @@ -469,6 +469,63 @@ type ConfigValidator interface {
}
```

## CLI Tool

Modular comes with a command-line tool (`modcli`) to help you create new modules and configurations.

### Installation

You can install the CLI tool using one of the following methods:

#### Using go install (recommended)

```bash
go install github.com/GoCodeAlone/modular/cmd/modcli@latest
```

This will download, build, and install the latest version of the CLI tool directly to your GOPATH's bin directory, which should be in your PATH.

#### Download pre-built binaries

Download the latest release from the [GitHub Releases page](https://github.com/GoCodeAlone/modular/releases) and add it to your PATH.

#### Build from source

```bash
# Clone the repository
git clone https://github.com/GoCodeAlone/modular.git
cd modular/cmd/modcli

# Build the CLI tool
go build -o modcli

# Move to a directory in your PATH
mv modcli /usr/local/bin/ # Linux/macOS
# or add the current directory to your PATH
```

### Usage

Generate a new module:

```bash
modcli generate module --name MyFeature
```

Generate a configuration:

```bash
modcli generate config --name Server
```

For more details on available commands:

```bash
modcli --help
```

Each command includes interactive prompts to guide you through the process of creating modules or configurations with the features you need.

## License

[MIT License](LICENSE)
Loading