1 Commits

Author SHA1 Message Date
55bf725491 Add GitHub Actions workflows and optimize build performance
- Add release.yml for multi-platform binary builds (Linux, macOS, Windows)
- Add gh-pages-fast.yml for fast deployment using pre-built binaries
- Add build-binary.yml for standalone binary artifact creation
- Optimize Cargo.toml with build profiles and reduced tokio features
- Remove 26MB of unused Font Awesome assets (kept only essential files)
- Font Awesome reduced from 28MB to 1.2MB

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-14 16:12:05 +09:00
14 changed files with 181 additions and 261 deletions

View File

@@ -42,11 +42,7 @@
"WebFetch(domain:syui.ai)",
"Bash(rustup target list:*)",
"Bash(rustup target:*)",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)",
"Bash(git tag:*)",
"Bash(../bin/ailog:*)"
"Bash(git add:*)"
],
"deny": []
}

51
.github/workflows/build-binary.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: Build Binary
on:
workflow_dispatch: # Manual trigger
push:
branches: [ main ]
paths:
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache target directory
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
- name: Build binary
run: cargo build --release
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: ailog-linux
path: target/release/ailog
retention-days: 30

View File

@@ -34,67 +34,22 @@ jobs:
- name: Copy OAuth build to static
run: |
# Remove old assets (following run.zsh pattern)
rm -rf my-blog/static/assets
# Copy all dist files to static
cp -rf oauth/dist/* my-blog/static/
# Copy index.html to oauth-assets.html template
cp oauth/dist/index.html my-blog/templates/oauth-assets.html
mkdir -p my-blog/static/assets
cp -r oauth/dist/assets/* my-blog/static/assets/
cp oauth/dist/index.html my-blog/static/oauth/index.html || true
- name: Cache ailog binary
uses: actions/cache@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
path: ./bin
key: ailog-bin-${{ runner.os }}
restore-keys: |
ailog-bin-${{ runner.os }}
- name: Setup ailog binary
run: |
# Get expected version from Cargo.toml
EXPECTED_VERSION=$(grep '^version' Cargo.toml | cut -d'"' -f2)
echo "Expected version from Cargo.toml: $EXPECTED_VERSION"
# Check current binary version if exists
if [ -f "./bin/ailog" ]; then
CURRENT_VERSION=$(./bin/ailog --version 2>/dev/null || echo "unknown")
echo "Current binary version: $CURRENT_VERSION"
else
CURRENT_VERSION="none"
echo "No binary found"
fi
# Check OS
OS="${{ runner.os }}"
echo "Runner OS: $OS"
# Use pre-packaged binary if version matches or extract from tar.gz
if [ "$CURRENT_VERSION" = "$EXPECTED_VERSION" ]; then
echo "Binary is up to date"
chmod +x ./bin/ailog
elif [ "$OS" = "Linux" ] && [ -f "./bin/ailog-linux-x86_64.tar.gz" ]; then
echo "Extracting ailog from pre-packaged tar.gz..."
cd bin
tar -xzf ailog-linux-x86_64.tar.gz
chmod +x ailog
cd ..
# Verify extracted version
EXTRACTED_VERSION=$(./bin/ailog --version 2>/dev/null || echo "unknown")
echo "Extracted binary version: $EXTRACTED_VERSION"
if [ "$EXTRACTED_VERSION" != "$EXPECTED_VERSION" ]; then
echo "Warning: Binary version mismatch. Expected $EXPECTED_VERSION but got $EXTRACTED_VERSION"
fi
else
echo "Error: No suitable binary found for OS: $OS"
exit 1
fi
toolchain: stable
- name: Build ailog
run: cargo build --release
- name: Build site with ailog
run: |
cd my-blog
../bin/ailog build
../target/release/ailog build
- name: List public directory
run: |

View File

@@ -1,92 +0,0 @@
name: github pages (fast)
on:
push:
branches:
- main
paths-ignore:
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
jobs:
build-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
pages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Cache ailog binary
uses: actions/cache@v4
with:
path: ./bin
key: ailog-bin-${{ runner.os }}
restore-keys: |
ailog-bin-${{ runner.os }}
- name: Setup ailog binary
run: |
# Get expected version from Cargo.toml
EXPECTED_VERSION=$(grep '^version' Cargo.toml | cut -d'"' -f2)
echo "Expected version from Cargo.toml: $EXPECTED_VERSION"
# Check current binary version if exists
if [ -f "./bin/ailog" ]; then
CURRENT_VERSION=$(./bin/ailog --version 2>/dev/null || echo "unknown")
echo "Current binary version: $CURRENT_VERSION"
else
CURRENT_VERSION="none"
echo "No binary found"
fi
# Check OS
OS="${{ runner.os }}"
echo "Runner OS: $OS"
# Use pre-packaged binary if version matches or extract from tar.gz
if [ "$CURRENT_VERSION" = "$EXPECTED_VERSION" ]; then
echo "Binary is up to date"
chmod +x ./bin/ailog
elif [ "$OS" = "Linux" ] && [ -f "./bin/ailog-linux-x86_64.tar.gz" ]; then
echo "Extracting ailog from pre-packaged tar.gz..."
cd bin
tar -xzf ailog-linux-x86_64.tar.gz
chmod +x ailog
cd ..
# Verify extracted version
EXTRACTED_VERSION=$(./bin/ailog --version 2>/dev/null || echo "unknown")
echo "Extracted binary version: $EXTRACTED_VERSION"
if [ "$EXTRACTED_VERSION" != "$EXPECTED_VERSION" ]; then
echo "Warning: Binary version mismatch. Expected $EXPECTED_VERSION but got $EXTRACTED_VERSION"
fi
else
echo "Error: No suitable binary found for OS: $OS"
exit 1
fi
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: "0.139.2"
extended: true
- name: Build with ailog
env:
TZ: "Asia/Tokyo"
run: |
# Use pre-built ailog binary instead of cargo build
cd my-blog
../bin/ailog build
touch ./public/.nojekyll
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./my-blog/public
publish_branch: gh-pages

50
.github/workflows/gh-pages-fast.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: github pages (fast)
on:
push:
branches:
- main
paths-ignore:
- 'src/**'
- 'Cargo.toml'
- 'Cargo.lock'
jobs:
build-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get latest release
id: latest_release
run: |
LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r .tag_name)
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
- name: Download pre-built binary from release
run: |
curl -sL https://github.com/${{ github.repository }}/releases/download/${{ steps.latest_release.outputs.tag }}/ailog-linux-x86_64.tar.gz | tar -xzf -
chmod +x ailog
mkdir -p ./bin
mv ailog ./bin/
- name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: "0.139.2"
extended: true
- name: Build with ailog
env:
TZ: "Asia/Tokyo"
run: |
# Use pre-built ailog binary instead of cargo build
./bin/ailog build --output ./public
touch ./public/.nojekyll
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./public
publish_branch: gh-pages

View File

@@ -11,20 +11,13 @@ on:
required: true
default: 'v0.1.0'
permissions:
contents: write
actions: read
env:
CARGO_TERM_COLOR: always
OPENSSL_STATIC: true
OPENSSL_VENDOR: true
jobs:
build:
name: Build ${{ matrix.target }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy:
matrix:
include:
@@ -32,6 +25,10 @@ jobs:
os: ubuntu-latest
artifact_name: ailog
asset_name: ailog-linux-x86_64
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
artifact_name: ailog
asset_name: ailog-linux-x86_64-musl
- target: aarch64-unknown-linux-gnu
os: ubuntu-latest
artifact_name: ailog
@@ -44,6 +41,10 @@ jobs:
os: macos-latest
artifact_name: ailog
asset_name: ailog-macos-aarch64
- target: x86_64-pc-windows-msvc
os: windows-latest
artifact_name: ailog.exe
asset_name: ailog-windows-x86_64.exe
steps:
- uses: actions/checkout@v4
@@ -54,10 +55,16 @@ jobs:
targets: ${{ matrix.target }}
- name: Install cross-compilation tools (Linux)
if: matrix.os == 'ubuntu-latest' && matrix.target == 'aarch64-unknown-linux-gnu'
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu
sudo apt-get install -y gcc-multilib
if [[ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]]; then
sudo apt-get install -y gcc-aarch64-linux-gnu
fi
if [[ "${{ matrix.target }}" == "x86_64-unknown-linux-musl" ]]; then
sudo apt-get install -y musl-tools
fi
- name: Configure cross-compilation (Linux ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
@@ -86,17 +93,11 @@ jobs:
shell: bash
run: |
cd target/${{ matrix.target }}/release
# Use appropriate strip command for cross-compilation
if [[ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]]; then
aarch64-linux-gnu-strip ${{ matrix.artifact_name }} || echo "Strip failed, continuing..."
elif [[ "${{ matrix.os }}" == "windows-latest" ]]; then
strip ${{ matrix.artifact_name }} || echo "Strip failed, continuing..."
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
strip ${{ matrix.artifact_name }} || true
else
strip ${{ matrix.artifact_name }} || echo "Strip failed, continuing..."
strip ${{ matrix.artifact_name }}
fi
# Create archive
if [[ "${{ matrix.target }}" == *"windows"* ]]; then
7z a ../../../${{ matrix.asset_name }}.zip ${{ matrix.artifact_name }}
else
@@ -107,15 +108,14 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset_name }}
path: ${{ matrix.asset_name }}.tar.gz
path: |
${{ matrix.asset_name }}.tar.gz
${{ matrix.asset_name }}.zip
release:
name: Create Release
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
actions: read
steps:
- uses: actions/checkout@v4
@@ -135,8 +135,9 @@ jobs:
echo "- AI comment system" >> release_notes.md
echo "" >> release_notes.md
echo "### Platforms" >> release_notes.md
echo "- Linux (x86_64, aarch64)" >> release_notes.md
echo "- Linux (x86_64, aarch64, musl)" >> release_notes.md
echo "- macOS (Intel, Apple Silicon)" >> release_notes.md
echo "- Windows (x86_64)" >> release_notes.md
echo "" >> release_notes.md
echo "### Installation" >> release_notes.md
echo "\`\`\`bash" >> release_notes.md
@@ -145,6 +146,8 @@ jobs:
echo "chmod +x ailog" >> release_notes.md
echo "sudo mv ailog /usr/local/bin/" >> release_notes.md
echo "" >> release_notes.md
echo "# Windows" >> release_notes.md
echo "# Extract ailog-windows-x86_64.zip and add to PATH" >> release_notes.md
echo "\`\`\`" >> release_notes.md
- name: Get tag name
@@ -164,6 +167,8 @@ jobs:
body_path: release_notes.md
draft: false
prerelease: ${{ contains(steps.tag_name.outputs.tag, 'alpha') || contains(steps.tag_name.outputs.tag, 'beta') || contains(steps.tag_name.outputs.tag, 'rc') }}
files: artifacts/*/ailog-*.tar.gz
files: |
artifacts/*/ailog-*.tar.gz
artifacts/*/ailog-*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

1
.gitignore vendored
View File

@@ -11,4 +11,3 @@ dist
node_modules
package-lock.json
my-blog/static/assets/comment-atproto-*
bin/ailog

View File

@@ -1,6 +1,6 @@
[package]
name = "ailog"
version = "0.1.4"
version = "0.1.0"
edition = "2021"
authors = ["syui"]
description = "A static blog generator with AI features"
@@ -26,7 +26,7 @@ fs_extra = "1.3"
colored = "2.1"
serde_yaml = "0.9"
syntect = "5.2"
reqwest = { version = "0.12", features = ["json", "rustls-tls"], default-features = false }
reqwest = { version = "0.12", features = ["json"] }
rand = "0.8"
sha2 = "0.10"
base64 = "0.22"
@@ -43,12 +43,12 @@ cookie = "0.18"
syn = { version = "2.0", features = ["full", "parsing", "visit"] }
quote = "1.0"
ignore = "0.4"
git2 = { version = "0.18", features = ["vendored-openssl", "vendored-libgit2", "ssh"], default-features = false }
git2 = "0.18"
regex = "1.0"
# ATProto and stream monitoring dependencies
tokio-tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots", "connect"], default-features = false }
tokio-tungstenite = { version = "0.21", features = ["native-tls"] }
futures-util = "0.3"
tungstenite = { version = "0.21", features = ["rustls-tls-webpki-roots"], default-features = false }
tungstenite = { version = "0.21", features = ["native-tls"] }
[dev-dependencies]
tempfile = "3.14"

View File

@@ -47,34 +47,17 @@ outputs:
runs:
using: 'composite'
steps:
- name: Cache ailog binary
uses: actions/cache@v4
- name: Setup Rust
uses: actions-rs/toolchain@v1
with:
path: ./bin
key: ailog-bin-${{ runner.os }}
restore-keys: |
ailog-bin-${{ runner.os }}
- name: Setup ailog binary
toolchain: stable
override: true
- name: Install ailog
shell: bash
run: |
# Check if pre-built binary exists
if [ -f "./bin/ailog-linux-x86_64" ]; then
echo "Using pre-built binary from repository"
chmod +x ./bin/ailog-linux-x86_64
CURRENT_VERSION=$(./bin/ailog-linux-x86_64 --version 2>/dev/null || echo "unknown")
echo "Binary version: $CURRENT_VERSION"
else
echo "No pre-built binary found, trying to build from source..."
if command -v cargo >/dev/null 2>&1; then
cargo build --release
mkdir -p ./bin
cp ./target/release/ailog ./bin/ailog-linux-x86_64
echo "Built from source: $(./bin/ailog-linux-x86_64 --version 2>/dev/null)"
else
echo "Error: No binary found and cargo not available"
exit 1
fi
if [ ! -f "./target/release/ailog" ]; then
cargo build --release
fi
- name: Setup Node.js for OAuth app
@@ -100,15 +83,12 @@ runs:
run: |
start_time=$(date +%s)
# Change to blog directory and run build
# Note: ailog build only takes a path argument, not options
if [ -d "my-blog" ]; then
cd my-blog
../bin/ailog-linux-x86_64 build
else
# If no my-blog directory, use current directory
./bin/ailog-linux-x86_64 build .
fi
./target/release/ailog generate \
--input ${{ inputs.content-dir }} \
--output ${{ inputs.output-dir }} \
--templates ${{ inputs.template-dir }} \
--static ${{ inputs.static-dir }} \
--config ${{ inputs.config-file }}
end_time=$(date +%s)
build_time=$((end_time - start_time))

Binary file not shown.

View File

@@ -1,5 +1,8 @@
# Ask-AI機能をOllamaにプロキシ
/api/ask https://ollama.syui.ai/api/generate 200
# AI機能をai.gpt MCP serverにリダイレクト
/api/ask https://ai-gpt-mcp.syui.ai/ask 200
# Ollama API proxy (Cloudflare Workers)
/api/ollama-proxy https://ollama-proxy.YOUR-SUBDOMAIN.workers.dev/:splat 200
# OAuth routes
/oauth/* /oauth/index.html 200

View File

@@ -517,21 +517,25 @@ a.view-markdown:any-link {
margin: 16px 0;
font-size: 14px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
position: relative;
}
/* File name display for code blocks - top bar style */
/* File name display for code blocks */
.article-body pre[data-filename]::before {
content: attr(data-filename);
display: block;
position: absolute;
top: 0;
right: 0;
background: #2D2D30;
color: #AE81FF;
padding: 8px 16px;
color: #CCCCCC;
padding: 4px 12px;
font-size: 12px;
font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
border-bottom: 1px solid #3E3D32;
margin: 0;
width: 100%;
box-sizing: border-box;
border-bottom-left-radius: 4px;
border: 1px solid #3E3D32;
border-top: none;
border-right: none;
z-index: 1;
}
.article-body pre code {
@@ -544,11 +548,6 @@ a.view-markdown:any-link {
line-height: 1.4;
}
/* Adjust padding when filename is present */
.article-body pre[data-filename] code {
padding: 16px;
}
/* Inline code (not in pre blocks) */
.article-body code {
background: var(--light-white);
@@ -854,16 +853,6 @@ a.view-markdown:any-link {
white-space: pre-wrap;
}
/* Mobile filename display */
.article-body pre[data-filename]::before {
padding: 6px 12px;
font-size: 11px;
}
.article-body pre[data-filename] code {
padding: 12px;
}
.article-body code {
word-break: break-all;
}

View File

@@ -15,6 +15,7 @@
<link rel="stylesheet" href="/pkg/icomoon/style.css">
<link rel="stylesheet" href="/pkg/font-awesome/css/all.min.css">
{% include "oauth-assets.html" %}
{% block head %}{% endblock %}
</head>
<body>
@@ -91,7 +92,5 @@
<script src="/js/ask-ai.js"></script>
<script src="/js/theme.js"></script>
{% include "oauth-assets.html" %}
</body>
</html>

View File

@@ -18,14 +18,10 @@ mod mcp;
#[derive(Parser)]
#[command(name = "ailog")]
#[command(about = "A static blog generator with AI features")]
#[command(disable_version_flag = true)]
#[command(version)]
struct Cli {
/// Print version information
#[arg(short = 'V', long = "version")]
version: bool,
#[command(subcommand)]
command: Option<Commands>,
command: Commands,
}
#[derive(Subcommand)]
@@ -139,19 +135,8 @@ enum OauthCommands {
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
// Handle version flag
if cli.version {
println!("{}", env!("CARGO_PKG_VERSION"));
return Ok(());
}
// Require subcommand if no version flag
let command = cli.command.ok_or_else(|| {
anyhow::anyhow!("No subcommand provided. Use --help for usage information.")
})?;
match command {
match cli.command {
Commands::Init { path } => {
commands::init::execute(path).await?;
}