Skip to content

Commit d096dd5

Browse files
authored
Merge pull request #276 from yahonda/add-devcontainer
Add devcontainer environment and CI
2 parents e5d3970 + 0c881e3 commit d096dd5

6 files changed

Lines changed: 165 additions & 0 deletions

File tree

.devcontainer/Dockerfile

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
FROM mcr.microsoft.com/devcontainers/base:trixie
2+
3+
# Install libaio1t64 and provide a libaio.so.1 symlink for Oracle Instant Client
4+
# Install rlwrap for readline support in sqlplus
5+
RUN rm -f /etc/apt/sources.list.d/yarn.list \
6+
&& apt-get update \
7+
&& apt-get install -y libaio1t64 rlwrap \
8+
&& rm -rf /var/lib/apt/lists/* \
9+
&& DEB_HOST_MULTIARCH="$(dpkg-architecture -qDEB_HOST_MULTIARCH)" \
10+
&& ln -sf /usr/lib/${DEB_HOST_MULTIARCH}/libaio.so.1t64 \
11+
/usr/lib/${DEB_HOST_MULTIARCH}/libaio.so.1 \
12+
&& echo "alias sqlplus='rlwrap sqlplus'" >> /etc/bash.bashrc
13+
14+
# Create directory structure for Oracle
15+
RUN mkdir -p /opt/oracle
16+
17+
# Download and install Oracle Instant Client based on architecture.
18+
# x86_64 uses Oracle's version-less "always latest" URLs; arm64 must pin a
19+
# version because Oracle does not publish version-less arm64 zips.
20+
WORKDIR /tmp
21+
RUN ARCH=$(uname -m) && \
22+
if [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then \
23+
IC_VERSION="23.26.1.0.0"; \
24+
IC_PATH="2326100"; \
25+
BASE_URL="https://download.oracle.com/otn_software/linux/instantclient/${IC_PATH}"; \
26+
BASIC="instantclient-basic-linux.arm64-${IC_VERSION}.zip"; \
27+
SDK="instantclient-sdk-linux.arm64-${IC_VERSION}.zip"; \
28+
SQLPLUS="instantclient-sqlplus-linux.arm64-${IC_VERSION}.zip"; \
29+
else \
30+
BASE_URL="https://download.oracle.com/otn_software/linux/instantclient"; \
31+
BASIC="instantclient-basic-linuxx64.zip"; \
32+
SDK="instantclient-sdk-linuxx64.zip"; \
33+
SQLPLUS="instantclient-sqlplus-linuxx64.zip"; \
34+
fi && \
35+
wget -q "${BASE_URL}/${BASIC}" \
36+
&& wget -q "${BASE_URL}/${SDK}" \
37+
&& wget -q "${BASE_URL}/${SQLPLUS}" \
38+
&& unzip -qo "${BASIC}" \
39+
&& unzip -qo "${SDK}" \
40+
&& unzip -qo "${SQLPLUS}" \
41+
&& mv instantclient_*/ /opt/oracle/instantclient \
42+
&& rm -f instantclient-*.zip
43+
44+
# Set Oracle environment variables
45+
ENV ORACLE_HOME=/opt/oracle/instantclient \
46+
LD_LIBRARY_PATH=/opt/oracle/instantclient:$LD_LIBRARY_PATH \
47+
PATH=/opt/oracle/instantclient:$PATH
48+
49+
# Switch to vscode user
50+
USER vscode
51+
52+
# Set working directory
53+
WORKDIR /workspaces/ruby-plsql

.devcontainer/devcontainer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "Ruby PL/SQL",
3+
"dockerComposeFile": "docker-compose.yml",
4+
"service": "app",
5+
"workspaceFolder": "/workspaces/ruby-plsql",
6+
"features": {
7+
"ghcr.io/rails/devcontainer/features/ruby:2": {
8+
"version": "4.0.3"
9+
}
10+
},
11+
"customizations": {
12+
"vscode": {
13+
"extensions": [
14+
"shopify.ruby-lsp"
15+
]
16+
}
17+
},
18+
"initializeCommand": "docker pull gvenzl/oracle-free:latest",
19+
"postCreateCommand": "bash .devcontainer/postCreateCommand.sh",
20+
"remoteEnv": {
21+
"DATABASE_NAME": "FREEPDB1",
22+
"DATABASE_SYS_PASSWORD": "Oracle18",
23+
"NLS_LANG": "American_America.AL32UTF8",
24+
"TNS_ADMIN": "/workspaces/ruby-plsql/ci/network/admin",
25+
"TWO_TASK": "FREEPDB1"
26+
},
27+
"remoteUser": "vscode",
28+
"mounts": [
29+
"source=${localWorkspaceFolder}/.bundle,target=/home/vscode/.bundle,type=bind,consistency=delegated"
30+
]
31+
}

.devcontainer/docker-compose.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
services:
2+
app:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile
6+
volumes:
7+
- ../..:/workspaces:cached
8+
command: sleep infinity
9+
network_mode: service:oracle
10+
11+
oracle:
12+
image: gvenzl/oracle-free:latest
13+
ports:
14+
- "1521:1521"
15+
environment:
16+
TZ: Europe/Riga
17+
ORACLE_PASSWORD: Oracle18
18+
healthcheck:
19+
test: ["CMD", "healthcheck.sh"]
20+
interval: 10s
21+
timeout: 5s
22+
retries: 10
23+
volumes:
24+
- oracle-data:/opt/oracle/oradata
25+
26+
volumes:
27+
oracle-data:

.devcontainer/postCreateCommand.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
gem update --system
6+
bundle install
7+
8+
echo "Waiting for Oracle to be ready..."
9+
oracle_ready=false
10+
for i in $(seq 1 30); do
11+
if echo "exit" | sqlplus -s "system/${DATABASE_SYS_PASSWORD}@${DATABASE_NAME}" > /dev/null 2>&1; then
12+
oracle_ready=true
13+
break
14+
fi
15+
echo "Attempt $i/30 failed, retrying in 10s..."
16+
sleep 10
17+
done
18+
if [ "$oracle_ready" != "true" ]; then
19+
echo "Oracle did not become ready after 30 attempts; aborting container setup." >&2
20+
exit 1
21+
fi
22+
23+
ci/setup_accounts.sh
24+
25+
echo "Dev container setup complete. You are ready to start developing ruby-plsql!"

.github/workflows/devcontainer.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: devcontainer
2+
3+
on:
4+
schedule:
5+
- cron: "0 6 1 * *" # 1st of every month at 6:00 AM UTC
6+
workflow_dispatch:
7+
8+
env:
9+
RUBYOPT: "-w"
10+
11+
jobs:
12+
test:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v6
16+
17+
- name: Ensure .bundle mount source exists
18+
run: mkdir -p .bundle
19+
20+
- name: Boot dev container and run tests
21+
uses: devcontainers/ci@v0.3
22+
with:
23+
runCmd: |
24+
uname -a
25+
lsb_release -a
26+
ruby --version
27+
bundle exec rake spec
28+
bundle exec rubocop

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ source "https://rubygems.org"
22

33
group :development do
44
gem "rspec_junit_formatter"
5+
gem "rdoc"
56
end
67

78
group :rubocop do

0 commit comments

Comments
 (0)