Skip to content

Commit

Permalink
feat: add Docker CI
Browse files Browse the repository at this point in the history
  • Loading branch information
m4tx committed Jan 16, 2024
1 parent 8d10132 commit 196507f
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 6 deletions.
6 changes: 6 additions & 0 deletions src/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ use readme::ReadmeAction;
use rust_ci::RustCiAction;
use rustfmt_toml::RustfmtTomlAction;

use crate::actions::docker::DockerCiAction;
use crate::actions::python::PythonCiAction;
use crate::data::{Repo, Value};

mod dependabot_config;
mod docker;
mod license;
mod pre_commit_config;
mod python;
mod readme;
mod rust_ci;
mod rustfmt_toml;
Expand All @@ -32,6 +36,8 @@ pub fn run_all_actions(action_data: &ActionData) -> ActionResult {
RustfmtTomlAction.run(action_data)?;
DependabotConfigAction.run(action_data)?;
RustCiAction.run(action_data)?;
PythonCiAction.run(action_data)?;
DockerCiAction.run(action_data)?;
ReadmeAction.run(action_data)?;

Ok(())
Expand Down
13 changes: 13 additions & 0 deletions src/actions/docker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::actions::{Action, ActionData, ActionResult};
use crate::template_renderer;

pub struct DockerCiAction;

const DOCKER_CI_FILENAME: &str = ".github/workflows/docker-publish.yml";

impl Action for DockerCiAction {
fn run(&self, data: &ActionData) -> ActionResult {
template_renderer::render_template(DOCKER_CI_FILENAME, data)?;
Ok(())
}
}
13 changes: 13 additions & 0 deletions src/actions/python.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use crate::actions::{Action, ActionData, ActionResult};
use crate::template_renderer;

pub struct PythonCiAction;

const PYTHON_CI_FILENAME: &str = ".github/workflows/python.yml";

impl Action for PythonCiAction {
fn run(&self, data: &ActionData) -> ActionResult {
template_renderer::render_template(PYTHON_CI_FILENAME, data)?;
Ok(())
}
}
1 change: 1 addition & 0 deletions src/context_keys.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub const CRATE_NAME: &str = "crate_name";
pub const DOCKERFILES: &str = "dockerfiles";
pub const FIRST_ACTIVITY_YEAR: &str = "first_activity_year";
pub const FRAMEWORKS: &str = "frameworks";
pub const FULL_NAME: &str = "full_name";
Expand Down
11 changes: 10 additions & 1 deletion src/data.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::collections::BTreeMap;
use std::ops::Index;
use std::ops::{Index, IndexMut};
use std::path::PathBuf;

use serde::de::Visitor;
Expand Down Expand Up @@ -260,6 +260,15 @@ impl Index<&str> for Value {
}
}

impl IndexMut<&str> for Value {
fn index_mut(&mut self, index: &str) -> &mut Self::Output {
match self {
Self::Object(value) => value.get_mut(index).expect("key not found"),
_ => panic!("not an object"),
}
}
}

impl From<Value> for tera::Value {
fn from(value: Value) -> Self {
match value {
Expand Down
52 changes: 49 additions & 3 deletions src/detectors/docker.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,64 @@
use std::collections::BTreeMap;

use thiserror::Error;

use crate::context_keys;
use crate::data::{Repo, Value};
use crate::detectors::{Detector, DetectorResult};

#[derive(Debug, Error)]
pub enum DockerDetectorError {
#[error("failed to read directory")]
ReadDir(#[from] std::io::Error),
}

pub struct DockerDetector;

fn dockerfile_cmp(a: &String, b: &String) -> std::cmp::Ordering {
let a = a.to_lowercase();
let b = b.to_lowercase();
if a == "dockerfile" {
return std::cmp::Ordering::Less;
}
if b == "dockerfile" {
return std::cmp::Ordering::Greater;
}

a.replace(".dockerfile", "")
.cmp(&b.replace(".dockerfile", ""))
}

impl Detector for DockerDetector {
fn detect(&self, repo: &Repo) -> DetectorResult {
let mut data = Value::new_object(BTreeMap::new());
let mut dockerfiles = vec![];
for entry in repo
.path()
.read_dir()
.map_err(DockerDetectorError::ReadDir)?
{
let entry = entry.map_err(DockerDetectorError::ReadDir)?;

let dockerfile = repo.path().join("Dockerfile");
if dockerfile.exists() {
let file_name = entry.file_name();
let file_name_str = file_name.to_string_lossy();
if file_name_str == "Dockerfile" || file_name_str.ends_with(".dockerfile") {
dockerfiles.push(file_name_str.to_string());
}
}
dockerfiles.sort_by(dockerfile_cmp);
println!("dockerfiles: {:?}", dockerfiles);

let mut data = Value::new_object(BTreeMap::new());
if !dockerfiles.is_empty() {
data.insert(context_keys::LANGS, vec![Value::new_string("docker")]);
data.insert(
context_keys::DOCKERFILES,
Value::new_array(
dockerfiles
.iter()
.map(|s| Value::new_string(s))
.collect::<Vec<Value>>(),
),
);
}

Ok(data)
Expand Down
3 changes: 1 addition & 2 deletions src/detectors/license.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ impl Detector for LicenseDetector {

let license = repo.path().join("LICENSE");
if license.exists() {
let license_text =
std::fs::read_to_string(&license).expect("could not read LICENSE.j2");
let license_text = std::fs::read_to_string(&license).expect("could not read LICENSE");

if license_text.contains("MIT License") {
data.insert(context_keys::LICENSE, "MIT");
Expand Down
2 changes: 2 additions & 0 deletions src/template_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub static TERA: Lazy<Tera> = Lazy::new(|| {
template!("LICENSE.j2"),
template!("rustfmt.toml.j2"),
template!(".github/dependabot.yml.j2"),
template!(".github/workflows/docker-publish.yml.j2"),
template!(".github/workflows/python.yml.j2"),
template!(".github/workflows/rust.yml.j2"),
template!("README.header.md.j2"),
])
Expand Down
48 changes: 48 additions & 0 deletions src/templates/.github/workflows/docker-publish.yml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Docker

on:
push:
pull_request:

env:
REGISTRY: ghcr.io

jobs:
{%- for dockerfile in boiler.dockerfiles %}
build-and-push{% if dockerfile != 'Dockerfile' %}-{{ dockerfile | replace(from=".dockerfile", to="") }}{% endif %}:
{%- raw %}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
if: github.ref == 'refs/heads/master'
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}{% endraw %}/{{ boiler.repo_owner }}/{% if dockerfile == 'Dockerfile' %}{{ boiler.repo_name }}{% else %}{{ dockerfile | replace(from=".dockerfile", to="") }}{% endif %}{% raw %}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
{%- endraw %}
file: {{ dockerfile }}
{%- raw %}
push: ${{ github.ref == 'refs/heads/master' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
{%- endraw %}
{% endfor -%}

0 comments on commit 196507f

Please sign in to comment.