diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..1a68db5e5 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ +## Goal + + +## Changes +- + +## Testing + + +## Checklist +- [ ] Title is a clear sentence (≤ 70 chars) +- [ ] Commits are signed (`git log --show-signature`) +- [ ] `submissions/labN.md` updated diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..383ab79ee --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +name: CI +on: + push: + branches: + - main + paths: + - app/** + - .github/workflows/ci.yml + pull_request: + branches: + - main + paths: + - app/** + - .github/workflows/ci.yml + workflow_dispatch: +jobs: + test: + name: Run ${{ matrix.target }} for Go ${{ matrix.version }} + runs-on: ubuntu-24.04 + permissions: + contents: read + strategy: + fail-fast: false + matrix: + version: ['1.24', '1.25'] + target: ['test', 'vet', 'lint'] + include: + - target: test + cmd: go test -race -count=1 ./... + - target: vet + cmd: go vet ./... + steps: + - name: Checkout code + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + + - name: Set up Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 + with: + go-version: ${{ matrix.version }} + cache: true + cache-dependency-path: app/go.mod + + - name: Run golangci-lint + if: matrix.target == 'lint' + uses: golangci/golangci-lint-action@82606bf257cbaff209d206a39f5134f0cfbfd2ee # v9.2.1 + with: + version: v2.5.0 + working-directory: app + + - name: Run ${{ matrix.target }} + if: matrix.target != 'lint' + run: | + cd app + ${{ matrix.cmd }} diff --git a/submissions/lab3-blocked-merge.png b/submissions/lab3-blocked-merge.png new file mode 100644 index 000000000..a95182638 Binary files /dev/null and b/submissions/lab3-blocked-merge.png differ diff --git a/submissions/lab3-branch-protection.png b/submissions/lab3-branch-protection.png new file mode 100644 index 000000000..5c419b72a Binary files /dev/null and b/submissions/lab3-branch-protection.png differ diff --git a/submissions/lab3-failed-run-log.png b/submissions/lab3-failed-run-log.png new file mode 100644 index 000000000..2d8f67490 Binary files /dev/null and b/submissions/lab3-failed-run-log.png differ diff --git a/submissions/lab3-merge-allowed.png b/submissions/lab3-merge-allowed.png new file mode 100644 index 000000000..43ae53f29 Binary files /dev/null and b/submissions/lab3-merge-allowed.png differ diff --git a/submissions/lab3.md b/submissions/lab3.md new file mode 100644 index 000000000..0a7161673 --- /dev/null +++ b/submissions/lab3.md @@ -0,0 +1,41 @@ +# Lab 3 submission +### The path +I have chosen GitHub path, because it works for me, and I already have an account. + +### Branch protection rule +![](./lab3-branch-protection.png) + +### Failed run + fix +Failed run prevents from merging:\ +![](./lab3-blocked-merge.png) + +Failed run log:\ +![](./lab3-failed-run-log.png) + +After fix:\ +![](./lab3-merge-allowed.png) + +[Link to the green run](https://github.com/arsenez2006/DevOps-Intro/actions/runs/27502050568) + +### Design questions +- a) `latest` tag is a moving target. When GitHub upgrades the underlying runner image version, our workflow inherits it. Sudden updates may introduce breaking changes in pre-installed software, leading to pipeline failures. +- b) One combined job runs sequentially, while separate units run concurrently, significantly reducing total pipeline execution time. If a single formatting commit triggers a combined job, where the lint error appears at the end of a 15-minute test suite run, the entire pipeline fails late. Furthermore, a failure in an early step might prevent subsequent steps from running at all, hiding other errors. +- c) SHA pinning prevents Supply Chain Attacks via tag mutability. Tags may be overwritten by a malicious actor, making our pipeline inherit the compromised code (In March 2025, the popular tj-actions/changed-files action was compromised; the attacker rewrote all tags to a malicious version, leaking secrets from thousands of public CI runs). A cryptographic SHA is immutable and cannot be spoofed. +- d) `permissions:` is the runner access configuration for workflows. On workflows initiation, GitHub automatically issues a short-lived access token for the runner. The runner access token permissions may be configured the `permissions:` directive. By explicitly defining permissions, we ensure that even if an attacker successfully injects malicious code into the runner, they cannot abuse the token to gain full access to the repository. +- f) Caching `go.sum`-keyed inputs ensures strict environmental reproducibility by fixing the dependency tree. Conversely, caching build outputs is unreliable because artifacts depend on host-specific hardware, compiler versions, and system flags, which often lead to invalid states when restored on different runners. +- g) `fail-fast: false` ensures that all matrix jobs run to completion even if one fails, allowing us to see the full scope of potential issues. `fail-fast: true` should be used during active development or PRs to stop the pipeline immediately upon the first error, which saves compute costs and provides faster feedback. +- h) An attacker could attempt to "poison" the cache by writing malicious artifacts from a PR that a protected branch might later read. GitHub mitigates this risk through strict scope isolation: workflows from PRs can read caches from the target branch, but they are explicitly forbidden from writing to or overwriting caches scoped to that protected base branch. + +### Pipeline Measurements + +| Scenario | Wall-clock | +|----------|-----------| +| Baseline (no cache, single Go version, no path filter) | 37 s | +| With cache | 33 s | +| With cache + matrix | 30 s | + +### Pipeline optimizations +- Every pipeline job are executed concurrently, reducing overall wall-time +- Build inputs (`setup-go` and `golandci-lint`) are cached \ No newline at end of file