Skip to content
Merged
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
65 changes: 59 additions & 6 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,64 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# Dependabot configuration for Branch Newspaper
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: "" # See documentation for possible values
directory: "/" # Location of package manifests
# Elixir/Mix dependencies
- package-ecosystem: "mix"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "elixir"
commit-message:
prefix: "deps(mix):"
groups:
phoenix:
patterns:
- "phoenix*"
- "plug*"
ecto:
patterns:
- "ecto*"
dev-deps:
patterns:
- "credo"
- "dialyxir"
- "sobelow"
- "ex_doc"
update-types:
- "minor"
- "patch"

# GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci(actions):"

# npm dependencies (if assets use npm)
- package-ecosystem: "npm"
directory: "/assets"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "javascript"
commit-message:
prefix: "deps(npm):"
ignore:
# Tailwind and esbuild are managed by Mix
- dependency-name: "tailwindcss"
- dependency-name: "esbuild"
167 changes: 167 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
name: CI

on:
push:
branches: [main, master, develop]
tags: ['v*']
pull_request:
branches: [main, master]
workflow_dispatch:

env:
MIX_ENV: test
ELIXIR_VERSION: '1.15.7'
OTP_VERSION: '26.2'

jobs:
lint:
name: Lint & Format
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: ${{ env.ELIXIR_VERSION }}
otp-version: ${{ env.OTP_VERSION }}

- name: Cache deps
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Install dependencies
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get

- name: Run lint checks
run: ./ci-scripts/lint.sh

test:
name: Test (Elixir ${{ matrix.elixir }} / OTP ${{ matrix.otp }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# Primary supported version
- elixir: '1.15.7'
otp: '26.2'
# Latest versions
- elixir: '1.16.0'
otp: '26.2'
# Minimum supported version
- elixir: '1.15.0'
otp: '25.3'

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: ${{ matrix.elixir }}
otp-version: ${{ matrix.otp }}

- name: Cache deps
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}-

- name: Install dependencies
run: |
mix local.hex --force
mix local.rebar --force
mix deps.get

- name: Setup test environment
run: ./ci-scripts/setup.sh

- name: Run tests
run: ./ci-scripts/test.sh

build:
name: Build Release
runs-on: ubuntu-latest
needs: [lint, test]
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
env:
MIX_ENV: prod

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Elixir
uses: erlef/setup-beam@v1
with:
elixir-version: ${{ env.ELIXIR_VERSION }}
otp-version: ${{ env.OTP_VERSION }}

- name: Cache deps
uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-prod-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-prod-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-

- name: Build release
run: ./ci-scripts/build.sh

- name: Upload release artifact
uses: actions/upload-artifact@v4
with:
name: branch-newspaper-release
path: _build/prod/rel/branch_newspaper/
if-no-files-found: warn

mirror-to-gitlab:
name: Mirror to GitLab
runs-on: ubuntu-latest
needs: [test]
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup SSH for GitLab
env:
GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$GITLAB_SSH_KEY" > ~/.ssh/gitlab_key
chmod 600 ~/.ssh/gitlab_key
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts
cat >> ~/.ssh/config << EOF
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_key
StrictHostKeyChecking no
EOF

- name: Push to GitLab
env:
GITLAB_URL: git@gitlab.com:maa-framework/3-applications/branch-newspaper.git
run: ./ci-scripts/mirror-push.sh
152 changes: 152 additions & 0 deletions .github/workflows/mirror-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
name: Mirror Sync

on:
push:
branches: ['**']
tags: ['**']
delete:
# Trigger on branch/tag deletion to sync deletions
workflow_dispatch:
inputs:
full_sync:
description: 'Perform full mirror sync (all branches and tags)'
required: false
default: 'false'
type: boolean

jobs:
mirror-push:
name: Push to GitLab Mirror
runs-on: ubuntu-latest
# Only run on the main repo, not forks
if: github.repository == 'hyperpolymath/branch-newspaper'

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup SSH for GitLab
env:
GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }}
run: |
if [ -z "$GITLAB_SSH_KEY" ]; then
echo "ERROR: GITLAB_SSH_KEY secret is not set"
echo "Please add a deploy key to GitLab and store the private key as a GitHub secret"
exit 1
fi

mkdir -p ~/.ssh
echo "$GITLAB_SSH_KEY" > ~/.ssh/gitlab_key
chmod 600 ~/.ssh/gitlab_key
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts

cat >> ~/.ssh/config << EOF
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_key
StrictHostKeyChecking no
EOF

- name: Configure Git
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"

- name: Add GitLab remote
run: |
git remote add gitlab git@gitlab.com:maa-framework/3-applications/branch-newspaper.git || true
git remote set-url gitlab git@gitlab.com:maa-framework/3-applications/branch-newspaper.git

- name: Push current ref to GitLab
if: github.event_name == 'push'
run: |
REF="${GITHUB_REF}"
echo "Pushing ref: $REF"

# Retry logic with exponential backoff
MAX_RETRIES=4
RETRY_DELAY=2

for i in $(seq 1 $MAX_RETRIES); do
if git push gitlab "$REF" --force-with-lease; then
echo "Successfully pushed $REF"
exit 0
fi
if [ $i -lt $MAX_RETRIES ]; then
echo "Push failed, retrying in ${RETRY_DELAY}s..."
sleep $RETRY_DELAY
RETRY_DELAY=$((RETRY_DELAY * 2))
fi
done

echo "Failed to push after $MAX_RETRIES attempts"
exit 1

- name: Full mirror sync
if: github.event.inputs.full_sync == 'true' || github.event_name == 'workflow_dispatch'
run: |
echo "Performing full mirror sync..."

# Push all branches
git push gitlab --all --force-with-lease

# Push all tags
git push gitlab --tags --force

echo "Full sync complete!"

- name: Handle deletion
if: github.event_name == 'delete'
run: |
REF_TYPE="${{ github.event.ref_type }}"
REF_NAME="${{ github.event.ref }}"

echo "Handling deletion of $REF_TYPE: $REF_NAME"

if [ "$REF_TYPE" = "branch" ]; then
git push gitlab --delete "$REF_NAME" || echo "Branch may already be deleted"
elif [ "$REF_TYPE" = "tag" ]; then
git push gitlab --delete "refs/tags/$REF_NAME" || echo "Tag may already be deleted"
fi

verify-mirror:
name: Verify Mirror Sync
runs-on: ubuntu-latest
needs: mirror-push
if: always() && needs.mirror-push.result == 'success'

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup SSH for GitLab
env:
GITLAB_SSH_KEY: ${{ secrets.GITLAB_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$GITLAB_SSH_KEY" > ~/.ssh/gitlab_key
chmod 600 ~/.ssh/gitlab_key
ssh-keyscan gitlab.com >> ~/.ssh/known_hosts

cat >> ~/.ssh/config << EOF
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/gitlab_key
StrictHostKeyChecking no
EOF

- name: Add GitLab remote
run: |
git remote add gitlab git@gitlab.com:maa-framework/3-applications/branch-newspaper.git || true

- name: Verify mirror sync
env:
SOURCE_REMOTE: origin
DEST_REMOTE: gitlab
run: ./ci-scripts/verify-mirror.sh
Loading
Loading