mirror of
https://github.com/LukeHagar/usage-statistics.git
synced 2025-12-06 04:21:55 +00:00
Add Usage Statistics Tracker GitHub Action with configuration options, outputs, and README integration
This commit is contained in:
52
.github/workflows/test-action.yml
vendored
Normal file
52
.github/workflows/test-action.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
name: Test GitHub Action
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-action:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Bun
|
||||||
|
uses: oven-sh/setup-bun@v1
|
||||||
|
with:
|
||||||
|
bun-version: latest
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: bun install
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: bun test
|
||||||
|
|
||||||
|
- name: Build action
|
||||||
|
run: bun run action:build
|
||||||
|
|
||||||
|
- name: Test action with preview mode
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
preview-mode: 'true'
|
||||||
|
json-output-path: 'test-stats.json'
|
||||||
|
csv-output-path: 'test-stats.csv'
|
||||||
|
report-output-path: 'test-report.md'
|
||||||
|
update-readme: 'false'
|
||||||
|
|
||||||
|
- name: Check outputs
|
||||||
|
run: |
|
||||||
|
echo "Checking generated files..."
|
||||||
|
ls -la test-stats.* test-report.md || echo "No output files found (expected in preview mode)"
|
||||||
|
|
||||||
|
echo "Checking action outputs..."
|
||||||
|
echo "JSON output: ${{ steps.test-action.outputs.json-output }}"
|
||||||
|
echo "CSV output: ${{ steps.test-action.outputs.csv-output }}"
|
||||||
|
echo "Report output: ${{ steps.test-action.outputs.report-output }}"
|
||||||
|
echo "Total downloads: ${{ steps.test-action.outputs.total-downloads }}"
|
||||||
|
echo "Unique packages: ${{ steps.test-action.outputs.unique-packages }}"
|
||||||
|
echo "Platforms tracked: ${{ steps.test-action.outputs.platforms-tracked }}"
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Usage Statistics Tracker
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
258
PUBLISHING.md
Normal file
258
PUBLISHING.md
Normal file
@@ -0,0 +1,258 @@
|
|||||||
|
# Publishing to GitHub Marketplace
|
||||||
|
|
||||||
|
This guide walks you through the process of publishing the Usage Statistics Tracker to the GitHub Marketplace.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
1. **GitHub Account**: You need a GitHub account with a verified email
|
||||||
|
2. **Repository**: This repository should be public
|
||||||
|
3. **GitHub Actions**: Actions must be enabled on your repository
|
||||||
|
|
||||||
|
## Step 1: Prepare Your Repository
|
||||||
|
|
||||||
|
### 1.1 Build the Action
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
bun install
|
||||||
|
|
||||||
|
# Build the action for distribution
|
||||||
|
bun run action:build
|
||||||
|
|
||||||
|
# Verify the build
|
||||||
|
ls -la dist/
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.2 Commit the Built Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add the built files
|
||||||
|
git add dist/
|
||||||
|
|
||||||
|
# Commit with a descriptive message
|
||||||
|
git commit -m "build: add action distribution files for v1.0.0"
|
||||||
|
|
||||||
|
# Push to main branch
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### 1.3 Create a Release
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create and push a tag
|
||||||
|
git tag v1.0.0
|
||||||
|
git push origin v1.0.0
|
||||||
|
|
||||||
|
# Or create a release via GitHub UI:
|
||||||
|
# 1. Go to your repository
|
||||||
|
# 2. Click "Releases" on the right
|
||||||
|
# 3. Click "Create a new release"
|
||||||
|
# 4. Choose the tag v1.0.0
|
||||||
|
# 5. Add release notes
|
||||||
|
# 6. Publish release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 2: Publish to Marketplace
|
||||||
|
|
||||||
|
### 2.1 Access the Publishing Interface
|
||||||
|
|
||||||
|
1. Go to your repository on GitHub
|
||||||
|
2. Click on the **Actions** tab
|
||||||
|
3. Look for a banner that says "Publish this Action to the GitHub Marketplace"
|
||||||
|
4. Click **Publish this Action**
|
||||||
|
|
||||||
|
### 2.2 Fill in Action Details
|
||||||
|
|
||||||
|
#### Basic Information
|
||||||
|
- **Action name**: `usage-statistics-tracker`
|
||||||
|
- **Description**: `Track download statistics across multiple platforms (NPM, GitHub, PyPI, Homebrew, PowerShell, Postman, Go)`
|
||||||
|
- **Category**: Choose `Data` or `Utilities`
|
||||||
|
- **Icon**: Upload a relevant icon (512x512px PNG recommended)
|
||||||
|
- **Color**: Choose a brand color (e.g., `#0366d6` for blue)
|
||||||
|
|
||||||
|
#### Detailed Description
|
||||||
|
Use the content from the main README.md file, focusing on:
|
||||||
|
- Features and capabilities
|
||||||
|
- Usage examples
|
||||||
|
- Configuration options
|
||||||
|
- Supported platforms
|
||||||
|
|
||||||
|
#### Keywords
|
||||||
|
Add relevant keywords:
|
||||||
|
- `statistics`
|
||||||
|
- `analytics`
|
||||||
|
- `downloads`
|
||||||
|
- `npm`
|
||||||
|
- `github`
|
||||||
|
- `pypi`
|
||||||
|
- `homebrew`
|
||||||
|
- `powershell`
|
||||||
|
- `postman`
|
||||||
|
- `go`
|
||||||
|
- `tracking`
|
||||||
|
- `usage`
|
||||||
|
|
||||||
|
### 2.3 Marketplace Listing
|
||||||
|
|
||||||
|
#### Action Name
|
||||||
|
- **Marketplace name**: `Usage Statistics Tracker`
|
||||||
|
- **Description**: `Comprehensive GitHub Action for tracking download statistics across multiple platforms with configurable outputs and README integration`
|
||||||
|
|
||||||
|
#### Categories
|
||||||
|
- **Primary category**: `Data`
|
||||||
|
- **Secondary category**: `Utilities`
|
||||||
|
|
||||||
|
#### Pricing
|
||||||
|
- **Pricing model**: Free
|
||||||
|
- **License**: MIT
|
||||||
|
|
||||||
|
## Step 3: Version Management
|
||||||
|
|
||||||
|
### 3.1 Semantic Versioning
|
||||||
|
|
||||||
|
Follow semantic versioning for releases:
|
||||||
|
- **Major** (1.0.0): Breaking changes
|
||||||
|
- **Minor** (1.1.0): New features, backward compatible
|
||||||
|
- **Patch** (1.0.1): Bug fixes
|
||||||
|
|
||||||
|
### 3.2 Release Process
|
||||||
|
|
||||||
|
For each new version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Update version in package.json
|
||||||
|
# 2. Update CHANGELOG.md
|
||||||
|
# 3. Build the action
|
||||||
|
bun run action:build
|
||||||
|
|
||||||
|
# 4. Commit changes
|
||||||
|
git add .
|
||||||
|
git commit -m "feat: release v1.1.0"
|
||||||
|
|
||||||
|
# 5. Create and push tag
|
||||||
|
git tag v1.1.0
|
||||||
|
git push origin v1.1.0
|
||||||
|
|
||||||
|
# 6. Create GitHub release
|
||||||
|
# Go to GitHub and create a release for the new tag
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 Changelog
|
||||||
|
|
||||||
|
Maintain a `CHANGELOG.md` file:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## [1.1.0] - 2025-01-XX
|
||||||
|
### Added
|
||||||
|
- New platform support for X
|
||||||
|
- Enhanced error handling
|
||||||
|
- Additional configuration options
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- Improved performance for large datasets
|
||||||
|
- Updated dependencies
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Bug fix for Y platform
|
||||||
|
- Resolved issue with Z feature
|
||||||
|
|
||||||
|
## [1.0.0] - 2025-01-XX
|
||||||
|
### Added
|
||||||
|
- Initial release
|
||||||
|
- Support for NPM, GitHub, PyPI, Homebrew, PowerShell, Postman, Go
|
||||||
|
- Configurable outputs (JSON, CSV, human-readable)
|
||||||
|
- README integration
|
||||||
|
- Preview mode
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 4: Marketing and Documentation
|
||||||
|
|
||||||
|
### 4.1 README Optimization
|
||||||
|
|
||||||
|
Ensure your README includes:
|
||||||
|
- Clear installation instructions
|
||||||
|
- Multiple usage examples
|
||||||
|
- Configuration documentation
|
||||||
|
- Troubleshooting section
|
||||||
|
- Contributing guidelines
|
||||||
|
|
||||||
|
### 4.2 Examples Repository
|
||||||
|
|
||||||
|
Consider creating a separate repository with examples:
|
||||||
|
- Basic usage workflows
|
||||||
|
- Advanced configurations
|
||||||
|
- Custom integrations
|
||||||
|
- Troubleshooting guides
|
||||||
|
|
||||||
|
### 4.3 Social Media
|
||||||
|
|
||||||
|
Promote your action on:
|
||||||
|
- GitHub Discussions
|
||||||
|
- Reddit (r/github, r/devops)
|
||||||
|
- Twitter/X with relevant hashtags
|
||||||
|
- LinkedIn for professional audience
|
||||||
|
|
||||||
|
## Step 5: Maintenance
|
||||||
|
|
||||||
|
### 5.1 Monitoring
|
||||||
|
|
||||||
|
- Monitor GitHub Issues for user feedback
|
||||||
|
- Track download statistics
|
||||||
|
- Respond to questions and bug reports
|
||||||
|
- Update documentation as needed
|
||||||
|
|
||||||
|
### 5.2 Updates
|
||||||
|
|
||||||
|
Regular maintenance tasks:
|
||||||
|
- Update dependencies
|
||||||
|
- Fix security vulnerabilities
|
||||||
|
- Add new platform support
|
||||||
|
- Improve performance
|
||||||
|
- Enhance documentation
|
||||||
|
|
||||||
|
### 5.3 Community Engagement
|
||||||
|
|
||||||
|
- Respond to issues promptly
|
||||||
|
- Help users with configuration
|
||||||
|
- Accept and review pull requests
|
||||||
|
- Maintain a welcoming community
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Action not found**: Ensure the action is properly built and tagged
|
||||||
|
2. **Build failures**: Check that all dependencies are included
|
||||||
|
3. **Permission issues**: Verify GitHub token permissions
|
||||||
|
4. **Rate limiting**: Implement proper rate limiting in the action
|
||||||
|
|
||||||
|
### Support
|
||||||
|
|
||||||
|
- GitHub Issues: For bug reports and feature requests
|
||||||
|
- GitHub Discussions: For questions and community support
|
||||||
|
- Documentation: Comprehensive README and examples
|
||||||
|
|
||||||
|
## Success Metrics
|
||||||
|
|
||||||
|
Track these metrics to measure success:
|
||||||
|
- **Downloads**: Number of action downloads
|
||||||
|
- **Stars**: Repository stars
|
||||||
|
- **Forks**: Repository forks
|
||||||
|
- **Issues**: User engagement and feedback
|
||||||
|
- **Usage**: Number of repositories using the action
|
||||||
|
|
||||||
|
## Legal Considerations
|
||||||
|
|
||||||
|
- **License**: MIT License (included)
|
||||||
|
- **Privacy**: No personal data collection
|
||||||
|
- **Terms of Service**: Follow GitHub's terms
|
||||||
|
- **Attribution**: Credit original authors if applicable
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
||||||
|
- [GitHub Marketplace Guidelines](https://docs.github.com/en/developers/github-marketplace)
|
||||||
|
- [Action Metadata Syntax](https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions)
|
||||||
|
- [Publishing Actions](https://docs.github.com/en/actions/creating-actions/publishing-actions-in-github-marketplace)
|
||||||
405
README.md
405
README.md
@@ -1,184 +1,323 @@
|
|||||||
# Usage Statistics
|
# Usage Statistics Tracker
|
||||||
|
|
||||||
A Bun TypeScript script project for analyzing usage statistics with a clean, modern architecture.
|
A comprehensive GitHub Action for tracking download statistics across multiple platforms (NPM, GitHub, PyPI, Homebrew, PowerShell, Postman, Go) with configurable outputs and README integration.
|
||||||
|
|
||||||
## Features
|
## 🚀 Features
|
||||||
|
|
||||||
- 🚀 **Fast Execution**: Built with Bun for lightning-fast TypeScript execution
|
- 📊 **Multi-Platform Tracking**: NPM, GitHub, PyPI, Homebrew, PowerShell, Postman, Go
|
||||||
- 📊 **Usage Analytics**: Track user actions and generate statistics
|
- 🎭 **Preview Mode**: Test with mock data without external API calls
|
||||||
- 🧪 **Comprehensive Testing**: Full test suite with Bun's built-in test runner
|
- 📄 **Flexible Outputs**: JSON, CSV, and human-readable reports
|
||||||
- 📦 **Modern Tooling**: TypeScript, ES modules, and modern JavaScript features
|
- 📝 **README Integration**: Auto-update README with statistics
|
||||||
- 🔧 **Developer Friendly**: Hot reloading, watch mode, and excellent DX
|
- ⚙️ **Configurable**: Custom configurations via JSON or preset modes
|
||||||
|
- 🔄 **GitHub Actions Ready**: Built for CI/CD workflows
|
||||||
|
- 🧪 **Comprehensive Testing**: Full test suite with Bun
|
||||||
|
|
||||||
## Prerequisites
|
## 📦 Installation
|
||||||
|
|
||||||
- [Bun](https://bun.sh/) (version 1.0.0 or higher)
|
### As a GitHub Action
|
||||||
|
|
||||||
## Installation
|
```yaml
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
|
json-output-path: 'stats.json'
|
||||||
|
csv-output-path: 'stats.csv'
|
||||||
|
report-output-path: 'report.md'
|
||||||
|
update-readme: 'true'
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
bun install
|
bun install
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
# Run the tracker
|
||||||
|
|
||||||
### Running the Script
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run the main script
|
|
||||||
bun start
|
bun start
|
||||||
|
|
||||||
# Preview the report with mock data (no external API calls)
|
# Preview mode (no external API calls)
|
||||||
bun preview
|
bun preview
|
||||||
|
|
||||||
# Run in development mode with hot reloading
|
# Run tests
|
||||||
bun run dev
|
bun test
|
||||||
|
|
||||||
# Run directly with bun
|
|
||||||
bun run src/index.ts
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Preview Mode
|
## 🔧 Configuration
|
||||||
|
|
||||||
The preview mode allows you to see how the report will look without making any external API calls or writing files:
|
### Input Parameters
|
||||||
|
|
||||||
```bash
|
| Parameter | Description | Required | Default |
|
||||||
# Generate a preview report with mock data
|
|-----------|-------------|----------|---------|
|
||||||
bun preview
|
| `config` | Configuration mode or JSON | No | `production` |
|
||||||
|
| `json-output-path` | Path for JSON output | No | `stats.json` |
|
||||||
|
| `csv-output-path` | Path for CSV output | No | (empty) |
|
||||||
|
| `report-output-path` | Path for human-readable report | No | (empty) |
|
||||||
|
| `update-readme` | Whether to update README | No | `true` |
|
||||||
|
| `readme-path` | Path to README file | No | `README.md` |
|
||||||
|
| `github-token` | GitHub token for API access | No | `${{ github.token }}` |
|
||||||
|
| `postman-api-key` | Postman API key | No | (empty) |
|
||||||
|
| `commit-message` | Commit message for changes | No | `chore: update usage statistics [skip ci]` |
|
||||||
|
| `preview-mode` | Run with mock data | No | `false` |
|
||||||
|
|
||||||
# Or use the long flag
|
### Configuration Modes
|
||||||
bun start --preview
|
|
||||||
|
#### Production Mode
|
||||||
|
```yaml
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
```
|
```
|
||||||
|
|
||||||
This is useful for:
|
#### Development Mode
|
||||||
- Testing the report format
|
```yaml
|
||||||
- Demonstrating the functionality
|
- name: Usage Statistics Tracker
|
||||||
- Development and debugging
|
uses: your-username/usage-statistics@v1
|
||||||
- CI/CD testing without external dependencies
|
with:
|
||||||
|
config: 'development'
|
||||||
### Building
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Build the project
|
|
||||||
bun run build
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing
|
#### Custom JSON Configuration
|
||||||
|
```yaml
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: '{"npmPackages": ["lodash", "axios"], "githubRepositories": ["microsoft/vscode"]}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Outputs
|
||||||
|
|
||||||
|
| Output | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `json-output` | Path to the generated JSON file |
|
||||||
|
| `csv-output` | Path to the generated CSV file |
|
||||||
|
| `report-output` | Path to the generated report file |
|
||||||
|
| `total-downloads` | Total downloads across all platforms |
|
||||||
|
| `unique-packages` | Number of unique packages tracked |
|
||||||
|
| `platforms-tracked` | Comma-separated list of platforms tracked |
|
||||||
|
|
||||||
|
## 📋 Usage Examples
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: Update Usage Statistics
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # Daily at midnight
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-stats:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
|
json-output-path: 'stats.json'
|
||||||
|
update-readme: 'true'
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Commit and push changes
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add stats.json README.md
|
||||||
|
git commit -m "chore: update usage statistics [skip ci]" || echo "No changes to commit"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Usage with Multiple Outputs
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
|
json-output-path: 'data/stats.json'
|
||||||
|
csv-output-path: 'data/stats.csv'
|
||||||
|
report-output-path: 'docs/usage-report.md'
|
||||||
|
update-readme: 'true'
|
||||||
|
readme-path: 'README.md'
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
postman-api-key: ${{ secrets.POSTMAN_API_KEY }}
|
||||||
|
commit-message: 'feat: update usage statistics with detailed report'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Preview Mode for Testing
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Test Usage Statistics
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
preview-mode: 'true'
|
||||||
|
json-output-path: 'test-stats.json'
|
||||||
|
csv-output-path: 'test-stats.csv'
|
||||||
|
report-output-path: 'test-report.md'
|
||||||
|
update-readme: 'false'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Outputs in Subsequent Steps
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
id: stats
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
|
json-output-path: 'stats.json'
|
||||||
|
|
||||||
|
- name: Use Statistics Data
|
||||||
|
run: |
|
||||||
|
echo "Total downloads: ${{ steps.stats.outputs.total-downloads }}"
|
||||||
|
echo "Unique packages: ${{ steps.stats.outputs.unique-packages }}"
|
||||||
|
echo "Platforms: ${{ steps.stats.outputs.platforms-tracked }}"
|
||||||
|
echo "JSON file: ${{ steps.stats.outputs.json-output }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 README Integration
|
||||||
|
|
||||||
|
To enable automatic README updates, add these markers to your README.md:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
<!-- USAGE_STATS_START -->
|
||||||
|
## 📊 Usage Statistics
|
||||||
|
|
||||||
|
Last updated: 2025-07-29T18:53:52.619Z
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
- **Total Downloads**: 414,533
|
||||||
|
- **Unique Packages**: 8
|
||||||
|
- **Platforms Tracked**: npm, pypi, homebrew, go
|
||||||
|
|
||||||
|
### Top Packages
|
||||||
|
1. **node** (homebrew) - 226,882 downloads
|
||||||
|
2. **git** (homebrew) - 153,281 downloads
|
||||||
|
3. **axios** (npm) - 18,397 downloads
|
||||||
|
4. **lodash** (npm) - 15,914 downloads
|
||||||
|
5. **github.com/go-chi/chi** (go) - 33 downloads
|
||||||
|
|
||||||
|
### Recent Activity
|
||||||
|
- **node** (homebrew) - 226,882 downloads on 7/29/2025
|
||||||
|
- **git** (homebrew) - 153,281 downloads on 7/29/2025
|
||||||
|
- **axios** (npm) - 722 downloads on 7/29/2025
|
||||||
|
- **lodash** (npm) - 857 downloads on 7/29/2025
|
||||||
|
- **axios** (npm) - 936 downloads on 7/28/2025
|
||||||
|
<!-- USAGE_STATS_END -->
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- [Bun](https://bun.sh/) (version 1.0.0 or higher)
|
||||||
|
|
||||||
|
### Local Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run all tests
|
# Install dependencies
|
||||||
|
bun install
|
||||||
|
|
||||||
|
# Run in development mode
|
||||||
|
bun dev
|
||||||
|
|
||||||
|
# Run tests
|
||||||
bun test
|
bun test
|
||||||
|
|
||||||
# Run tests in watch mode
|
# Build the action
|
||||||
bun test --watch
|
bun run action:build
|
||||||
|
|
||||||
|
# Test the action locally
|
||||||
|
bun run action:test
|
||||||
```
|
```
|
||||||
|
|
||||||
## Project Structure
|
### Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
usage-statistics/
|
usage-statistics/
|
||||||
├── src/
|
├── src/
|
||||||
│ ├── index.ts # Main entry point
|
│ ├── index.ts # Main library entry point
|
||||||
│ ├── index.test.ts # Test suite
|
│ ├── action.ts # GitHub Action entry point
|
||||||
│ └── test-setup.ts # Test configuration
|
│ ├── config.ts # Configuration management
|
||||||
|
│ ├── aggregator.ts # Statistics aggregation
|
||||||
|
│ ├── types/ # TypeScript type definitions
|
||||||
|
│ ├── trackers/ # Platform-specific trackers
|
||||||
|
│ └── utils/ # Utility functions
|
||||||
|
├── .github/
|
||||||
|
│ └── workflows/ # GitHub Actions workflows
|
||||||
|
├── action.yml # Action metadata
|
||||||
├── package.json # Project configuration
|
├── package.json # Project configuration
|
||||||
├── tsconfig.json # TypeScript configuration
|
|
||||||
├── bunfig.toml # Bun configuration
|
|
||||||
├── .gitignore # Git ignore rules
|
|
||||||
└── README.md # This file
|
└── README.md # This file
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Reference
|
## 🚀 Publishing to GitHub Marketplace
|
||||||
|
|
||||||
### UsageStatistics Class
|
### 1. Prepare Your Repository
|
||||||
|
|
||||||
The main class for tracking and analyzing usage data.
|
1. **Create a release tag**:
|
||||||
|
```bash
|
||||||
|
git tag v1.0.0
|
||||||
|
git push origin v1.0.0
|
||||||
|
```
|
||||||
|
|
||||||
#### Methods
|
2. **Build the action**:
|
||||||
|
```bash
|
||||||
|
bun run action:build
|
||||||
|
```
|
||||||
|
|
||||||
- `addUsage(userId: string, action: string, metadata?: Record<string, any>)`: Add a new usage record
|
3. **Commit the built files**:
|
||||||
- `getAllData()`: Get all usage data
|
```bash
|
||||||
- `getUserData(userId: string)`: Get usage data for a specific user
|
git add dist/
|
||||||
- `getActionData(action: string)`: Get usage data for a specific action
|
git commit -m "build: add action distribution files"
|
||||||
- `getStatistics()`: Get comprehensive statistics summary
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
#### Example Usage
|
### 2. Publish to Marketplace
|
||||||
|
|
||||||
```typescript
|
1. Go to your repository on GitHub
|
||||||
import { UsageStatistics } from './src/index';
|
2. Click on the **Actions** tab
|
||||||
|
3. Click **Publish this Action to the GitHub Marketplace**
|
||||||
|
4. Fill in the required information:
|
||||||
|
- **Action name**: `usage-statistics-tracker`
|
||||||
|
- **Description**: `Track download statistics across multiple platforms`
|
||||||
|
- **Category**: `Data` or `Utilities`
|
||||||
|
- **Icon**: Upload an appropriate icon
|
||||||
|
- **Color**: Choose a brand color
|
||||||
|
- **README**: Use the content from this README
|
||||||
|
|
||||||
const stats = new UsageStatistics();
|
### 3. Version Management
|
||||||
|
|
||||||
// Add usage data
|
For each new version:
|
||||||
stats.addUsage("user1", "login", { browser: "chrome" });
|
|
||||||
stats.addUsage("user2", "logout");
|
|
||||||
|
|
||||||
// Get statistics
|
|
||||||
const summary = stats.getStatistics();
|
|
||||||
console.log(`Total records: ${summary.totalRecords}`);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
### Scripts
|
|
||||||
|
|
||||||
- `bun start`: Run the main script
|
|
||||||
- `bun run dev`: Run in development mode with file watching
|
|
||||||
- `bun run build`: Build the project for production
|
|
||||||
- `bun test`: Run the test suite
|
|
||||||
|
|
||||||
### Adding Dependencies
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Add a production dependency
|
# Update version in package.json
|
||||||
bun add <package-name>
|
# Build the action
|
||||||
|
bun run action:build
|
||||||
|
|
||||||
# Add a development dependency
|
# Create and push a new tag
|
||||||
bun add -d <package-name>
|
git tag v1.1.0
|
||||||
|
git push origin v1.1.0
|
||||||
```
|
```
|
||||||
|
|
||||||
## GitHub Actions Integration
|
## 📈 Supported Platforms
|
||||||
|
|
||||||
This project includes a GitHub Actions workflow that automatically updates usage statistics and commits the results to the repository.
|
- **NPM**: Package download statistics
|
||||||
|
- **GitHub**: Release download statistics
|
||||||
|
- **PyPI**: Python package downloads
|
||||||
|
- **Homebrew**: Formula installation statistics
|
||||||
|
- **PowerShell**: Module download statistics
|
||||||
|
- **Postman**: Collection fork/download statistics
|
||||||
|
- **Go**: Module proxy statistics
|
||||||
|
|
||||||
### Setup
|
## 🤝 Contributing
|
||||||
|
|
||||||
1. **Enable the workflow**: The workflow file is located at `.github/workflows/update-stats.yml`
|
|
||||||
2. **Configure your packages**: Update `src/config.ts` with your actual package names
|
|
||||||
3. **Set up environment variables** (if needed):
|
|
||||||
- `GITHUB_TOKEN`: Automatically provided by GitHub Actions
|
|
||||||
- `POSTMAN_API_KEY`: If tracking Postman collections
|
|
||||||
|
|
||||||
### Workflow Features
|
|
||||||
|
|
||||||
- **Scheduled runs**: Updates stats daily at 2 AM UTC
|
|
||||||
- **Manual triggering**: Can be run manually via GitHub Actions UI
|
|
||||||
- **Rate limiting**: Built-in rate limiting to avoid API abuse
|
|
||||||
- **Auto-commit**: Automatically commits `stats.json` and updates README
|
|
||||||
- **Error handling**: Graceful handling of API failures
|
|
||||||
|
|
||||||
### Customization
|
|
||||||
|
|
||||||
Edit `src/config.ts` to track your specific packages:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
export const defaultConfig: TrackingConfig = {
|
|
||||||
npmPackages: ['your-package-name'],
|
|
||||||
githubRepos: ['your-org/your-repo'],
|
|
||||||
// ... other platforms
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### Manual Execution
|
|
||||||
|
|
||||||
Run locally with GitHub Action mode:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GITHUB_TOKEN=your_token bun run src/index.ts --action
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
1. Fork the repository
|
1. Fork the repository
|
||||||
2. Create a feature branch
|
2. Create a feature branch
|
||||||
@@ -187,6 +326,12 @@ GITHUB_TOKEN=your_token bun run src/index.ts --action
|
|||||||
5. Run the test suite
|
5. Run the test suite
|
||||||
6. Submit a pull request
|
6. Submit a pull request
|
||||||
|
|
||||||
## License
|
## 📄 License
|
||||||
|
|
||||||
This project is open source and available under the [MIT License](LICENSE).
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## 🙏 Acknowledgments
|
||||||
|
|
||||||
|
- Built with [Bun](https://bun.sh/) for fast TypeScript execution
|
||||||
|
- Uses [Octokit](https://github.com/octokit/octokit.js) for GitHub API integration
|
||||||
|
- Inspired by the need for comprehensive usage analytics across multiple platforms
|
||||||
83
action.yml
Normal file
83
action.yml
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
name: 'Usage Statistics Tracker'
|
||||||
|
description: 'Track download statistics across multiple platforms (NPM, GitHub, PyPI, Homebrew, PowerShell, Postman, Go)'
|
||||||
|
author: 'Your Name'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
# Configuration
|
||||||
|
config:
|
||||||
|
description: 'Configuration for tracking (development, production, test, or custom JSON)'
|
||||||
|
required: false
|
||||||
|
default: 'production'
|
||||||
|
|
||||||
|
# Output paths
|
||||||
|
json-output-path:
|
||||||
|
description: 'Path for JSON output file'
|
||||||
|
required: false
|
||||||
|
default: 'stats.json'
|
||||||
|
|
||||||
|
csv-output-path:
|
||||||
|
description: 'Path for CSV output file'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
report-output-path:
|
||||||
|
description: 'Path for human-readable report file'
|
||||||
|
required: false
|
||||||
|
default: ''
|
||||||
|
|
||||||
|
# README update
|
||||||
|
update-readme:
|
||||||
|
description: 'Whether to update README.md with statistics'
|
||||||
|
required: false
|
||||||
|
default: 'true'
|
||||||
|
|
||||||
|
readme-path:
|
||||||
|
description: 'Path to README file to update'
|
||||||
|
required: false
|
||||||
|
default: 'README.md'
|
||||||
|
|
||||||
|
# GitHub integration
|
||||||
|
github-token:
|
||||||
|
description: 'GitHub token for API access and commits'
|
||||||
|
required: false
|
||||||
|
default: '${{ github.token }}'
|
||||||
|
|
||||||
|
# Postman integration
|
||||||
|
postman-api-key:
|
||||||
|
description: 'Postman API key for collection statistics'
|
||||||
|
required: false
|
||||||
|
|
||||||
|
# Commit settings
|
||||||
|
commit-message:
|
||||||
|
description: 'Commit message for changes'
|
||||||
|
required: false
|
||||||
|
default: 'chore: update usage statistics [skip ci]'
|
||||||
|
|
||||||
|
# Preview mode
|
||||||
|
preview-mode:
|
||||||
|
description: 'Run in preview mode with mock data (no external API calls)'
|
||||||
|
required: false
|
||||||
|
default: 'false'
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
json-output:
|
||||||
|
description: 'Path to the generated JSON file'
|
||||||
|
|
||||||
|
csv-output:
|
||||||
|
description: 'Path to the generated CSV file'
|
||||||
|
|
||||||
|
report-output:
|
||||||
|
description: 'Path to the generated report file'
|
||||||
|
|
||||||
|
total-downloads:
|
||||||
|
description: 'Total downloads across all platforms'
|
||||||
|
|
||||||
|
unique-packages:
|
||||||
|
description: 'Number of unique packages tracked'
|
||||||
|
|
||||||
|
platforms-tracked:
|
||||||
|
description: 'Comma-separated list of platforms tracked'
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: 'node20'
|
||||||
|
main: 'dist/index.js'
|
||||||
15
bun.lock
15
bun.lock
@@ -4,6 +4,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "usage-statistics",
|
"name": "usage-statistics",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@actions/core": "1.11.1",
|
||||||
"@octokit/rest": "22.0.0",
|
"@octokit/rest": "22.0.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -14,6 +15,16 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
"@actions/core": ["@actions/core@1.11.1", "", { "dependencies": { "@actions/exec": "^1.1.1", "@actions/http-client": "^2.0.1" } }, "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A=="],
|
||||||
|
|
||||||
|
"@actions/exec": ["@actions/exec@1.1.1", "", { "dependencies": { "@actions/io": "^1.0.1" } }, "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w=="],
|
||||||
|
|
||||||
|
"@actions/http-client": ["@actions/http-client@2.2.3", "", { "dependencies": { "tunnel": "^0.0.6", "undici": "^5.25.4" } }, "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA=="],
|
||||||
|
|
||||||
|
"@actions/io": ["@actions/io@1.1.3", "", {}, "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q=="],
|
||||||
|
|
||||||
|
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
|
||||||
|
|
||||||
"@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="],
|
"@octokit/auth-token": ["@octokit/auth-token@6.0.0", "", {}, "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w=="],
|
||||||
|
|
||||||
"@octokit/core": ["@octokit/core@7.0.3", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.1", "@octokit/request": "^10.0.2", "@octokit/request-error": "^7.0.0", "@octokit/types": "^14.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ=="],
|
"@octokit/core": ["@octokit/core@7.0.3", "", { "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.1", "@octokit/request": "^10.0.2", "@octokit/request-error": "^7.0.0", "@octokit/types": "^14.0.0", "before-after-hook": "^4.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ=="],
|
||||||
@@ -50,8 +61,12 @@
|
|||||||
|
|
||||||
"fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="],
|
"fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="],
|
||||||
|
|
||||||
|
"tunnel": ["tunnel@0.0.6", "", {}, "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
"typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
|
||||||
|
|
||||||
|
"undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||||
|
|
||||||
"universal-user-agent": ["universal-user-agent@7.0.3", "", {}, "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A=="],
|
"universal-user-agent": ["universal-user-agent@7.0.3", "", {}, "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A=="],
|
||||||
|
|||||||
33
examples/basic-usage.yml
Normal file
33
examples/basic-usage.yml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Update Usage Statistics
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * *' # Daily at midnight
|
||||||
|
workflow_dispatch: # Allow manual triggering
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-stats:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Usage Statistics Tracker
|
||||||
|
uses: your-username/usage-statistics@v1
|
||||||
|
with:
|
||||||
|
config: 'production'
|
||||||
|
json-output-path: 'stats.json'
|
||||||
|
csv-output-path: 'stats.csv'
|
||||||
|
report-output-path: 'docs/usage-report.md'
|
||||||
|
update-readme: 'true'
|
||||||
|
readme-path: 'README.md'
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Commit and push changes
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
git add stats.json stats.csv docs/usage-report.md README.md
|
||||||
|
git commit -m "chore: update usage statistics [skip ci]" || echo "No changes to commit"
|
||||||
|
git push
|
||||||
@@ -8,7 +8,9 @@
|
|||||||
"preview": "bun run src/index.ts --preview",
|
"preview": "bun run src/index.ts --preview",
|
||||||
"dev": "bun --watch src/index.ts",
|
"dev": "bun --watch src/index.ts",
|
||||||
"build": "bun build src/index.ts --outdir dist",
|
"build": "bun build src/index.ts --outdir dist",
|
||||||
"test": "bun test"
|
"test": "bun test",
|
||||||
|
"action:build": "bun build src/action.ts --outdir dist --target node --minify",
|
||||||
|
"action:test": "bun test && bun run action:build"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.0.0",
|
"@types/node": "^20.0.0",
|
||||||
@@ -16,6 +18,7 @@
|
|||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@actions/core": "1.11.1",
|
||||||
"@octokit/rest": "22.0.0"
|
"@octokit/rest": "22.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
196
src/action.ts
Normal file
196
src/action.ts
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
#!/usr/bin/env bun
|
||||||
|
import * as core from '@actions/core';
|
||||||
|
import * as fs from 'fs/promises';
|
||||||
|
import * as path from 'path';
|
||||||
|
import { UsageStatisticsManager } from './index';
|
||||||
|
import { getConfig, validateConfig } from './config';
|
||||||
|
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
// Get inputs
|
||||||
|
const configInput = core.getInput('config');
|
||||||
|
const jsonOutputPath = core.getInput('json-output-path');
|
||||||
|
const csvOutputPath = core.getInput('csv-output-path');
|
||||||
|
const reportOutputPath = core.getInput('report-output-path');
|
||||||
|
const updateReadme = core.getInput('update-readme') === 'true';
|
||||||
|
const readmePath = core.getInput('readme-path');
|
||||||
|
const githubToken = core.getInput('github-token');
|
||||||
|
const postmanApiKey = core.getInput('postman-api-key');
|
||||||
|
const commitMessage = core.getInput('commit-message');
|
||||||
|
const previewMode = core.getInput('preview-mode') === 'true';
|
||||||
|
|
||||||
|
// Set environment variables
|
||||||
|
if (githubToken) {
|
||||||
|
process.env.GITHUB_TOKEN = githubToken;
|
||||||
|
}
|
||||||
|
if (postmanApiKey) {
|
||||||
|
process.env.POSTMAN_API_KEY = postmanApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get configuration
|
||||||
|
let trackingConfig;
|
||||||
|
if (configInput === 'development' || configInput === 'production' || configInput === 'test') {
|
||||||
|
trackingConfig = getConfig(configInput as 'development' | 'production' | 'test');
|
||||||
|
} else {
|
||||||
|
// Try to parse as JSON
|
||||||
|
try {
|
||||||
|
trackingConfig = JSON.parse(configInput);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Invalid config input: ${configInput}. Must be 'development', 'production', 'test', or valid JSON.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate configuration
|
||||||
|
try {
|
||||||
|
validateConfig(trackingConfig);
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Configuration validation failed: ${error}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create manager
|
||||||
|
const manager = new UsageStatisticsManager(trackingConfig);
|
||||||
|
|
||||||
|
// Generate report
|
||||||
|
let report;
|
||||||
|
if (previewMode) {
|
||||||
|
core.info('🎭 Running in preview mode with mock data...');
|
||||||
|
report = await manager.generatePreviewReport();
|
||||||
|
} else {
|
||||||
|
core.info('📊 Generating comprehensive usage statistics report...');
|
||||||
|
report = await manager.generateComprehensiveReport();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display report
|
||||||
|
await manager.displayReport(report);
|
||||||
|
|
||||||
|
// Write JSON output
|
||||||
|
if (jsonOutputPath) {
|
||||||
|
const jsonContent = JSON.stringify(report, null, 2);
|
||||||
|
await fs.writeFile(jsonOutputPath, jsonContent);
|
||||||
|
core.info(`📄 JSON report written to ${jsonOutputPath}`);
|
||||||
|
core.setOutput('json-output', jsonOutputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write CSV output
|
||||||
|
if (csvOutputPath) {
|
||||||
|
const csvReport = await manager.exportReport('csv');
|
||||||
|
await fs.writeFile(csvOutputPath, csvReport);
|
||||||
|
core.info(`📊 CSV report written to ${csvOutputPath}`);
|
||||||
|
core.setOutput('csv-output', csvOutputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write human-readable report
|
||||||
|
if (reportOutputPath) {
|
||||||
|
const reportContent = await generateHumanReadableReport(report);
|
||||||
|
await fs.writeFile(reportOutputPath, reportContent);
|
||||||
|
core.info(`📋 Human-readable report written to ${reportOutputPath}`);
|
||||||
|
core.setOutput('report-output', reportOutputPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update README if requested
|
||||||
|
if (updateReadme && readmePath) {
|
||||||
|
try {
|
||||||
|
await updateReadmeWithStats(report, readmePath);
|
||||||
|
core.info(`📝 README updated at ${readmePath}`);
|
||||||
|
} catch (error) {
|
||||||
|
core.warning(`Failed to update README: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set outputs
|
||||||
|
core.setOutput('total-downloads', report.totalDownloads.toString());
|
||||||
|
core.setOutput('unique-packages', report.uniquePackages.toString());
|
||||||
|
core.setOutput('platforms-tracked', report.platforms.join(','));
|
||||||
|
|
||||||
|
core.info('✅ Usage Statistics Tracker completed successfully!');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
core.setFailed(`Action failed: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateHumanReadableReport(report: any): Promise<string> {
|
||||||
|
let content = '# Usage Statistics Report\n\n';
|
||||||
|
content += `Generated on: ${new Date().toISOString()}\n\n`;
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
content += '## Summary\n\n';
|
||||||
|
content += `- **Total Downloads**: ${report.totalDownloads.toLocaleString()}\n`;
|
||||||
|
content += `- **Unique Packages**: ${report.uniquePackages}\n`;
|
||||||
|
content += `- **Platforms Tracked**: ${report.platforms.join(', ')}\n\n`;
|
||||||
|
|
||||||
|
// Platform Breakdown
|
||||||
|
content += '## Platform Breakdown\n\n';
|
||||||
|
for (const [platform, data] of Object.entries(report.platformBreakdown)) {
|
||||||
|
content += `### ${platform.toUpperCase()}\n`;
|
||||||
|
content += `- Downloads: ${data.totalDownloads.toLocaleString()}\n`;
|
||||||
|
content += `- Packages: ${data.uniquePackages}\n`;
|
||||||
|
content += `- Package List: ${data.packages.join(', ')}\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Top Packages
|
||||||
|
content += '## Top Packages\n\n';
|
||||||
|
report.topPackages.slice(0, 10).forEach((pkg: any, index: number) => {
|
||||||
|
content += `${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads\n`;
|
||||||
|
});
|
||||||
|
content += '\n';
|
||||||
|
|
||||||
|
// Recent Activity
|
||||||
|
content += '## Recent Activity\n\n';
|
||||||
|
report.recentActivity.slice(0, 5).forEach((activity: any) => {
|
||||||
|
content += `- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}\n`;
|
||||||
|
});
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateReadmeWithStats(report: any, readmePath: string) {
|
||||||
|
const STATS_MARKER_START = '<!-- USAGE_STATS_START -->';
|
||||||
|
const STATS_MARKER_END = '<!-- USAGE_STATS_END -->';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const readmeContent = await fs.readFile(readmePath, 'utf-8');
|
||||||
|
|
||||||
|
const statsSection = `
|
||||||
|
## 📊 Usage Statistics
|
||||||
|
|
||||||
|
Last updated: ${new Date().toISOString()}
|
||||||
|
|
||||||
|
### Summary
|
||||||
|
- **Total Downloads**: ${report.totalDownloads.toLocaleString()}
|
||||||
|
- **Unique Packages**: ${report.uniquePackages}
|
||||||
|
- **Platforms Tracked**: ${report.platforms.join(', ')}
|
||||||
|
|
||||||
|
### Top Packages
|
||||||
|
${report.topPackages.slice(0, 10).map((pkg: any, index: number) =>
|
||||||
|
`${index + 1}. **${pkg.name}** (${pkg.platform}) - ${pkg.downloads.toLocaleString()} downloads`
|
||||||
|
).join('\n')}
|
||||||
|
|
||||||
|
### Recent Activity
|
||||||
|
${report.recentActivity.slice(0, 5).map((activity: any) =>
|
||||||
|
`- **${activity.packageName}** (${activity.platform}) - ${activity.downloads.toLocaleString()} downloads on ${activity.timestamp.toLocaleDateString()}`
|
||||||
|
).join('\n')}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const startMarker = readmeContent.indexOf(STATS_MARKER_START);
|
||||||
|
const endMarker = readmeContent.indexOf(STATS_MARKER_END);
|
||||||
|
|
||||||
|
if (startMarker !== -1 && endMarker !== -1) {
|
||||||
|
const beforeStats = readmeContent.substring(0, startMarker + STATS_MARKER_START.length);
|
||||||
|
const afterStats = readmeContent.substring(endMarker);
|
||||||
|
const updatedContent = beforeStats + statsSection + afterStats;
|
||||||
|
await fs.writeFile(readmePath, updatedContent);
|
||||||
|
} else {
|
||||||
|
core.warning(`Stats markers not found in README. Please add ${STATS_MARKER_START} and ${STATS_MARKER_END} markers.`);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to update README: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the action
|
||||||
|
if (import.meta.main) {
|
||||||
|
run();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user