oxidizer #67
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: oxidizer | |
| on: | |
| schedule: | |
| - cron: '0 0 * * *' # 北京时间早上 8 点 (UTC+8) | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| oxidize: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check if ready to oxidize | |
| run: | | |
| METAL="self/metal.metal" | |
| # Check if metal.metal exists and is not empty | |
| if [ ! -f "$METAL" ] || [ ! -s "$METAL" ]; then | |
| echo "metal.metal doesn't exist or is empty. Skipping oxidation." | |
| exit 0 | |
| fi | |
| # Check if first character is # | |
| FIRST_CHAR=$(head -c 1 "$METAL") | |
| if [ "$FIRST_CHAR" != "#" ]; then | |
| echo "First character is not #. Skipping oxidation." | |
| exit 0 | |
| fi | |
| echo "Ready to oxidize." | |
| - name: Oxidize self files | |
| run: | | |
| METAL="self/metal.metal" | |
| RUST="self/rust.rs" | |
| REMAINING=$(wc -l < "$METAL" | tr -d ' ') | |
| if [ "$REMAINING" -eq 0 ]; then | |
| echo "✓ Fully oxidized. Process complete." | |
| exit 0 | |
| fi | |
| # Remove last line from metal, append to rust | |
| head -n -1 "$METAL" > "$METAL.tmp" && mv "$METAL.tmp" "$METAL" | |
| echo '#' >> "$RUST" | |
| - name: Update README | |
| run: | | |
| METAL="self/metal.metal" | |
| RUST="self/rust.rs" | |
| # Calculate counts AFTER oxidation | |
| METAL_LINES=$(wc -l < "$METAL" | tr -d ' ') | |
| RUST_LINES=$(wc -l < "$RUST" | tr -d ' ') | |
| TOTAL=$((METAL_LINES + RUST_LINES)) | |
| # Handle edge case when TOTAL is 0 | |
| if [ "$TOTAL" -eq 0 ]; then | |
| echo "No lines to process" | |
| exit 0 | |
| fi | |
| PCT=$(awk "BEGIN {printf \"%.1f\", ($RUST_LINES/$TOTAL)*100}") | |
| # Update language composition bar (80 chars total) | |
| FILLED=$(awk "BEGIN {printf \"%.0f\", ($RUST_LINES/$TOTAL)*80}") | |
| EMPTY=$((80 - FILLED)) | |
| # 安全拼接进度条,避免 printf 空参数 Bug | |
| BAR="" | |
| if [ "$EMPTY" -gt 0 ]; then BAR="${BAR}$(printf '█%.0s' $(seq 1 $EMPTY))"; fi | |
| if [ "$FILLED" -gt 0 ]; then BAR="${BAR}$(printf '░%.0s' $(seq 1 $FILLED))"; fi | |
| METAL_PCT=$(awk "BEGIN {printf \"%.1f\", ($METAL_LINES/$TOTAL)*100}") | |
| RUST_PCT="${PCT}" | |
| # 精确计算左右两端字符串,并动态填充空格保证总长度为 80 | |
| LEFT_STR="Metal: ${METAL_PCT}%" | |
| RIGHT_STR="Rust: ${RUST_PCT}%" | |
| SPACES=$((80 - ${#LEFT_STR} - ${#RIGHT_STR})) | |
| LABEL_LINE=$(printf "%s%*s%s" "$LEFT_STR" "$SPACES" "" "$RIGHT_STR") | |
| # Update Status section in README using awk for precise targeting | |
| # First pass: extract date information | |
| DATES=$(awk ' | |
| /^### Status/ { in_status=1; next } | |
| /^```/ && in_status == 1 { in_status=2; next } | |
| /^```/ && in_status == 2 { in_status=0; next } | |
| in_status == 2 && /^(Deployed|Duration|Ends):/ { print; } | |
| ' README.md) | |
| # Second pass: update the status block | |
| awk -v bar="${BAR}" -v label="${LABEL_LINE}" -v dates="${DATES}" ' | |
| /^### Status/ { in_status=1; print; next } | |
| /^```/ && in_status == 1 { | |
| in_status=2 | |
| next | |
| } | |
| /^```/ && in_status == 2 { | |
| print bar | |
| print label | |
| if (dates != "") { | |
| print "" | |
| print dates | |
| } | |
| in_status=0 | |
| next | |
| } | |
| in_status == 2 { | |
| # Skip old content inside code block | |
| next | |
| } | |
| { print } | |
| ' README.md > README.md.tmp && mv README.md.tmp README.md | |
| echo "Oxidation progress: ${PCT}% (${RUST_LINES}/${TOTAL} days)" | |
| - name: Commit | |
| run: | | |
| git config user.name "oxidizer-bot[bot]" | |
| git config user.email "oxidizer-bot[bot]@users.noreply.github.com" | |
| git add self/ README.md | |
| git diff --cached --quiet && exit 0 | |
| git commit -m "oxidize: another day passes" | |
| git push |