Running deploy in CI
cordless deploy was built for interactive use first, but nothing about it actually depends on a
terminal. There’s no config to unlock, no separate “CI mode”, just three things lining up: AWS
credentials, your Discord credentials, and no confirmation prompts blocking the run.
Confirmation prompts
Section titled “Confirmation prompts”deploy itself never prompts for anything, there’s no input() call anywhere in it, so it was
already safe to run non-interactively. The only commands that ask anything are cordless init
(one required question about endpoint, skip it with --endpoint function_url or
--endpoint api_gateway) and cordless destroy (pass --yes to skip its confirmation).
AWS credentials
Section titled “AWS credentials”cordless doesn’t implement its own credential handling: deploy/destroy construct a plain
boto3.Session(), so they pick up whatever boto3’s standard credential chain finds: environment
variables, a shared credentials file, an IAM role attached to the runner, or short-lived
credentials from OIDC federation. In GitHub Actions, that means
aws-actions/configure-aws-credentials
already works with zero cordless-specific setup: it assumes a role via OIDC and exports
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN as environment variables, which
cordless deploy then just inherits:
permissions: id-token: write # required for OIDC contents: read
steps: - uses: actions/checkout@v4 - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/cordless-deploy aws-region: us-east-1 - run: pip install cordless - run: cordless deploy --registerNo long-lived access keys stored as repository secrets, and no cordless flag needed to opt into it. See the IAM permissions section for exactly what to scope that role down to.
Discord credentials
Section titled “Discord credentials”DISCORD_PUBLIC_KEY and DISCORD_BOT_TOKEN fall back to the process environment when they
aren’t set some other way, so exporting them as CI secrets is enough, no .env file needed (and
you shouldn’t commit one, that would mean checking in secrets):
- run: cordless deploy --register env: DISCORD_PUBLIC_KEY: ${{ secrets.DISCORD_PUBLIC_KEY }} DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}This fallback is lowest priority: a .env file, cordless.toml’s [deploy.env], or an explicit
--env KEY=VALUE flag all still win if present, same as they do locally. It only fills in what
nothing else already set, so it’s safe to leave real environment variables exported in a shell
without them silently overriding a project’s own .env during local development.
Anything else your bot needs baked into its Lambda environment (a STRIPE_KEY, a bucket name,
whatever) isn’t covered by this fallback, those go through [deploy.env] in cordless.toml or
repeated --env KEY=VALUE flags, same as they do outside CI.
Putting it together
Section titled “Putting it together”name: Deploy boton: push: branches: [main]
permissions: id-token: write contents: read
jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::123456789012:role/cordless-deploy aws-region: us-east-1 - run: pip install cordless - run: cordless deploy --register env: DISCORD_PUBLIC_KEY: ${{ secrets.DISCORD_PUBLIC_KEY }} DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN }}deploy is safe to run on every push: creating/updating an existing function is idempotent, and a
run that fails partway through leaves already-created resources in place rather than a
half-torn-down state. Rerunning it picks up wherever it stopped instead of erroring on things
that already exist.
