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
30 changes: 24 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,27 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true

jobs:
sync-main:
name: Sync main branch
runs-on: ubuntu-latest
# Only runs on v* tag pushes (release trigger). Uses force-push because main
# is a release-only mirror of develop — any commits on main not in develop
# are stale snapshots that should be overwritten by the current release.
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
- uses: actions/checkout@v4
with:
ref: develop

Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
- name: Push to main
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
run: |
git push origin HEAD:main --force
echo "✅ main synced to develop at ${{ github.sha }}"

build-release:
needs: sync-main
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
strategy:
Expand Down Expand Up @@ -152,18 +172,16 @@ jobs:
printf '| Windows (x86_64) | `cora-x86_64-pc-windows-msvc-%s.zip` |\n\n' "${{ steps.version.outputs.TAG }}"
printf '### 🚀 Quick Start\n\n'
printf '```bash\n'
printf '# Install via cargo\n'
printf '# Quick install (Linux / macOS)\n'
printf 'curl -fsSL https://raw.githubusercontent.com/codecoradev/cora-cli/main/install.sh | sh\n\n'
printf '# Or via cargo\n'
printf 'cargo install cora\n\n'
printf '# Or download binary (extracts as '\''cora'\'')\n'
printf 'curl -fsSL https://github.com/codecoradev/cora-cli/releases/latest/download/cora-x86_64-unknown-linux-gnu-%s.tar.gz | tar xz\n' "${{ steps.version.outputs.TAG }}"
printf 'chmod +x cora\n'
printf 'sudo mv cora /usr/local/bin/\n\n'
printf '# Init project\n'
printf 'cora init\n\n'
printf '# Review staged changes\n'
printf 'CORA_API_KEY=your-key cora review --staged\n'
printf '```\n\n'
printf '**Full changelog:** https://github.com/codecoradev/cora-cli/blob/develop/CHANGELOG.md\n'
printf '**Full changelog:** https://github.com/codecoradev/cora-cli/blob/main/CHANGELOG.md\n'
} > release-notes.md

- name: Create GitHub Release
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ Installs to `~/.local/bin`. Add to PATH if needed:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc # or ~/.zshrc
```

Pin a specific version with `CORA_VERSION`:

```bash
CORA_VERSION=v0.4.0 curl -fsSL https://raw.githubusercontent.com/codecoradev/cora-cli/main/install.sh | sh
```

### Pre-built Binaries

Download from [GitHub Releases](https://github.com/codecoradev/cora-cli/releases):
Expand Down Expand Up @@ -358,11 +364,9 @@ jobs:
Or install manually:

```yaml
# Manual install in CI
# Manual install in CI (using install script)
- name: Install cora-cli
run: |
curl -fsSL https://github.com/codecoradev/cora-cli/releases/latest/download/cora-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv cora /usr/local/bin/
run: curl -fsSL https://raw.githubusercontent.com/codecoradev/cora-cli/main/install.sh | sh
```

### GitLab CI
Expand Down
23 changes: 22 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,35 @@ install() {
TEMP_DIR=$(mktemp -d)
ARCHIVE="${TEMP_DIR}/${ARCHIVE_NAME}"

CHECKSUMS_URL="https://github.com/${REPO}/releases/download/${VERSION}/checksums-sha256.txt"
CHECKSUM_FILE="${TEMP_DIR}/checksums-sha256.txt"

info "Downloading from: $DOWNLOAD_URL"
if ! curl -fsSL "$DOWNLOAD_URL" -o "$ARCHIVE"; then
error "Failed to download ${ARCHIVE_NAME}"
fi

# Verify SHA256 checksum (prevents MITM / corrupted download).
info "Downloading checksums..."
if curl -fsSL "$CHECKSUMS_URL" -o "$CHECKSUM_FILE"; then
info "Verifying SHA256 checksum..."
EXPECTED=$(grep -F "$ARCHIVE_NAME" "$CHECKSUM_FILE" | awk '{print $1}')
if [ -n "$EXPECTED" ]; then
ACTUAL=$(sha256sum "$ARCHIVE" | awk '{print $1}')
if [ "$ACTUAL" != "$EXPECTED" ]; then
error "Checksum mismatch! Expected: ${EXPECTED}, got: ${ACTUAL}"
fi
info "Checksum verified: $EXPECTED"
else
warn "Checksum for ${ARCHIVE_NAME} not found in checksums file — skipping verification"
fi
else
warn "Failed to download checksums — skipping verification"
fi

# Verify archive contents before extraction (CWE-22 path traversal).
# Reject any entry with an absolute path or a ".." component.
info "Verifying archive..."
info "Verifying archive integrity..."
if tar -tzf "$ARCHIVE" | grep -qE '^/|(^|/)\.\.(/|$)'; then
error "Archive contains unsafe paths (absolute or directory traversal) — refusing to extract"
fi
Expand Down
Loading