diff --git a/.gitea/workflows/cleanup-branch.yaml b/.gitea/workflows/cleanup-branch.yaml new file mode 100644 index 0000000..d81565a --- /dev/null +++ b/.gitea/workflows/cleanup-branch.yaml @@ -0,0 +1,14 @@ +name: Cleanup branch.dsv.su.se +on: + pull_request: + types: [closed] + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - id: cleanup + uses: https://gitea.dsv.su.se/ansv7779/action-branch-deploy@510ddaa0b9507c6c1bc288582ef6e23b8b5b6089 + with: + compose-file: 'compose-branch.yaml' + mode: 'cleanup' diff --git a/.gitea/workflows/deploy-branch.yaml b/.gitea/workflows/deploy-branch.yaml new file mode 100644 index 0000000..4099b9e --- /dev/null +++ b/.gitea/workflows/deploy-branch.yaml @@ -0,0 +1,27 @@ +name: Deploy to branch.dsv.su.se +on: + pull_request: + types: [opened, reopened, synchronize] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - id: deploy + uses: https://gitea.dsv.su.se/ansv7779/action-branch-deploy@510ddaa0b9507c6c1bc288582ef6e23b8b5b6089 + with: + compose-file: 'compose-branch.yaml' + - name: Post URL to deployment as comment + uses: actions/github-script@v7 + if: github.event.action == 'opened' + env: + BRANCH_URL: ${{ steps.deploy.outputs.url }} + with: + script: | + const url = process.env.BRANCH_URL; + github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `Deployed to ${url}` + }) diff --git a/compose-branch.yaml b/compose-branch.yaml new file mode 100644 index 0000000..ff527dd --- /dev/null +++ b/compose-branch.yaml @@ -0,0 +1,45 @@ +services: + web: + extends: + file: compose-parent.yaml + service: web + depends_on: + db: + condition: service_healthy + networks: + - blog-network + - traefik + environment: + - OAUTH2_AUTHORIZATION_URI=https://oauth2-${VHOST}/authorize + - OAUTH2_TOKEN_URI=https://oauth2-${VHOST}/exchange + - OAUTH2_USER_INFO_URI=https://oauth2-${VHOST}/verify + labels: + - "traefik.enable=true" + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.rule=Host(`${VHOST}`)" + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}.tls.certresolver=letsencrypt" + + db: + extends: + file: compose-parent.yaml + service: db + networks: + - blog-network + + oauth2: + extends: + file: compose-parent.yaml + service: oauth2 + networks: + - traefik + environment: + CLIENT_REDIRECT_URI: https://${VHOST}/login/oauth2/code/local + labels: + - "traefik.enable=true" + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}-oauth2.rule=Host(`oauth2-${VHOST}`)" + - "traefik.http.routers.${COMPOSE_PROJECT_NAME}-oauth2.tls.certresolver=letsencrypt" + +networks: + blog-network: + traefik: + name: traefik + external: true diff --git a/compose-parent.yaml b/compose-parent.yaml new file mode 100644 index 0000000..03ae2ab --- /dev/null +++ b/compose-parent.yaml @@ -0,0 +1,40 @@ +services: + web: + build: + context: . + restart: always + ports: + - "8080:8080" + + db: + image: mariadb:latest + restart: always + environment: + MARIADB_RANDOM_ROOT_PASSWORD: "yes" + MARIADB_ROOT_HOST: "localhost" + MARIADB_DATABASE: "branch" + MARIADB_USER: "branch" + MARIADB_PASSWORD: "branch" + healthcheck: + test: ["CMD", "healthcheck.sh", "--connect"] + start_period: 5s + interval: 3s + timeout: 1s + retries: 5 +# volumes: +# - type: bind +# source: ./db/ +# target: /docker-entrypoint-initdb.d/ +# read_only: true + + oauth2: + build: + context: https://github.com/dsv-su/toker.git + dockerfile: embedded.Dockerfile + restart: always + ports: + - '59999:8080' + environment: + - CLIENT_ID=blog + - CLIENT_SECRET=s3cr3t + diff --git a/compose.yaml b/compose.yaml index 813710a..e356310 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,43 +1,21 @@ services: web: - build: - context: . - depends_on: - db: - condition: service_healthy - restart: always - ports: - - "8080:8080" + extends: + file: compose-parent.yaml + service: web + environment: + - OAUTH2_AUTHORIZATION_URI=http://localhost:59999/authorize # exposed port since browser has to access + - OAUTH2_TOKEN_URI=http://oauth2:8080/exchange # inside the docker network + - OAUTH2_USER_INFO_URI=http://oauth2:8080/verify db: - image: mariadb:latest - restart: always - environment: - MARIADB_RANDOM_ROOT_PASSWORD: "yes" - MARIADB_ROOT_HOST: "localhost" - MARIADB_DATABASE: "branch" - MARIADB_USER: "branch" - MARIADB_PASSWORD: "branch" - healthcheck: - test: ["CMD", "healthcheck.sh", "--connect"] - start_period: 5s - interval: 3s - timeout: 1s - retries: 5 - volumes: - - type: bind - source: ./db/ - target: /docker-entrypoint-initdb.d/ - read_only: true + extends: + file: compose-parent.yaml + service: db oauth2: - build: - context: https://github.com/dsv-su/toker.git - dockerfile: embedded.Dockerfile - restart: always - ports: - - '59999:8080' + extends: + file: compose-parent.yaml + service: oauth2 environment: - - CLIENT_ID=blog - - CLIENT_SECRET=s3cr3t - CLIENT_REDIRECT_URI=http://localhost:8080/login/oauth2/code/local diff --git a/mvnw b/mvnw old mode 100644 new mode 100755 diff --git a/src/main/java/se/su/dsv/branchdeploytesting/BlogApplication.java b/src/main/java/se/su/dsv/branchdeploytesting/BlogApplication.java index 0dd3dd9..ac6d1ff 100644 --- a/src/main/java/se/su/dsv/branchdeploytesting/BlogApplication.java +++ b/src/main/java/se/su/dsv/branchdeploytesting/BlogApplication.java @@ -2,11 +2,14 @@ package se.su.dsv.branchdeploytesting; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; +import org.springframework.core.Ordered; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.filter.ForwardedHeaderFilter; @SpringBootApplication @EnableWebSecurity @@ -23,4 +26,15 @@ public class BlogApplication { return http.build(); } + /** + * Spring runs on HTTP and is protected by a HTTPS proxy. + * This filter takes the `X-Forwarded-*` headers and updates the request to reflect the original HTTP request. + */ + @Bean + public FilterRegistrationBean forwardedHeaderFilter() { + var filterRegistrationBean = new FilterRegistrationBean<>(new ForwardedHeaderFilter()); + filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); + return filterRegistrationBean; + } + } diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml index 52d5d44..78c648c 100644 --- a/src/main/resources/application-docker.yml +++ b/src/main/resources/application-docker.yml @@ -8,9 +8,9 @@ spring: client: provider: embedded-toker: - authorization-uri: http://localhost:59999/authorize # exposed port since browser has to access - token-uri: http://oauth2:8080/exchange # inside the docker network - user-info-uri: http://oauth2:8080/verify + authorization-uri: ${OAUTH2_AUTHORIZATION_URI} + token-uri: ${OAUTH2_TOKEN_URI} + user-info-uri: ${OAUTH2_USER_INFO_URI} user-name-attribute: sub registration: local: