Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Goal
<!-- What does this PR accomplish? 1 sentence. -->

## Changes
-

## Testing
<!-- How did you verify it? -->

## Checklist
- [ ] Title is a clear sentence (≤ 70 chars)
- [ ] Commits are signed (git log --show-signature)
- [ ] submissions/labN.md updated
84 changes: 84 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: quicknotes-ci

on:
push:
branches: [main]
paths:
- "app/**"
- ".github/workflows/ci.yml"
- "submissions/**"
pull_request:
branches: [main]
paths:
- "app/**"
- ".github/workflows/ci.yml"
- "submissions/**"

permissions:
contents: read

jobs:
vet:
name: vet (${{ matrix.go-version }})
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
go-version: ["1.23", "1.24"]
defaults:
run:
working-directory: app
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ matrix.go-version }}
cache: true
cache-dependency-path: app/go.mod
- run: go vet ./...

test:
name: test (${{ matrix.go-version }})
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
go-version: ["1.23", "1.24"]
defaults:
run:
working-directory: app
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: ${{ matrix.go-version }}
cache: true
cache-dependency-path: app/go.mod
- run: go test -race -count=1 ./...

lint:
name: lint
runs-on: ubuntu-24.04
defaults:
run:
working-directory: app
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
with:
go-version: "1.24"
cache: true
cache-dependency-path: app/go.mod
- uses: golangci/golangci-lint-action@db582008a42febd596419635a5abc9d9815daa9c # v9.2.1
with:
version: v2.5.0
working-directory: app

ci-ok:
name: ci-ok
if: always()
needs: [vet, test, lint]
runs-on: ubuntu-24.04
steps:
- run: |
test "${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}" = "false"
147 changes: 147 additions & 0 deletions submissions/lab1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Lab 1 submission

## Task 1. SSH Commit Signing & QuickNotes Run

I ran the QuickNotes Go service locally and verified the main API endpoints required for the lab. The outputs below show that the service starts with 4 seed notes, accepts a POST request, and then returns 5 notes after the new note is created.

### GET /health

```json
{
"notes": 4,
"status": "ok"
}
```

### GET /notes

```json
[
{
"id": 4,
"title": "Endpoint cheat-sheet",
"body": "GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics",
"created_at": "2026-01-15T10:15:00Z"
},
{
"id": 1,
"title": "Welcome to QuickNotes",
"body": "This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.",
"created_at": "2026-01-15T10:00:00Z"
},
{
"id": 2,
"title": "Read app/main.go first",
"body": "Start by understanding the entry point ??? env vars, signal handling, graceful shutdown.",
"created_at": "2026-01-15T10:05:00Z"
},
{
"id": 3,
"title": "DevOps mantra",
"body": "If it hurts, do it more often.",
"created_at": "2026-01-15T10:10:00Z"
}
]
```

### POST /notes

```json
{
"id": 5,
"title": "hello",
"body": "first POST",
"created_at": "2026-06-09T16:15:20.8332538Z"
}
```

### GET /notes after POST

```json
[
{
"id": 1,
"title": "Welcome to QuickNotes",
"body": "This is the project you'll containerize, deploy, monitor, and harden across all 10 labs.",
"created_at": "2026-01-15T10:00:00Z"
},
{
"id": 2,
"title": "Read app/main.go first",
"body": "Start by understanding the entry point ??? env vars, signal handling, graceful shutdown.",
"created_at": "2026-01-15T10:05:00Z"
},
{
"id": 3,
"title": "DevOps mantra",
"body": "If it hurts, do it more often.",
"created_at": "2026-01-15T10:10:00Z"
},
{
"id": 4,
"title": "Endpoint cheat-sheet",
"body": "GET /notes GET /notes/{id} POST /notes DELETE /notes/{id} GET /health GET /metrics",
"created_at": "2026-01-15T10:15:00Z"
},
{
"id": 5,
"title": "hello",
"body": "first POST",
"created_at": "2026-06-09T16:15:20.8332538Z"
}
]
```


### SSH Signature Verification

Output of `git log --show-signature -1`:

```text
commit dc8c98d900773636b9d274270de88981ea55d5a5 (HEAD -> feature/lab1)
Good "git" signature for sokoslav1707@gmail.com with ED25519 key SHA256:...
Author: Yaroslav Sokolov <sokoslav1707@gmail.com>
Date: Tue Jun 9 19:21:06 2026 +0300

docs(lab1): start submission

Signed-off-by: Yaroslav Sokolov <sokoslav1707@gmail.com>
```

### Verified Commit Screenshot

![Verified Commit](src/screenshots/lab01/task1_verified_commit_screenshot.png)

### Why Signed Commits Matter

Signed commits provide cryptographic proof that a commit was created by the claimed author and has not been modified after signing. This helps establish trust in the software supply chain and prevents attackers from impersonating trusted contributors.

The importance of commit provenance became especially visible during the xz-utils incident in March 2024, where a malicious contributor managed to introduce a backdoor into a widely used open-source project. Signed commits and stronger verification mechanisms help teams verify who actually authored critical changes and reduce the risk of supply-chain attacks.


## Task 2. Pull Request Template & First PR

### PR Template Auto-Population

The pull request description was automatically populated from the template stored in `.github/pull_request_template.md`.

![PR Template Auto-Population](src/screenshots/lab01/task2_pr_template.png)


## Task 3. GitHub Community

Stars help developers bookmark useful repositories and give visibility to open-source projects. Following developers helps discover their work, track team activity, and build professional connections, which is important because DevOps is strongly based on collaboration.

## Bonus Task. Branch Protection & Required Signed Commits

### Branch Protection Configuration

![Branch Protection Rules](src/screenshots/lab01/bonus_task_rulesets.png)

### Unsigned Push Attempt

![Unsigned Push Attempt](src/screenshots/lab01/bonus_task_failed_push.png)

### Reflection

With branch protection and required signed commits, a risky production branch becomes harder to mutate accidentally or anonymously. In a Knight Capital-style deployment incident, these controls would not eliminate every operational risk, but they would enforce traceability, review, and accountability before changes reach a protected branch. Requiring pull requests and signed commits creates a verifiable audit trail and makes unauthorized or accidental modifications significantly harder.
Binary file added submissions/lab2.md
Binary file not shown.
Loading