From 6f244a0a5f8a3c0dfe7762e2e02eb4fec4a7fbfa Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 18:43:58 -0500 Subject: [PATCH 01/10] Add pipeline for running the rust tests. --- .lighthouse/pipeline-rust-test.yaml | 188 ++++++++++++++++++++++++++++ .lighthouse/triggers.yaml | 7 ++ 2 files changed, 195 insertions(+) create mode 100644 .lighthouse/pipeline-rust-test.yaml diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml new file mode 100644 index 0000000..ffc5881 --- /dev/null +++ b/.lighthouse/pipeline-rust-test.yaml @@ -0,0 +1,188 @@ +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: rust-test +spec: + pipelineSpec: + timeouts: + pipeline: "2h0m0s" + tasks: "1h0m40s" + finally: "0h30m0s" + params: + - name: image-name + description: The name for the built image + type: string + - name: path-to-image-context + description: The path to the build context + type: string + - name: path-to-dockerfile + description: The path to the Dockerfile + type: string + tasks: + - name: report-pending + taskRef: + name: gitea-set-status + runAfter: + - fetch-repository + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has started" + - name: STATE + value: pending + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: fetch-repository + taskRef: + name: git-clone + workspaces: + - name: output + workspace: git-source + params: + - name: url + value: $(params.REPO_URL) + - name: revision + value: $(params.PULL_BASE_SHA) + - name: deleteExisting + value: "true" + - name: build-image + taskRef: + name: kaniko + params: + - name: IMAGE + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + - name: CONTEXT + value: $(params.path-to-image-context) + - name: DOCKERFILE + value: $(params.path-to-dockerfile) + - name: BUILDER_IMAGE + value: "gcr.io/kaniko-project/executor:v1.12.1" + - name: EXTRA_ARGS + value: + - --target=tester + - --cache=true + - --cache-copy-layers + - --cache-repo=harbor.fizz.buzz/kanikocache/cache + - --use-new-run # Should result in a speed-up + - --reproducible # To remove timestamps so layer caching works. + - --snapshot-mode=redo + - --skip-unused-stages=true + - --registry-mirror=dockerhub.dockerhub.svc.cluster.local + workspaces: + - name: source + workspace: git-source + - name: dockerconfig + workspace: docker-credentials + runAfter: + - fetch-repository + - name: run-image + taskRef: + name: run-docker-image + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + runAfter: + - build-image + params: + - name: command + value: [cargo, test, --no-fail-fast] + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + finally: + - name: report-success + when: + - input: "$(tasks.status)" + operator: in + values: ["Succeeded", "Completed"] + taskRef: + name: gitea-set-status + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has succeeded" + - name: STATE + value: success + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: report-failure + when: + - input: "$(tasks.status)" + operator: in + values: ["Failed"] + taskRef: + name: gitea-set-status + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has failed" + - name: STATE + value: failure + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: cargo-cache-autoclean + taskRef: + name: run-docker-image + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + params: + - name: command + value: [cargo, cache, --autoclean] + - name: args + value: [] + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + workspaces: + - name: git-source + - name: docker-credentials + - name: cargo-cache + workspaces: + - name: git-source + volumeClaimTemplate: + spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + subPath: rust-source + - name: cargo-cache + persistentVolumeClaim: + claimName: natter-cargo-cache-test + - name: docker-credentials + secret: + secretName: harbor-plain + serviceAccountName: build-bot + params: + - name: image-name + value: "harbor.fizz.buzz/private/natter-development" + - name: path-to-image-context + value: docker/natter_development/ + - name: path-to-dockerfile + value: docker/natter_development/Dockerfile diff --git a/.lighthouse/triggers.yaml b/.lighthouse/triggers.yaml index 0af244d..180fa7b 100644 --- a/.lighthouse/triggers.yaml +++ b/.lighthouse/triggers.yaml @@ -9,3 +9,10 @@ spec: branches: - ^main$ - ^master$ + - name: rust-test + source: "pipeline-rust-test.yaml" + # Override https-based url from lighthouse events. + clone_uri: "git@code.fizz.buzz:talexander/natter.git" + skip_branches: + # We already run on every commit, so running when the semver tags get pushed is causing needless double-processing. + - "^v[0-9]+\\.[0-9]+\\.[0-9]+$" From 457ff9e759def49edeccef0e1d5f46aca786a14a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 18:56:21 -0500 Subject: [PATCH 02/10] Add dockerfile for running rust tests. --- .lighthouse/pipeline-rust-test.yaml | 1 - docker/natter_development/Dockerfile | 4 ++++ docker/natter_development/Makefile | 32 ++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 docker/natter_development/Dockerfile create mode 100644 docker/natter_development/Makefile diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml index ffc5881..7959062 100644 --- a/.lighthouse/pipeline-rust-test.yaml +++ b/.lighthouse/pipeline-rust-test.yaml @@ -66,7 +66,6 @@ spec: value: "gcr.io/kaniko-project/executor:v1.12.1" - name: EXTRA_ARGS value: - - --target=tester - --cache=true - --cache-copy-layers - --cache-repo=harbor.fizz.buzz/kanikocache/cache diff --git a/docker/natter_development/Dockerfile b/docker/natter_development/Dockerfile new file mode 100644 index 0000000..38f2de1 --- /dev/null +++ b/docker/natter_development/Dockerfile @@ -0,0 +1,4 @@ +FROM rustlang/rust:nightly-alpine3.17 AS builder + +RUN apk add --no-cache musl-dev +RUN cargo install --locked --no-default-features --features ci-autoclean cargo-cache diff --git a/docker/natter_development/Makefile b/docker/natter_development/Makefile new file mode 100644 index 0000000..c6fce8f --- /dev/null +++ b/docker/natter_development/Makefile @@ -0,0 +1,32 @@ +SHELL := bash +.ONESHELL: +.SHELLFLAGS := -eu -o pipefail -c +.DELETE_ON_ERROR: +MAKEFLAGS += --warn-undefined-variables +MAKEFLAGS += --no-builtin-rules +OS:=$(shell uname -s) + +ifeq ($(origin .RECIPEPREFIX), undefined) + $(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later) +endif +.RECIPEPREFIX = > + +IMAGE_NAME:=natter-development +TARGET := + +.PHONY: help +help: +> @grep -h "##" $(MAKEFILE_LIST) | grep -v grep | sed -E 's/^([^:]*): *## */\1: /' + +.PHONY: build +build: ## Build the docker image. +> docker build --tag $(IMAGE_NAME) --target=$(TARGET) --file Dockerfile . + +.PHONY: shell +shell: ## Launch an interactive shell inside the docker image with the source repository mounted at /source. +shell: build +> docker run --rm -i -t --entrypoint /bin/sh --mount type=tmpfs,destination=/tmp -v "$$(readlink -f ../../):/source" --workdir=/source $(IMAGE_NAME) + +.PHONY: clean +clean: +> docker rmi $(IMAGE_NAME) From 4447f1ed4acc46a4e2b15bfe205f7c4306a851c9 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 19:18:30 -0500 Subject: [PATCH 03/10] Inline the test pipeline. --- .lighthouse/pipeline-rust-test.yaml | 33 ++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml index 7959062..2d47307 100644 --- a/.lighthouse/pipeline-rust-test.yaml +++ b/.lighthouse/pipeline-rust-test.yaml @@ -81,9 +81,34 @@ spec: workspace: docker-credentials runAfter: - fetch-repository - - name: run-image - taskRef: - name: run-docker-image + - name: run-cargo-test + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: [cargo, test, --no-fail-fast] + args: [] workspaces: - name: source workspace: git-source @@ -92,8 +117,6 @@ spec: runAfter: - build-image params: - - name: command - value: [cargo, test, --no-fail-fast] - name: docker-image value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" finally: From 134444b2c35aed397d3b9af00a95e74942b2ab0d Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 19:30:53 -0500 Subject: [PATCH 04/10] Set cargo target dir. This is to avoid writing to the target dir in the repo folder. --- .lighthouse/pipeline-rust-test.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml index 2d47307..8989125 100644 --- a/.lighthouse/pipeline-rust-test.yaml +++ b/.lighthouse/pipeline-rust-test.yaml @@ -109,6 +109,9 @@ spec: workingDir: "$(workspaces.source.path)" command: [cargo, test, --no-fail-fast] args: [] + env: + - name: CARGO_TARGET_DIR + value: /target workspaces: - name: source workspace: git-source From bcb6b2d75fa93d100a85ac8ae5db2a474559a67a Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 19:45:32 -0500 Subject: [PATCH 05/10] Inline the cargo cache autoclean step. --- .lighthouse/pipeline-rust-test.yaml | 33 +++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml index 8989125..b38bffc 100644 --- a/.lighthouse/pipeline-rust-test.yaml +++ b/.lighthouse/pipeline-rust-test.yaml @@ -168,18 +168,39 @@ spec: - name: TARGET_URL value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" - name: cargo-cache-autoclean - taskRef: - name: run-docker-image + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: [cargo, cache, --autoclean] + args: [] workspaces: - name: source workspace: git-source - name: cargo-cache workspace: cargo-cache params: - - name: command - value: [cargo, cache, --autoclean] - - name: args - value: [] - name: docker-image value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" workspaces: From 48af194da0188b17b9aa9b7cab96f95582ee5091 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 19:56:20 -0500 Subject: [PATCH 06/10] Use a resolver to remove dependency on installed catalog tasks. --- .lighthouse/pipeline-rust-test.yaml | 45 +++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/.lighthouse/pipeline-rust-test.yaml b/.lighthouse/pipeline-rust-test.yaml index b38bffc..7bbc64f 100644 --- a/.lighthouse/pipeline-rust-test.yaml +++ b/.lighthouse/pipeline-rust-test.yaml @@ -21,7 +21,14 @@ spec: tasks: - name: report-pending taskRef: - name: gitea-set-status + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml runAfter: - fetch-repository params: @@ -41,7 +48,14 @@ spec: value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" - name: fetch-repository taskRef: - name: git-clone + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/git-clone/0.9/git-clone.yaml workspaces: - name: output workspace: git-source @@ -54,7 +68,14 @@ spec: value: "true" - name: build-image taskRef: - name: kaniko + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/kaniko/0.6//kaniko.yaml params: - name: IMAGE value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" @@ -129,7 +150,14 @@ spec: operator: in values: ["Succeeded", "Completed"] taskRef: - name: gitea-set-status + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml params: - name: CONTEXT value: "$(params.JOB_NAME)" @@ -151,7 +179,14 @@ spec: operator: in values: ["Failed"] taskRef: - name: gitea-set-status + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml params: - name: CONTEXT value: "$(params.JOB_NAME)" From 904f834c86969c450e40f8d1d30212595ecf1938 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 20:08:24 -0500 Subject: [PATCH 07/10] Add CI job to run clippy. --- .lighthouse/pipeline-rust-clippy.yaml | 279 ++++++++++++++++++++++++++ .lighthouse/triggers.yaml | 7 + 2 files changed, 286 insertions(+) create mode 100644 .lighthouse/pipeline-rust-clippy.yaml diff --git a/.lighthouse/pipeline-rust-clippy.yaml b/.lighthouse/pipeline-rust-clippy.yaml new file mode 100644 index 0000000..731f07e --- /dev/null +++ b/.lighthouse/pipeline-rust-clippy.yaml @@ -0,0 +1,279 @@ +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: rust-clippy +spec: + pipelineSpec: + timeouts: + pipeline: "2h0m0s" + tasks: "1h0m40s" + finally: "0h30m0s" + params: + - name: image-name + description: The name for the built image + type: string + - name: path-to-image-context + description: The path to the build context + type: string + - name: path-to-dockerfile + description: The path to the Dockerfile + type: string + tasks: + - name: report-pending + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + runAfter: + - fetch-repository + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has started" + - name: STATE + value: pending + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: fetch-repository + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/git-clone/0.9/git-clone.yaml + workspaces: + - name: output + workspace: git-source + params: + - name: url + value: $(params.REPO_URL) + - name: revision + value: $(params.PULL_BASE_SHA) + - name: deleteExisting + value: "true" + - name: build-image + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/kaniko/0.6//kaniko.yaml + params: + - name: IMAGE + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + - name: CONTEXT + value: $(params.path-to-image-context) + - name: DOCKERFILE + value: $(params.path-to-dockerfile) + - name: BUILDER_IMAGE + value: "gcr.io/kaniko-project/executor:v1.12.1" + - name: EXTRA_ARGS + value: + - --cache=true + - --cache-copy-layers + - --cache-repo=harbor.fizz.buzz/kanikocache/cache + - --use-new-run # Should result in a speed-up + - --reproducible # To remove timestamps so layer caching works. + - --snapshot-mode=redo + - --skip-unused-stages=true + - --registry-mirror=dockerhub.dockerhub.svc.cluster.local + workspaces: + - name: source + workspace: git-source + - name: dockerconfig + workspace: docker-credentials + runAfter: + - fetch-repository + - name: run-cargo-clippy + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: + [ + "cargo", + "clippy", + "--no-deps", + "--all-targets", + "--all-features", + "--", + "-D", + "warnings", + ] + args: [] + env: + - name: CARGO_TARGET_DIR + value: /target + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + runAfter: + - build-image + params: + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + finally: + - name: report-success + when: + - input: "$(tasks.status)" + operator: in + values: ["Succeeded", "Completed"] + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has succeeded" + - name: STATE + value: success + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: report-failure + when: + - input: "$(tasks.status)" + operator: in + values: ["Failed"] + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has failed" + - name: STATE + value: failure + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: cargo-cache-autoclean + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: [cargo, cache, --autoclean] + args: [] + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + params: + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + workspaces: + - name: git-source + - name: docker-credentials + - name: cargo-cache + workspaces: + - name: git-source + volumeClaimTemplate: + spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + subPath: rust-source + - name: cargo-cache + persistentVolumeClaim: + claimName: natter-cargo-cache-clippy + - name: docker-credentials + secret: + secretName: harbor-plain + serviceAccountName: build-bot + params: + - name: image-name + value: "harbor.fizz.buzz/private/natter-development" + - name: path-to-image-context + value: docker/natter_development/ + - name: path-to-dockerfile + value: docker/natter_development/Dockerfile diff --git a/.lighthouse/triggers.yaml b/.lighthouse/triggers.yaml index 180fa7b..d59516b 100644 --- a/.lighthouse/triggers.yaml +++ b/.lighthouse/triggers.yaml @@ -16,3 +16,10 @@ spec: skip_branches: # We already run on every commit, so running when the semver tags get pushed is causing needless double-processing. - "^v[0-9]+\\.[0-9]+\\.[0-9]+$" + - name: rust-clippy + source: "pipeline-rust-clippy.yaml" + # Override https-based url from lighthouse events. + clone_uri: "git@code.fizz.buzz:talexander/natter.git" + skip_branches: + # We already run on every commit, so running when the semver tags get pushed is causing needless double-processing. + - "^v[0-9]+\\.[0-9]+\\.[0-9]+$" From 322dbb8f4f119793dd945901db4a80314743470f Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 20:12:59 -0500 Subject: [PATCH 08/10] Add CI job to auto-format code. --- .lighthouse/pipeline-format.yaml | 300 +++++++++++++++++++++++++++ .lighthouse/triggers.yaml | 7 + docker/natter_development/Dockerfile | 1 + 3 files changed, 308 insertions(+) create mode 100644 .lighthouse/pipeline-format.yaml diff --git a/.lighthouse/pipeline-format.yaml b/.lighthouse/pipeline-format.yaml new file mode 100644 index 0000000..4493a79 --- /dev/null +++ b/.lighthouse/pipeline-format.yaml @@ -0,0 +1,300 @@ +apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +metadata: + name: rust-clippy +spec: + pipelineSpec: + timeouts: + pipeline: "2h0m0s" + tasks: "1h0m40s" + finally: "0h30m0s" + params: + - name: image-name + description: The name for the built image + type: string + - name: path-to-image-context + description: The path to the build context + type: string + - name: path-to-dockerfile + description: The path to the Dockerfile + type: string + tasks: + - name: report-pending + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + runAfter: + - fetch-repository + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has started" + - name: STATE + value: pending + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: fetch-repository + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/git-clone/0.9/git-clone.yaml + workspaces: + - name: output + workspace: git-source + params: + - name: url + value: $(params.REPO_URL) + - name: revision + value: $(params.PULL_BASE_SHA) + - name: deleteExisting + value: "true" + - name: build-image + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/kaniko/0.6//kaniko.yaml + params: + - name: IMAGE + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + - name: CONTEXT + value: $(params.path-to-image-context) + - name: DOCKERFILE + value: $(params.path-to-dockerfile) + - name: BUILDER_IMAGE + value: "gcr.io/kaniko-project/executor:v1.12.1" + - name: EXTRA_ARGS + value: + - --cache=true + - --cache-copy-layers + - --cache-repo=harbor.fizz.buzz/kanikocache/cache + - --use-new-run # Should result in a speed-up + - --reproducible # To remove timestamps so layer caching works. + - --snapshot-mode=redo + - --skip-unused-stages=true + - --registry-mirror=dockerhub.dockerhub.svc.cluster.local + workspaces: + - name: source + workspace: git-source + - name: dockerconfig + workspace: docker-credentials + runAfter: + - fetch-repository + - name: run-cargo-fmt + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: ["cargo", "fmt"] + args: [] + env: + - name: CARGO_TARGET_DIR + value: /target + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + runAfter: + - build-image + params: + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + - name: commit-changes + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/git-cli/0.4/git-cli.yaml + params: + - name: GIT_USER_NAME + value: fluxcdbot + - name: GIT_USER_EMAIL + value: "fluxcdbot@users.noreply.github.com" + - name: GIT_SCRIPT + value: | + pwd + git config --global --add safe.directory /workspace/source + git_status=$(git status --porcelain) + if [ -n "$git_status" ]; then + git commit -a -m "CI: autofix rust code." + git push origin HEAD:$(params.PULL_BASE_REF) + else + echo "No changes to commit." + fi + workspaces: + - name: source + workspace: git-source + runAfter: + - run-cargo-fmt + finally: + - name: report-success + when: + - input: "$(tasks.status)" + operator: in + values: ["Succeeded", "Completed"] + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has succeeded" + - name: STATE + value: success + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: report-failure + when: + - input: "$(tasks.status)" + operator: in + values: ["Failed"] + taskRef: + resolver: git + params: + - name: url + value: https://github.com/tektoncd/catalog.git + - name: revision + value: df36b3853a5657fd883015cdbf07ad6466918acf + - name: pathInRepo + value: task/gitea-set-status/0.1/gitea-set-status.yaml + params: + - name: CONTEXT + value: "$(params.JOB_NAME)" + - name: REPO_FULL_NAME + value: "$(params.REPO_OWNER)/$(params.REPO_NAME)" + - name: GITEA_HOST_URL + value: code.fizz.buzz + - name: SHA + value: "$(tasks.fetch-repository.results.commit)" + - name: DESCRIPTION + value: "Build $(params.JOB_NAME) has failed" + - name: STATE + value: failure + - name: TARGET_URL + value: "https://tekton.fizz.buzz/#/namespaces/$(context.pipelineRun.namespace)/pipelineruns/$(context.pipelineRun.name)" + - name: cargo-cache-autoclean + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + - name: cargo-cache + mountPath: /usr/local/cargo/registry + optional: true + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: [cargo, cache, --autoclean] + args: [] + workspaces: + - name: source + workspace: git-source + - name: cargo-cache + workspace: cargo-cache + params: + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + workspaces: + - name: git-source + - name: docker-credentials + - name: cargo-cache + workspaces: + - name: git-source + volumeClaimTemplate: + spec: + storageClassName: "nfs-client" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + subPath: rust-source + - name: cargo-cache + persistentVolumeClaim: + claimName: natter-cargo-cache-fmt + - name: docker-credentials + secret: + secretName: harbor-plain + serviceAccountName: build-bot + params: + - name: image-name + value: "harbor.fizz.buzz/private/natter-development" + - name: path-to-image-context + value: docker/natter_development/ + - name: path-to-dockerfile + value: docker/natter_development/Dockerfile diff --git a/.lighthouse/triggers.yaml b/.lighthouse/triggers.yaml index d59516b..eeb89d1 100644 --- a/.lighthouse/triggers.yaml +++ b/.lighthouse/triggers.yaml @@ -23,3 +23,10 @@ spec: skip_branches: # We already run on every commit, so running when the semver tags get pushed is causing needless double-processing. - "^v[0-9]+\\.[0-9]+\\.[0-9]+$" + - name: format + source: "pipeline-format.yaml" + # Override https-based url from lighthouse events. + clone_uri: "git@code.fizz.buzz:talexander/natter.git" + skip_branches: + # We already run on every commit, so running when the semver tags get pushed is causing needless double-processing. + - "^v[0-9]+\\.[0-9]+\\.[0-9]+$" diff --git a/docker/natter_development/Dockerfile b/docker/natter_development/Dockerfile index 38f2de1..a217814 100644 --- a/docker/natter_development/Dockerfile +++ b/docker/natter_development/Dockerfile @@ -2,3 +2,4 @@ FROM rustlang/rust:nightly-alpine3.17 AS builder RUN apk add --no-cache musl-dev RUN cargo install --locked --no-default-features --features ci-autoclean cargo-cache +RUN rustup component add rustfmt From d5572c93cd64940eb8b957ae627b44263478982b Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Fri, 22 Dec 2023 20:43:39 -0500 Subject: [PATCH 09/10] Add prettier step. --- .lighthouse/pipeline-format.yaml | 40 +++++++++++++++++++++++++++- docker/natter_development/Dockerfile | 5 ++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/.lighthouse/pipeline-format.yaml b/.lighthouse/pipeline-format.yaml index 4493a79..e53d3ef 100644 --- a/.lighthouse/pipeline-format.yaml +++ b/.lighthouse/pipeline-format.yaml @@ -143,6 +143,44 @@ spec: params: - name: docker-image value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" + - name: run-prettier + taskSpec: + metadata: {} + params: + - name: docker-image + type: string + description: Docker image to run. + default: alpine:3.18 + stepTemplate: + image: alpine:3.18 + name: "" + resources: + requests: + cpu: 10m + memory: 600Mi + workingDir: /workspace/source + workspaces: + - name: source + mountPath: /source + steps: + - name: run + image: $(params.docker-image) + workingDir: "$(workspaces.source.path)" + command: ["sh", "-c"] + args: + - | + prettier --write --no-error-on-unmatched-pattern "default_environment/**/*.js" "default_environment/**/*.css" + env: + - name: CARGO_TARGET_DIR + value: /target + workspaces: + - name: source + workspace: git-source + runAfter: + - run-cargo-fmt + params: + - name: docker-image + value: "$(params.image-name):$(tasks.fetch-repository.results.commit)" - name: commit-changes taskRef: resolver: git @@ -173,7 +211,7 @@ spec: - name: source workspace: git-source runAfter: - - run-cargo-fmt + - run-prettier finally: - name: report-success when: diff --git a/docker/natter_development/Dockerfile b/docker/natter_development/Dockerfile index a217814..bfbcdb1 100644 --- a/docker/natter_development/Dockerfile +++ b/docker/natter_development/Dockerfile @@ -3,3 +3,8 @@ FROM rustlang/rust:nightly-alpine3.17 AS builder RUN apk add --no-cache musl-dev RUN cargo install --locked --no-default-features --features ci-autoclean cargo-cache RUN rustup component add rustfmt + +FROM builder AS javascript + +RUN apk add --no-cache npm +RUN npm install --global prettier@3.1.0 From df339f20fa4bc0c989906b7755109e15c344a000 Mon Sep 17 00:00:00 2001 From: fluxcdbot Date: Sat, 23 Dec 2023 01:46:40 +0000 Subject: [PATCH 10/10] CI: autofix rust code. --- default_environment/stylesheet/main.css | 367 ++++++++++++----------- default_environment/stylesheet/reset.css | 147 +++++++-- src/command/add_post/mod.rs | 1 + 3 files changed, 301 insertions(+), 214 deletions(-) diff --git a/default_environment/stylesheet/main.css b/default_environment/stylesheet/main.css index b7af2a4..89f4259 100644 --- a/default_environment/stylesheet/main.css +++ b/default_environment/stylesheet/main.css @@ -1,224 +1,229 @@ :root { - --main-max-width: 800px; - --site-background-color: #0a0a0a; - --site-text-color: #fffffc; - --header-divider-color: #6a687a; + --main-max-width: 800px; + --site-background-color: #0a0a0a; + --site-text-color: #fffffc; + --header-divider-color: #6a687a; - --stream-divider-color: #6ccff6; + --stream-divider-color: #6ccff6; - --src-font-family: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace; + --src-font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, + Consolas, "DejaVu Sans Mono", monospace; - --src-block-background-color: #141414; - --src-block-border-color: #84828f; - --src-block-language-color: #0a0a0a; - --src-block-language-background: #84828f; + --src-block-background-color: #141414; + --src-block-border-color: #84828f; + --src-block-language-color: #0a0a0a; + --src-block-language-background: #84828f; - --quote-block-border-color: #84828f; + --quote-block-border-color: #84828f; - --table-border-color: #6a687a; - --table-odd-background-color: #0a0a0a; - --table-even-background-color: #141414; + --table-border-color: #6a687a; + --table-odd-background-color: #0a0a0a; + --table-even-background-color: #141414; } body { - color: var(--site-text-color); - background-color: var(--site-background-color); - font-family: source-sans-pro, Seravek, 'Gill Sans Nova', Ubuntu, Calibri, 'DejaVu Sans', sans-serif; + color: var(--site-text-color); + background-color: var(--site-background-color); + font-family: source-sans-pro, Seravek, "Gill Sans Nova", Ubuntu, Calibri, + "DejaVu Sans", sans-serif; - a:link, a:visited { - /* TODO: Should I use a different color for links? */ - color: var(--site-text-color); - } + a:link, + a:visited { + /* TODO: Should I use a different color for links? */ + color: var(--site-text-color); + } } .page_centering { - display: flex; - flex-direction: column; - align-items: center; + display: flex; + flex-direction: column; + align-items: center; } .page_header { - width: 100%; - max-width: var(--main-max-width); - border-bottom: 0.1rem solid var(--header-divider-color); + width: 100%; + max-width: var(--main-max-width); + border-bottom: 0.1rem solid var(--header-divider-color); - .home_link { - font-size: 1.2rem; - font-weight: 600; - text-decoration: none; + .home_link { + font-size: 1.2rem; + font-weight: 600; + text-decoration: none; - &:link, &:visited { - color: var(--site-text-color); - } + &:link, + &:visited { + color: var(--site-text-color); } + } } .main_content { - width: 100%; - max-width: var(--main-max-width); - font-size: 1.2rem; - line-height: 1.2; + width: 100%; + max-width: var(--main-max-width); + font-size: 1.2rem; + line-height: 1.2; - /* A stand-alone blog post (not in a blog stream). */ - .blog_post { - padding: 1rem 0 3rem 0; + /* A stand-alone blog post (not in a blog stream). */ + .blog_post { + padding: 1rem 0 3rem 0; + } + + .blog_stream { + .stream_divider { + color: var(--stream-divider-color); + } + } + + /* A blog post in a blog stream (for example, the homepage). */ + .blog_stream_post { + background: #1f1f1f; + padding: 1rem 0.2rem; + } + + .blog_post_title { + font-size: 2.5rem; + font-weight: 700; + padding-bottom: 1rem; + } + + p { + margin: 1rem 0; + } + + .src_block { + background: var(--src-block-background-color); + border-radius: 3px; + border: 1px solid var(--src-block-border-color); + font-size: 1rem; + font-family: var(--src-font-family); + margin: 1rem 0; + + .src_language { + display: inline-block; + color: var(--src-block-language-color); + background: var(--src-block-language-background); + border-radius: 0 0 3px 0; + padding: 0.1rem 0.5rem; + font-size: 0.8rem; + vertical-align: top; } - .blog_stream { - .stream_divider { - color: var(--stream-divider-color); - } + .src_body { + margin: 0.5rem; + + .src_line { + white-space: pre-wrap; + } + } + } + + .inline_source_block { + font-family: var(--src-font-family); + font-size: 1rem; + } + + .code, + .verbatim { + font-family: var(--src-font-family); + font-size: 1rem; + } + + .quote_block { + border-left: 1px solid var(--quote-block-border-color); + padding: 0 0 0 1rem; + margin: 1rem 0 1rem 2rem; + } + + h2, + h3 { + margin: 1rem 0; + padding-bottom: 0.5rem; + } + + h2 { + font-size: 2.3rem; + font-weight: 600; + } + + h3 { + font-size: 2.1rem; + font-weight: 600; + } + + .plain_list { + &.unordered { + list-style-type: disc; + padding-left: 2.5rem; } - /* A blog post in a blog stream (for example, the homepage). */ - .blog_stream_post { - background: #1F1F1F; - padding: 1rem 0.2rem; + &.ordered { + list-style-type: decimal; + padding-left: 2.5rem; } - .blog_post_title { - font-size: 2.5rem; - font-weight: 700; - padding-bottom: 1rem; - } - - - p { - margin: 1rem 0; - } - - .src_block { - background: var(--src-block-background-color); - border-radius: 3px; - border: 1px solid var(--src-block-border-color); - font-size: 1rem; - font-family: var(--src-font-family); - margin: 1rem 0; - - .src_language { - display: inline-block; - color: var(--src-block-language-color); - background: var(--src-block-language-background); - border-radius: 0 0 3px 0; - padding: 0.1rem 0.5rem; - font-size: 0.8rem; - vertical-align: top; - } - - .src_body { - margin: 0.5rem; - - .src_line { - white-space: pre-wrap; - } - } - } - - .inline_source_block { - font-family: var(--src-font-family); - font-size: 1rem; - } - - .code, .verbatim { - font-family: var(--src-font-family); - font-size: 1rem; - } - - .quote_block { - border-left: 1px solid var(--quote-block-border-color); - padding: 0 0 0 1rem; - margin: 1rem 0 1rem 2rem; - } - - h2, h3 { - margin: 1rem 0; - padding-bottom: 0.5rem; - } - - h2 { - font-size: 2.3rem; + &.descriptive { + font-size: 1rem; + > dt { font-weight: 600; + } + + > dd { + padding-left: 2.5rem; + } } + } - h3 { - font-size: 2.1rem; - font-weight: 600; + .footnote_reference { + vertical-align: super; + font-size: 80%; + > a { + text-decoration: none; } + } - .plain_list { - &.unordered { - list-style-type: disc; - padding-left: 2.5rem; - } - - &.ordered { - list-style-type: decimal; - padding-left: 2.5rem; - } - - &.descriptive { - font-size: 1rem; - > dt { - font-weight: 600; - } - - > dd { - padding-left: 2.5rem; - } - } + .footnote_definition { + .label { + text-decoration: none; } + .definition { + display: inline; - .footnote_reference { - vertical-align: super; - font-size: 80%; - > a { - text-decoration: none; - } + > p { + display: inline; + } } + } - .footnote_definition { - .label { - text-decoration: none; - } - .definition { - display: inline; - - > p { - display: inline; - } + .org_table { + table-layout: fixed; + border-collapse: collapse; + border: 1px solid var(--table-border-color); + > tbody { + border-width: 1px 0; + border-style: solid; + border-color: var(--table-border-color); + > tr { + > td { + padding: 0.2rem; } + } + > tr:nth-child(odd) { + background-color: var(--table-odd-background-color); + } + > tr:nth-child(even) { + background-color: var(--table-even-background-color); + } } - - .org_table { - table-layout: fixed; - border-collapse: collapse; - border: 1px solid var(--table-border-color); - > tbody { - border-width: 1px 0; - border-style: solid; - border-color: var(--table-border-color); - > tr { - > td { - padding: 0.2rem; - } - } - > tr:nth-child(odd) { - background-color: var(--table-odd-background-color); - } - > tr:nth-child(even) { - background-color: var(--table-even-background-color); - } - } - > thead { - border-width: 1px 0; - border-style: solid; - border-color: var(--table-border-color); - > tr { - > th { - padding: 0.2rem; - font-weight: 600; - } - } + > thead { + border-width: 1px 0; + border-style: solid; + border-color: var(--table-border-color); + > tr { + > th { + padding: 0.2rem; + font-weight: 600; } + } } + } } diff --git a/default_environment/stylesheet/reset.css b/default_environment/stylesheet/reset.css index ed11813..3675e64 100644 --- a/default_environment/stylesheet/reset.css +++ b/default_environment/stylesheet/reset.css @@ -3,46 +3,127 @@ License: none (public domain) */ -html, body, div, span, applet, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -a, abbr, acronym, address, big, cite, code, -del, dfn, em, img, ins, kbd, q, s, samp, -small, strike, strong, sub, sup, tt, var, -b, u, i, center, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, canvas, details, embed, -figure, figcaption, footer, header, hgroup, -menu, nav, output, ruby, section, summary, -time, mark, audio, video { - margin: 0; - padding: 0; - border: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline; +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ -article, aside, details, figcaption, figure, -footer, header, hgroup, menu, nav, section { - display: block; +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; } body { - line-height: 1; + line-height: 1; } -ol, ul { - list-style: none; +ol, +ul { + list-style: none; } -blockquote, q { - quotes: none; +blockquote, +q { + quotes: none; } -blockquote:before, blockquote:after, -q:before, q:after { - content: ''; - content: none; +blockquote:before, +blockquote:after, +q:before, +q:after { + content: ""; + content: none; } table { - border-collapse: collapse; - border-spacing: 0; + border-collapse: collapse; + border-spacing: 0; } diff --git a/src/command/add_post/mod.rs b/src/command/add_post/mod.rs index e69de29..8b13789 100644 --- a/src/command/add_post/mod.rs +++ b/src/command/add_post/mod.rs @@ -0,0 +1 @@ +