# Business rules — CodeDeployScripts

Evidence date: 2026-10-18. `master` at `06626b32e2a09034b7df2b94b9abae5809bc12e6`. `development` at `dc915f471e87e29b745568c2a5aba62fb0e4dfd7` where a rule differs.

This repository is a deploy example and a checklist. It has no application domain objects, no database, and no permission code. Rules below are the ones the README states or the scripts enforce. Nothing here is a new product decision.

Labels:

- **Documented** — written in `README.md`.
- **Implemented** — what a script, the AppSpec, or the pipeline file does.
- **Inferred** — a reasonable reading that the file does not state.

Placeholder values in the README and the PEM body are not copied into this document.

## BR-PURPOSE — What the repository is for

The `master` branch deploys the tree to EC2 through CodeDeploy. The `development` branch sends the tree to FTP through `git-ftp`. The HTML file is the payload a person can look at after a deploy.

Provenance: the two pipeline steps are **Implemented**. The README title states both AWS and FTP. Treating the HTML file as a smoke banner rather than a product screen is **Inferred** from the heading text and from there being no other page.

## BR-BRANCH — Which pipeline runs

1. A build of `master` runs the `master` step only. Provenance: **Implemented**.
2. A build of `development` runs the `development` step only. Provenance: **Implemented**.
3. There is no default pipeline and no pull-request pipeline. Provenance: **Implemented** by absence.
4. The step uses the yml committed on that branch. The two tips do not contain the same FTP command. Provenance: **Implemented**.

## BR-AWS-TARGET — Names the checklist gives

These names are written in the README. The Python script does not hard-code them. It reads environment variables.

| Checklist name | Value written in the README | Variable the script reads |
|---|---|---|
| Region | `eu-west-1` | `AWS_DEFAULT_REGION` is listed. The script does not pass `region_name` |
| Application | `CodedeployDev` | `APPLICATION_NAME` |
| Deployment group | `DG1` | `DEPLOYMENT_GROUP_NAME` |
| Deployment config | `CodeDeployDefault.OneAtATime` | `DEPLOYMENT_CONFIG` |
| S3 bucket | `codedeploy` | `S3_BUCKET` |
| EC2 tag | key `name`, value `CodedeployEC2Dev` | not read by the script. CodeDeploy group selection is outside this repo |
| IAM group | `CodeDeployGroup` | not read by the script |
| IAM role | `AWSCodeDeployRole` | not read by the script |

Provenance: the values are **Documented**. The variable reads are **Implemented**.

A rule that these example names must be kept forever was **not found**. They are the only names the checklist gives.

## BR-IAM — Access the checklist asks for

The README tells the operator to attach:

- On group `CodeDeployGroup`: `AmazonEC2FullAccess`, `AmazonS3FullAccess`, `AWSCodeDeployFullAccess`.
- On role `AWSCodeDeployRole`: `AWSCodeDeployRole` and `AmazonS3FullAccess`.
- Trust: `ec2.amazonaws.com` and `codedeploy.eu-west-1.amazonaws.com`, action `sts:AssumeRole`.

Provenance: **Documented**. This repo does not call IAM.

The programmatic user's key and secret are stored as Bitbucket variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. The README marks the access key id line with `#secure` and prints placeholders. Provenance: **Documented**.

## BR-NETWORK — What the checklist opens

The EC2 security group in the README allows HTTP, HTTPS, SSH, and TCP 3000 from anywhere. Provenance: **Documented**.

No script sets a listen port. `start_server` runs `service httpd start` with no port argument. Nothing in the tree refers to port 3000 except that security-group line. A reason for port 3000 was **not found**. **Unknown / Requires Confirmation**.

SSH from anywhere is what the README writes. It is not a rule enforced by code in this repo.

## BR-INSTANCE — What must already be on the box

The README's manual install is Amazon Linux, `t2.micro`, Remi PHP 5.4, `httpd`, `git`, `ruby`, `wget`, and the CodeDeploy agent for `eu-west-1`. The install line is written as `sudo sudo yum`. Provenance: **Documented**, including the doubled `sudo`.

The hooks do not repeat that install. They only `yum install httpd` and start or stop `httpd`. Provenance: **Implemented**.

No committed file is PHP. A rule that the deployed site needs PHP was **not found** in code. The package list is only in the README. Whether a later, uncommitted site needed PHP is **Unknown / Requires Confirmation**.

## BR-PACKAGE — What a master build uploads

1. The zip command is `zip -r /tmp/artifact.zip *` from the pipeline work directory. Provenance: **Implemented**.
2. The object key is `{APPLICATION_NAME}/{YYYYmmddHHMMSS}-bitbucket_builds.zip`. Provenance: **Implemented**.
3. The timestamp is taken once, at import, with `strftime("%Y%m%d%H%M%S")`. Two builds in the same second could share a key. The script has no uniqueness check. Provenance: **Implemented** format. The collision case is **Inferred**.
4. `APPLICATION_NAME` is required for the key to be built. The script does not check it before concatenation. Provenance: **Implemented**.
5. The AppSpec then copies the archive root to `/var/www/html/`. Provenance: **Implemented**.
6. The glob includes the tracked private key file, because that file is not a dotfile and it lives at the root. Provenance: **Inferred** from the glob and `git ls-files`. No comment says this is intended.

## BR-DEPLOY-RESULT — When the master step succeeds

1. Upload failure returns False and the process exits 1. Provenance: **Implemented**.
2. `create_deployment` failure returns False and the process exits 1. Provenance: **Implemented**.
3. Status `Succeeded` is the only polled status that exits 0. Provenance: **Implemented**.
4. Status `Failed` or `Stopped` exits 1 and prints `deploymentInfo`. Provenance: **Implemented**.
5. Status `InProgress`, `Queued`, or `Created` polls again immediately. Provenance: **Implemented**.
6. Any other status also polls again. The chain has no `else`. Provenance: **Implemented**.
7. The loop has no timeout. The yml sets no `max-time`. What Bitbucket does with a step that never exits is **Unknown** from this repo.
8. `ignoreApplicationStopFailures` is true, so CodeDeploy is told not to fail the deployment when `ApplicationStop` fails. Provenance: **Implemented**. The README does not mention this flag.

## BR-HOOKS — Order of host actions the AppSpec names

The file names three hooks. It does not describe CodeDeploy's full lifecycle.

1. `ApplicationStop` runs `scripts/stop_server` as root, limit 300 seconds. Provenance: **Implemented**.
2. `BeforeInstall` runs `scripts/install_dependencies` as root, limit 300 seconds. That script is `sudo yum install -y httpd`. Provenance: **Implemented**.
3. `ApplicationStart` runs `scripts/start_server` as root, limit 300 seconds. That script sets mode `755` on `/var/www/html` and starts `httpd`. Provenance: **Implemented**.
4. There is no `ValidateService` hook. A start script that returns 0 is the last check this repo defines. Provenance: **Implemented** by absence. Calling that "no health check" is **Inferred**.

## BR-STOP — What the stop script actually writes

1. The first line is `isExistApp = `pgrep httpd`` with spaces around `=`. Provenance: **Implemented**.
2. A shell assignment cannot have those spaces. The line is a command, not an assignment. Provenance: **Inferred** from bash syntax. The repo does not include a test run.
3. The `if` stops `httpd` only when `$isExistApp` is non-empty. If the assignment never happens, the variable is empty and `httpd` is not stopped. Provenance: **Inferred**.
4. The script has no `set -e`. A failing command does not by itself stop the rest of the file. Provenance: **Implemented** by absence. The effect is **Inferred**.
5. The script always reaches `sudo chmod 777 -R /var/www/html` unless an earlier line aborts the shell. Provenance: **Implemented** text. Whether the chmod is reached is **Inferred** (medium confidence) and **Requires Confirmation** on a shell.
6. The README does not say the web root should be mode `777` before install or mode `755` after start. Those modes are **Implemented** only. Whether they are accepted is **Unknown / Requires Confirmation**.

## BR-FTP — When the development step runs

1. Required variables are `FTP_USERNAME`, `FTP_PASSWORD`, and `FTP_HOST`. Provenance: **Documented** and **Implemented**.
2. The URL is `ftp://$FTP_HOST`. No port, no path, no FTPS. Provenance: **Implemented**.
3. On `development`, the active command is `git ftp push`. `git ftp init` is commented. Provenance: **Implemented**.
4. On `master`, the `development` key does the opposite: init is active, push is commented. Provenance: **Implemented**.
5. The README says the first deploy uses "git init" and later deploys use "git push", and that the real commands are in the yml. Provenance: **Documented**. The yml commands are `git ftp init` and `git ftp push`. The README does not say which branch's yml is the one to follow.
6. The password is passed with `-p` on the command line. Provenance: **Implemented**. The README comment on that variable is `#secure`.
7. Whether init has already been run against the host is **Unknown / Requires Confirmation**. Running init twice is a `git-ftp` concern. This repo does not handle that error.

## BR-PAGE — What the banner is allowed to say

No rule in the README constrains the page text. The committed headings are the feature. They have been overwritten several times, including a heading that is not on either tip (`Monique is die pragtigste` in `bc26c5b`, replaced by `093d5ab`).

The current `master` heading says "Dev Server". The current `development` heading says "QA Enviroment". An earlier shared heading said "Production Deployment". A rule that maps branches to environments was **not found** beyond those strings. **Unknown / Requires Confirmation** which environment each branch is supposed to be.

## BR-SECRET-FILE — The committed key

1. `silcodedeploy_evolvav.pem` is tracked. The blob is 1670 bytes. The first line is `-----BEGIN RSA PRIVATE KEY-----`. Provenance: **Implemented**.
2. It was added in `88a609e` (2019-05-30, "New updates pem") by Jaco Brits. Provenance: **Implemented** history.
3. No README line, pipeline step, hook, or Python string names `pem` or `evolvav`. Provenance: **Implemented** absence (`git grep` on `master`).
4. The filename is not a documented requirement. What "evolvav" refers to is **Unknown / Requires Confirmation**.
5. Because the file is in git history, deleting it on a later commit would not remove it from old revisions. That is a property of git, not a rule this repo states.

## BR-AUTH — Who may deploy

The repo does not check the caller. Deploy rights are whoever can push the branch and whoever holds the Bitbucket variables. Provenance: **Inferred** from the absence of auth code plus the variables the pipeline reads. Bitbucket project permissions are **Unknown / Requires Confirmation**.

The README's IAM policies are the AWS managed full-access policies named above. This repo does not narrow them.

## BR-SAMPLE-ORIGIN — The deploy script's stated origin

The Python file header says it is Amazon's Bitbucket Builds template v1.0.0, copyright 2016, Apache License 2.0, contact `narshiva@amazon.com`. The README points at `https://bitbucket.org/awslabs/aws-codedeploy-bitbucket-pipelines-python/src/master/`. Provenance: **Documented**.

Local commits on 2019-05-29 changed error reporting and briefly added a retries dict. A line-by-line claim that the tip still matches upstream v1.0.0 was **not** verified against that remote. **Unknown / Requires Confirmation** how far the body has drifted from the sample.
