use std::fmt::Write as _;
use super::Edits;
use crate::{
CliResult,
ci::{I18N_STEP, STEPS},
project::Project,
};
pub const WORKFLOW: &str = ".github/workflows/ci.yml";
const INSTALL_OCRE: &str = "cargo install --git https://github.com/tgeselle/ocre.rs ocre-cli";
const HEADER: &str = r#"# CI for this Ocre app. Generated by `ocre g ci`; `ocre ci` runs the same
# checks locally, in the same order.
#
# The deploy job needs two repository secrets (Settings > Secrets and
# variables > Actions):
# CLOUDFLARE_API_TOKEN an API token (My Profile > API Tokens) with Account
# permissions "Workers Scripts: Edit", "D1: Edit", and
# when the app uses them "Queues: Edit", "Workers KV
# Storage: Edit", "Workers R2 Storage: Edit"; plus
# "Zone: Workers Routes: Edit" for custom domains.
# CLOUDFLARE_ACCOUNT_ID the account id (Workers & Pages overview), needed
# when the token can see several accounts.
# Commit package-lock.json (`npm ci` installs the pinned cf and wrangler) and
# the KV ids the first `ocre deploy` writes into cloudflare.config.ts.
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# rust-toolchain.toml adds the wasm32-unknown-unknown target.
- run: rustup component add rustfmt clippy
- uses: Swatinem/rust-cache@v2
"#;
pub fn ci(project: &Project) -> CliResult {
let mut workflow = HEADER.to_owned();
for (step, _) in STEPS {
writeln!(workflow, " - run: {step}").expect("writing to a String");
}
write!(
workflow,
r#" # Translations: every key of the default locale in every locale.
- if: hashFiles('locales/*.yml') != ''
run: {INSTALL_OCRE} && {I18N_STEP}
deploy:
needs: check
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
# One deploy at a time; a newer push waits for the running one.
concurrency: deploy
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- uses: Swatinem/rust-cache@v2
- run: npm ci
- run: {INSTALL_OCRE}
# Builds the Worker, creates missing resources, applies remote migrations.
- run: ocre deploy --json
env:
CLOUDFLARE_API_TOKEN: ${{{{ secrets.CLOUDFLARE_API_TOKEN }}}}
CLOUDFLARE_ACCOUNT_ID: ${{{{ secrets.CLOUDFLARE_ACCOUNT_ID }}}}
CF_SEND_TELEMETRY: "false"
"#
)
.expect("writing to a String");
let mut edits = Edits::new(project);
edits.create(WORKFLOW, workflow)?;
let mut report = edits.apply("generate ci")?;
report.next = vec![
"add the repository secrets CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID (see the comment at the top of the workflow)"
.to_owned(),
"ocre ci (the same checks, locally)".to_owned(),
"git add .github package-lock.json && git commit, then push to main".to_owned(),
];
Ok(report)
}